Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 21
CRAP
0.00% covered (danger)
0.00%
0 / 127
Synonyms
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 21
2162.00
0.00% covered (danger)
0.00%
0 / 127
 __construct
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 4
 is_inDictionary
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 5
 get_originalName
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 5
 get_original_id
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 5
 addSynonymsArray
0.00% covered (danger)
0.00%
0 / 1
42.00
0.00% covered (danger)
0.00%
0 / 10
 addSynonym
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 dbLoadSynonyms
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 7
 dbAddSynonymsArray
0.00% covered (danger)
0.00%
0 / 1
90.00
0.00% covered (danger)
0.00%
0 / 26
 queryUpdateOriginal
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 5
 queryUpdateOriginalById
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 5
 queryDeleteSynonym
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 5
 queryDeleteOriginal
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 5
 queryDeleteOriginal_id
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 5
 dbReadSynonymOriginal
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 dbReadSynonymOriginal_id
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 3
 queryFromWhere
0.00% covered (danger)
0.00%
0 / 1
20.00
0.00% covered (danger)
0.00%
0 / 7
 dbCreateSynonymTable
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 2
 standardizeWord
0.00% covered (danger)
0.00%
0 / 1
2.00
0.00% covered (danger)
0.00%
0 / 1
 registerSynonym
0.00% covered (danger)
0.00%
0 / 1
6.00
0.00% covered (danger)
0.00%
0 / 10
 registerVariants
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 6
 parent_tableParentDefault
0.00% covered (danger)
0.00%
0 / 1
12.00
0.00% covered (danger)
0.00%
0 / 5
<?php
/** @noinspection SqlNoDataSourceInspection */
/** @noinspection SqlResolve */
namespace ia\Lib;
use ia\Sql\Mysql\IaMysqli;
use ia\Sql\Mysql\MultipleInsert;
use ia\Sql\Mysql\SqlBuilder;
use ia\Util\Str;
class Synonyms {
    private $tryPluralSingular = true;
    private $parent_id;
    private $parent_table;
    private $thesaurus = [];
    private $thesaurus_id = [];
    private $dbTableName = 'ia_synonyms';
    /**
     * Synonyms::__construct()
     *
     * @param bool $tryPluralSingular
     * @param string $parent_id
     * @param string $parent_table
     * @return
     */
    public function __construct($tryPluralSingular = true, string $parent_id = '', string $parent_table = '') {
        $this->tryPluralSingular = $tryPluralSingular;
        $this->parent_id = $parent_id;
        $this->parent_table = $parent_table;
    }
    /* ///// use synonyms ///// */
        /**
         * True if word $alternativeName mactches to an original name
         *
         * @param string $alternativeName
         * @param string|null $parent_id
         * @param string|null $parent_table
         * @return bool true $alternativeName exists in database
         */
        public function is_inDictionary(string $alternativeName, $parent_id = null, $parent_table = null) {
            $this->parent_tableParentDefault($parent_id, $parent_table);
            $standardized = $this->standardizeWord($alternativeName);
            if(isset($this->thesaurus[$parent_table][$parent_id][$standardized])) {
                return true;
            }
            return false;
        }
        /**
         * for $alternativeName return the original name or null if not regestered
         *
         * @param string $alternativeName
         * @param string|null $parent_id
         * @param string|null $parent_table
         * @return string|null
         */
        public function get_originalName($alternativeName, $parent_id = null, $parent_table = null) {
            $this->parent_tableParentDefault($parent_id, $parent_table);
             $standardized = $this->standardizeWord($alternativeName);
             if(isset($this->thesaurus[$parent_table][$parent_id][$standardized])) {
                return $this->thesaurus[$parent_table][$parent_id][$standardized];
             }
             return null;
        }
        /**
         * Sfor $alternativeName return the original_id or null if not regestered
         *
         * @param string $alternativeName
         * @param string|null $parent_id
         * @param string|null $parent_table
         * @return string|null
         */
        public function get_original_id(string $alternativeName, $parent_id = null, $parent_table = null) {
            $this->parent_tableParentDefault($parent_id, $parent_table);
            $standardized = $this->standardizeWord($alternativeName);
            if(isset($this->thesaurus_id[$parent_table][$parent_id][$standardized])) {
                return $this->thesaurus_id[$parent_table][$parent_id][$standardized];
            }
            return null;
        }
    /* ///// Add synonyms manually not to be stored in db ///// */
        /**
         *
         *
         * @param array $synonyms ['tax Id'=>'rfc', 'vat number'=>'rfc']
         * @param string|null $parent_id
         * @param string|null $parent_table
         * @return
         */
        public function addSynonymsArray(array $synonyms, $parent_id = null, $parent_table = null) {
            $this->parent_tableParentDefault($parent_id, $parent_table);
            foreach($synonyms as $alternativeName => $original) {
                if(is_array($original)) {
                    $name = $original['original'];
                    $original_id = empty($original['original_id']) ? null : $original['original_id'];
                    $useParent_id = empty($original['parent_id']) ? $parent_id : $original['parent_id'];
                    $useTheme = empty($original['parent_table']) ? $parent_table : $original['parent_table'];
                    $this->registerSynonym($name, $original, $original_id, $useParent_id, $useTheme);
                } else {
                    $this->registerSynonym($alternativeName, $original, null, $parent_id, $parent_table);
                }
            }
        }
        /**
         * Synonyms::addSynonym()
         *
         * @param string $alternativeName
         * @param string $original
         * @param string $original_id
         * @param string|null $parent_id
         * @param string|null $parent_table
         * @return
         */
        public function addSynonym(string $alternativeName, string $original, $original_id = null, $parent_id = null,
                                   $parent_table = null) {
            $this->parent_tableParentDefault($parent_id, $parent_table);
            $this->registerSynonym($alternativeName, $original, $original_id, $parent_id, $parent_table);
        }
    /* ///// Synonims db interface  ///// */
        /**
         * @param IaMysqli $db
         * @param string $parent_id
         * @param string $parent_table
         * @return bool true success, false failure
         * @throws \ia\Sql\Mysql\IacSqlException
         */
        public function dbLoadSynonyms($db, $parent_id, $parent_table) {
            $this->thesaurus = $db->selectArrayMultiKey(
              'SELECT parent_table, parent_id, synonym, original ' . $this->queryFromWhere($parent_id, $parent_table),
              3
            );
            $this->thesaurus_id = $db->selectArrayMultiKey(
                'SELECT parent_table, parent_id, synonym, original_id ' . $this->queryFromWhere($parent_id, $parent_table),
                3
            );
            return $this->thesaurus !== false && $this->thesaurus_id !== false;
        }
        /**
         * Synonyms::dbAddSynonymsArray()
         *
         * @param IaMysqli $db
         * @param array $synonyms
         * @param string|null $parent_id
         * @param string|null $parent_table
         * @return true ok, false db error
         */
        public function dbAddSynonymsArray($db, array $synonyms, $parent_id = null, $parent_table = null) {
            $notInserted = [];
            $dbInsert = new MultipleInsert($db,
                "INSERT INTO $this->dbTableName(parent_table, parent_id,synonym,original_id,original,registered)",
                " ON DUPLICATE KEY UPDATE original = VALUES(original), original_id = VALUES(original_id)"
            );
            $this->parent_tableParentDefault($parent_id, $parent_table);
            foreach($synonyms as $alternativeName => $original) {
                if(is_array($original)) {
                    $ins = [
                        'parent_table' => empty($original['parent_table']) ? $parent_table : $original['parent_table'],
                        'parent_id' => empty($original['parent_id']) ? $parent_id : $original['parent_id'],
                        'synonym' => empty($original['synonym']) ? $alternativeName : $original['synonym'],
                        'original_id' => empty($original['original_id']) ? null : $original['original_id'],
                        'original' => empty($original['original']) ? null : $original['original'],
                        'registered' => 'NOW()',
                    ];
                } else {
                    $ins = [
                        'parent_table' => $parent_table,
                        'parent_id' => $parent_id ,
                        'synonym' => $alternativeName,
                        'original_id' => null,
                        'original' => $original,
                        'registered' => 'NOW()',
                    ];
                }
                if(empty($ins['original'])) {
                    $notInserted[] = $ins;
                } else {
                    $dbInsert->valuesArray($ins);
                }
            }
            $dbInsert->insertNow();
            return [
                'ok' => $dbInsert->get_insertsErrorsNum() === false,
                'numOk'=>$dbInsert->get_insertsOkNum(),
                'numSqlErrors'=>$dbInsert->get_insertsErrorsNum(),
                'recordErrors'=>$notInserted
            ];
        }
        /**
         * Synonyms::queryUpdateOriginal()
         *
         * @param string|null $parent_table
         * @param string|null $parent_id
         * @param string $original
         * @param string $newOriginal
         * @return bool true ok, false db error
         */
        public static function queryUpdateOriginal($parent_table, $parent_id, $original, $newOriginal) {
            $sqlBuilder = new SqlBuilder();
            return $sqlBuilder->update(
                $this->dbTableName,
                ['original' => $newOriginal],
                ['parent_table' => $parent_table, 'parent_id' => $parent_id, 'original' => $original]
            );
        }
        /**
         * Synonyms::queryUpdateOriginalById()
         *
         * @param string|null $parent_table
         * @param string|null $parent_id
         * @param string $original_id
         * @param string $newOriginal
         * @return bool true ok, false db error
         */
        public static function queryUpdateOriginalById($parent_table, $parent_id, $original_id, $newOriginal) {
            $sqlBuilder = new SqlBuilder();
            return $db->query($sqlBuilder->update(
                $this->dbTableName,
                ['original' => $newOriginal],
                ['parent_table' => $parent_table, 'parent_id' => $parent_id, 'original_id' => $original_id]
            ));
        }
        /**
         * Synonyms::queryDeleteSynonym()
         *
         * @param string|null $parent_table
         * @param string|null $parent_id
         * @param string $synonym
         * @return bool true ok, false db error
         */
        public static function queryDeleteSynonym($parent_table, $parent_id, $synonym) {
            $sqlBuilder = new SqlBuilder();
            return " DELETE FROM $this->dbTableName WHERE " . $sqlBuilder->where([
                'parent_table' => $parent_table,
                'parent_id' => $parent_id,
                'synonym' => $synonym
            ]);
        }
        /**
         * Synonyms::queryDeleteOriginal()
         *
         * @param string|null $parent_table
         * @param string|null $parent_id
         * @param string $original
         * @return bool true ok, false db error
         */
        public static function queryDeleteOriginal($parent_table, $parent_id, $original) {
            $sqlBuilder = new SqlBuilder();
            return " DELETE FROM $this->dbTableName WHERE " . $sqlBuilder->where([
                'parent_table' => $parent_table,
                'parent_id' => $parent_id,
                'original' => $original
            ]);
        }
        /**
         * Synonyms::queryDeleteOriginal_id()
         *
         * @param string|null $parent_table
         * @param string|null $parent_id
         * @paramv $original_id
         * @return bool true ok, false db error
         */
        public static function queryDeleteOriginal_id($parent_table, $parent_id, $original_id) {
            $sqlBuilder = new SqlBuilder();
            return " DELETE FROM $this->dbTableName WHERE " . $sqlBuilder->where([
                'parent_table' => $parent_table,
                'parent_id' => $parent_id,
                'original_id' => $original_id
            ]);
        }
        /**
         * ['synonym'=>'original',...]
         *
         * @param IaMysqli $db
         * @param string $parent_id
         * @param string $parent_table
         * @return array|bool ['synonym'=>'original',...] or false on error
         * @throws \ia\Sql\Mysql\IacSqlException
         */
        public function dbReadSynonymOriginal($db, $parent_id = null, $parent_table = null) {
            $this->parent_tableParentDefault($parent_id, $parent_table);
            return $db->selectKeyValue("SELECT synonym, original ".$this->queryFromWhere($parent_id, $parent_table).
                " ORDER BY original, synonym");
        }
        /**
         * ['synonym'=>'original_id',...]
         *
         * @param IaMysqli $db
         * @param string $parent_id
         * @param string $parent_table
         * @return array|bool ['synonym'=>'original_id',...] or false on error
         * @throws \ia\Sql\Mysql\IacSqlException
         */
        public function dbReadSynonymOriginal_id($db, $parent_id = null, $parent_table = null) {
            $this->parent_tableParentDefault($parent_id, $parent_table);
            return $db->selectKeyValue("SELECT synonym, original_id ".$this->queryFromWhere($parent_id, $parent_table).
                " ORDER BY original, synonym");
        }
        /**
         * Synonyms::queryFromWhere()
         *
         * @param string|null $parent_id
         * @param string|null $parent_table
         * @return string
         */
        private function queryFromWhere($parent_id = null, $parent_table = null) {
            $where = [];
            if($parent_table !== null) {
                $where['parent_table'] = $parent_table;
            }
            if($parent_id !== null) {
                $where['parent_id'] = $parent_id;
            }
            $sqlBuilder = new SqlBuilder();
            return " FROM $this->dbTableName " . ($where === [] ? '' : ' WHERE ' . $sqlBuilder->where($where) );
        }
        /**
         * Synonyms::dbCreateSynonymTable()
         *
         * @param IaMysqli $db
         * @return bool
         */
        private function dbCreateSynonymTable($db) {
            $sql = <<< CREATETABLETAG
            CREATE TABLE IF NOT EXISTS $this->dbTableName (
                parent_table VARCHAR(191) NOT NULL COMMENT 'Category or table for parent_id',
                parent_id VARCHAR(64) NOT NULL COMMENT 'If parent_table is a table id for row, CRUD for parent table must synch this value',
                synonym VARCHAR(1024) NOT NULL COMMENT 'Alternative name for the original word, standarized',
                original_id VARCHAR(64) NULL DEFAULT NULL COMMENT ' CRUD for original's table must synch this value',
                original VARCHAR(1024) NOT NULL COMMENT 'Synonim for this word',
                registered DATETIME NOT NULL,
                PRIMARY KEY(parent_table, parent_id, synonym),
                KEY by_original(parent_table, parent_id, original, synonym),
                KEY by_original(parent_table, parent_id, original_id, synonym)
            ) ENGINE=Innodb DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Synonim to original word'
CREATETABLETAG;
            return $db->query($sql);
        }
    /* ///// helper functions ///// */
        /**
         * Synonyms::standardizeWord()
         *
         * @param string $word
         * @return string
         */
        private function standardizeWord($word) {
            return Str::standardize($word);
        }
        /**
         * Synonyms::registerSynonym()
         *
         * @param string $alternativeName
         * @param string $original
         * @param string|null $original_id
         * @param string|null $parent_id
         * @param string|null $parent_table
         * @return void
         */
        private function registerSynonym(string $alternativeName, string $original, $original_id, $parent_id, $parent_table) {
            $oficialStandardized = $this->standardizeWord($original);
            if(!isset($this->thesaurus[$parent_table][$parent_id][$oficialStandardized])) {
                $this->thesaurus[$parent_table][$parent_id][$oficialStandardized] = $original;
                $this->thesaurus_id[$parent_table][$parent_id][$oficialStandardized] = $original_id;
                $this->registerVariants($original, $original, $original_id, $parent_id, $parent_table);
            }
            $standardized = $this->standardizeWord($alternativeName);
            $this->thesaurus[$parent_table][$parent_id][$standardized] = $original;
            $this->thesaurus_id[$parent_table][$parent_id][$standardized] = $original_id;
            $this->registerVariants($alternativeName, $original, $original_id, $parent_id, $parent_table);
        }
        /**
         * Synonyms::registerVariants()
         *
         * @param string $alternativeName
         * @param string $original
         * @param string $original_id
         * @param string|null $parent_id
         * @param string|null $parent_table
         * @return void
         */
        private function registerVariants($alternativeName, $original, $original_id, $parent_id,
                                            $parent_table) {
            if($this->tryPluralSingular) {
                foreach(iaPalabra::variants($alternativeName) as $variant) {
                    $standardized = $this->standardizeWord($variant);
                    $this->thesaurus[$parent_table][$parent_id][$standardized] = $original;
                    $this->thesaurus_id[$parent_table][$parent_id][$standardized] = $original_id;
                }
            }
        }
        /**
         * Set parent_id and parent_table to the default when instance was created
         *
         * @param string|null &$parent_id on null changes to the default when instance was created $this->parent_id
         * @param string|null &$parent_table on null changes to the default when instance was created $this->parent_table
         */
        private function parent_tableParentDefault(&$parent_id = null, &$parent_table = null) {
            if($parent_id === null) {
                $parent_id = $this->parent_id;
            }
            if($parent_table === null) {
                $parent_table = $this->parent_table;
            }
        }
}