* @since Version 1.0 */ class cMapUrls { private $module; private $mapData = array(); private $mapDataArray = array(); const type_map = 0; const type_map_url = 1; private $defaultLangId = 0; /** * Class constructor */ public function __construct() { $this->module = new cMapUrlsModule(); } /** * Function to create site map urls new array if no errors found, else return error array * * @author Mareks Keišs * @category LIB Map Urls * @param array $urls4products - lang key based array for passed site map chunks -> lang_id => array( 'l' => '/link-to-add/', 'id' => 'alias_id' ) * @param int|bool $recordId - by ref item id for storage * @param int|bool $sm_aliasID - site map alias id * @param int|bool $smu_aliasID - site map urls alias id * @param int $url_type - url type * @param int $urlChCount - url chunk count before before substring cutting of products * @return void|array containing errors */ public function checkAndCreateMapUrlsForInsert($urls4products = array(), &$recordId = 0, $sm_aliasID = false, $smu_aliasID = false, $url_type = 0, $urlChCount = 1){ $oUrl = new cUrl(); $oUrl->_endSlash = true; if(!!$urls4products && is_array($urls4products) && ($sm_aliasID || $smu_aliasID)){ // Get base urls data $baseUrl = $this->getFullUrlById($sm_aliasID, $smu_aliasID); $urlChCount = substr_count($oUrl->rmSlashesIndex(firstE($baseUrl)['url']), '/'); if(!!$baseUrl && is_array($baseUrl)){ $i = 0; $nUrl = array(); $node = array(); $itemUrls = array(); $this->mapData = array(); $mapDataLangRefId = 0; // Load all item linked data for update or insert if($recordId){ $itemUrls = $this->module->getAllSiteMapUrlsByItemId($recordId, $urlChCount); } // Loop each url chunk foreach($urls4products as $langId=>$v){ $id = 0; $parentUrl = $oUrl->rmSlashesIndex((!empty($baseUrl[$langId]['url']) ? $baseUrl[$langId]['url'] :'/dummy-link/')); if(!!$parentUrl){ $nUrl[$langId] = $this->addUrlChunk($parentUrl, $v["l"]); // Check if found & set id & ref if (!empty($itemUrls[$langId][$parentUrl])) { $id = $itemUrls[$langId][$parentUrl]['id']; $mapDataLangRefId = $itemUrls[$langId][$parentUrl]['r_id']; //pr($id, $baseUrl); } // Create new link item $node = array( 'id' => $id, 'url_fname' => $nUrl[$langId], 'url_alias_id' => $baseUrl[$langId]['map_id'], 'url_type' => $url_type, 'url_lang_ref_id' => &$mapDataLangRefId, 'url_lang_id' => $langId, 'url_item_id' => &$recordId, 'url_p_id' => 0, ); if(!!$smu_aliasID) $node['url_p_id'] = $smu_aliasID; } $this->mapData[($id ? $id : 'c' . $i++)] = $node; } // Check if found duplicates if(!!($foundUrls = $this->chkModUrlExists($nUrl, false, array_keys($this->mapData)))){ // Go through all provided links & set error array for return foreach($nUrl as $langId=>$url){ if(!in_array($url, $foundUrls)){ unset($nUrl[$langId]); } } // Send error lang links return $nUrl; } } } return false; } /** * Function to create site map urls new array if no errors found, else return error array * * @author Mareks Keišs * @category LIB Map Urls * @param array $urls4products - lang key based array for passed site map chunks -> lang_id => '/link-to-add/' * @param int|bool $recordId - by ref item id for storage * @param array|bool $sm_aliasID - site map alias id's * @param array|bool $smu_aliasID - site map urls alias id's * @param int|bool $url_type - url type * @param array|bool $baseUrlData - overwritten data array for urls -> id => array( 'language_id' => array( 'url' => '/url-to-add/', 'map_id' => 233) * @param bool $subCat - whether its has sub cat or not * @return void|array containing errors */ public function checkAndCreateMapUrlsForInsertArrayToArray( $urls4products = [], &$recordId = 0, $sm_aliasID = false, $smu_aliasID = false, $url_type = false, $baseUrlData = false, $subCat = false ) { $itemUrls = []; if (!!$urls4products && is_array($urls4products) && (!!$sm_aliasID || !!$smu_aliasID || !!$baseUrlData)) { if (!!$sm_aliasID && !is_array($sm_aliasID)) $sm_aliasID = array($sm_aliasID); if (!!$smu_aliasID && !is_array($smu_aliasID)) $smu_aliasID = array($smu_aliasID); // Get base urls data if (!!!$baseUrlData || !is_array($baseUrlData)) $baseUrlData = $this->getFullUrlById($sm_aliasID, $smu_aliasID); // Load all item linked data for update or insert if ($recordId) $itemUrls = $this->module->getAllSiteMapUrlsByItemId($recordId, $subCat ? 4 : 3); //pr([$baseUrlData, $recordId, $itemUrls]); if (!!$baseUrlData && is_array($baseUrlData)) { $i = 0; $nUrl = []; $this->mapDataArray = []; // Loop each record foreach ($baseUrlData as $subType => $langUrls) { $langUrls['mapDataLangRefId'] = 0; foreach($urls4products as $langId=>$urlChunk) { $id = 0; $mapId = 0; $parentUrl = ''; if(!empty($langUrls[$langId]['url'])){ $mapId = $langUrls[$langId]['map_id']; $parentUrl = $langUrls[$langId]['url']; } if (!!$parentUrl) { $nUrl["{$i}-{$langId}"] = $this->addUrlChunk($parentUrl, $urlChunk); //pr([$parentUrl, $itemUrls[$langId]]); // Check if found & set id & ref if (!empty($itemUrls[$langId][$parentUrl])) { $id = $itemUrls[$langId][$parentUrl]['id']; $langUrls['mapDataLangRefId'] = $itemUrls[$langId][$parentUrl]['r_id']; } // Create new link item $this->mapDataArray[($id ?: "c{$i}")] = [ 'id' => $id, 'url_p_id' => ($subType ?: 0), 'url_fname' => $nUrl["{$i}-{$langId}"], 'url_alias_id' => $mapId, 'url_type' => ($url_type ?: 0), 'url_lang_ref_id' => &$langUrls['mapDataLangRefId'], 'url_lang_id' => $langId, 'url_item_id' => &$recordId, ]; $i++; } } } //pr($this->mapDataArray); // Check if found duplicates if (!!($foundUrls = $this->chkModUrlExists($nUrl, false, array_keys($this->mapDataArray)))) { // Go through all provided links & set error array for return $errors = []; foreach ($nUrl as $key => $url) { if (in_array($url, $foundUrls)) { $p = explode('-', $key); $errors[$p[1]] = $urls4products[$p[1]]; } unset($p, $nUrl[$key]); } // Send error lang links return $errors; } } } return false; } /** * Function to update map url data & update alias ids to translation array * * @author Mareks Keišs * @category LIB Map Urls * @param array $sTranslations - translation array based on language keys -> lang_id => array( data_keys => values ) * @param string $sKey - field key to set alias id * @param bool $bUpdateChildUrls - update child urls in site_maps_urls table * @return bool */ public function updateMapUrls(&$sTranslations, $sKey, $bUpdateChildUrls = false){ if(!!$this->mapData){ // Set lang ref id foreach($this->mapData as &$v){ if(!$v['id']) break; if(!$this->defaultLangId) $this->defaultLangId = $v['url_lang_id']; if($v['url_lang_id'] == $this->defaultLangId){ $v['url_lang_ref_id'] = $v['id']; break; } } unset($v); foreach($this->mapData as &$v){ if($v['id']){ // Update children urls if($bUpdateChildUrls) $this->module->updateChildUrlsByParentId($v['id'], $v['url_fname'], $v['url_lang_id']); // update link $this->module->saveMapUrlsData($v['id'], array( 'url_fname' => $v['url_fname'], 'url_alias_id' => $v['url_alias_id'], 'url_type' => $v['url_type'], 'url_lang_ref_id' => $v['url_lang_ref_id'], 'url_p_id' => $v['url_p_id'], ), array( 'id' => $v['id'], 'url_lang_id' => $v['url_lang_id'] )); }else{ // Insert new link unset($v['id']); $v['id'] = $this->module->saveMapUrlsData(false, $v); if(!$v['url_lang_ref_id']){ $v['url_lang_ref_id'] = $v['id']; $this->module->saveMapUrlsData($v['id'], array('url_lang_ref_id' => $v['id'])); } } if(isset($sTranslations[$v['url_lang_id']][$sKey])) $sTranslations[$v['url_lang_id']][$sKey] = $v['id']; } unset($v); return true; } return false; } /** * Function to update map url data array * * @author Mareks Keišs * @category LIB Map Urls * @return bool */ public function updateMapUrlsArray(){ if(!!$this->mapDataArray){ foreach($this->mapDataArray as &$v){ $id = $v['id']; unset($v['id']); if(!!$id){ // update link $this->module->saveMapUrlsData($id, $v, array( 'id' => $id, 'url_lang_id' => $v['url_lang_id'] )); }else{ // Insert new link $id = $this->module->saveMapUrlsData(false, $v); // Update references if(!$v['url_lang_ref_id']){ $v['url_lang_ref_id'] = $id; $this->module->saveMapUrlsData($id, array('url_lang_ref_id' => $id)); } } } unset($v); return true; } return false; } /** * Function to generate & insert new sub-child urls * * @author Mareks Keišs * @category LIB Map Urls * @param array $sTranslations - translation array based on product to language keys -> prod_id => lang_id => array( data_keys => values ) * @param string $sKey - field key to set alias id * @param array $urlChunks - chunk array based on -> prod_id => language keys => url * @param array $aliasesToDelete - alias ids to delete * @param string $sUrlType - url type * @param int|bool $defLangId - default language id * @return mixed */ public function updateSubChildrenUrls(&$sTranslations, $sKey, $urlChunks, $aliasesToDelete, $sUrlType, $defLangId = false){ $this->defaultLangId = $defLangId; // Delete old urls if(!!$aliasesToDelete && is_array($aliasesToDelete) && $sUrlType){ $this->module->deleteAliasesById($aliasesToDelete, $sUrlType); } if(!!$urlChunks && is_array($urlChunks) && $sUrlType && !!$this->mapData){ // Recreate base url array $baseUrl = array(); foreach($this->mapData as $v){ $baseUrl[$v['url_lang_id']] = array( 'l' => $v['url_fname'], 'map_id' => $v['url_alias_id'], ); } $i = 0; $mapData = array(); $this->mapData = array(); // Loop each passed prod & languages creating links $nUrl = array(); foreach($urlChunks as $pId=>$prodLangs){ if(!!$prodLangs && is_array($prodLangs)){ $mapDataLangRefId = 0; foreach($prodLangs as $langId=>$url){ if(!empty($url)){ $nUrl[$i] = $this->addUrlChunk((!empty($baseUrl[$langId]['l']) ? $baseUrl[$langId]['l'] : '/dummy-sub-link/'), $url); // Create new link item $mapData[$pId][$langId] = array( 'id' => 0, 'url_fname' => $nUrl[$i], 'url_alias_id' => $baseUrl[$langId]['map_id'], 'url_type' => $sUrlType, 'url_lang_ref_id' => &$mapDataLangRefId, 'url_lang_id' => $langId, ); $i++; } } } } // Check if found duplicates if(!!($foundUrls = $this->chkModUrlExists($nUrl))){ return 'Somwhere duplicate url found'; } // Insert new ones if(!!$mapData && is_array($mapData)){ foreach ($mapData as $pId=>$langTrData){ $this->mapData = $langTrData; if(isset($sTranslations[$pId])) $this->updateMapUrls($sTranslations[$pId], $sKey); } } } return false; } /** * Function to get site map url by id * * @author Mareks Keišs * @category LIB Map Urls * @param int|array|bool $eSid - exclude site_map id * @param int|array|bool $eUid - exclude site_map_urls id * @return string - url data */ private function getFullUrlById($eSid = false, $eUid = false){ if(!!$eSid){ if(is_array($eSid)) return $this->module->getSiteMapDataArrayById($eSid); else return $this->module->getSiteMapDataById($eSid, 'p_full_url', true); }elseif(!!$eUid){ if(is_array($eUid)) return $this->module->getSiteMapUrlsDataArrayById($eUid); else return $this->module->getSiteMapUrlsDataById($eUid, 'url_fname', true); } return false; } /** * Function to check if url already exists in db * * @author Mareks Keišs * @category LIB Map Urls * @param string|array $url - search full link * @param int|array|bool $eSid - exclude site_map id * @param int|array|bool $eUid - exclude site_map_urls id * @return string - ajax request code */ public function chkModUrlExists($url, $eSid = false, $eUid = false){ if(is_string($url)) $url = array($url); // Get all found data from both tables // Array structure for keys -> 'type', 'lang_ref_id', 'id' $foundData = $this->module->getAllUrlOccurrencesInBothTables($url); //pr([$eSid, $eUid, $foundData]); // Loop data & unset unneeded if(!!$foundData && is_array($foundData)){ $id = array(0); $type = -1; if($eSid){ $type = self::type_map; $id = array_flip(is_array($eSid) ? $eSid : array($eSid)); }elseif($eUid){ $type = self::type_map_url; $id = array_flip(is_array($eUid) ? $eUid : array($eUid)); } //pr([$id, $foundData, $type]); if(isset($foundData[$type]) && !!$foundData[$type]){ // remove all ref id based data $foundData[$type] = array_diff_key($foundData[$type], $id); // Loop each base id if(!!$foundData[$type]){ foreach($foundData[$type] as $ref_id=>$v){ if(count(array_intersect_key($v, $id))){ unset($foundData[$type][$ref_id]); break; } } } if(!!!$foundData[$type]) unset($foundData[$type]); if(!empty($foundData)) return $this->array_value_recursive($foundData); } } return false; } /** * Function to add url chunk & create correct full urls * * @author Mareks Keišs * @category LIB Map Urls * @param string $baseUrl - base full url * @param string $chunk - chunk to add at the end * @param bool $lang - has language attached * @return string - url data */ private function addUrlChunk($baseUrl, $chunk, $lang = false){ if($baseUrl && $chunk){ // Replace startiong and ending slashes $chunks = explode('/', preg_replace('/^\/|\/+$/', '', $baseUrl)); // Handle language if($lang){ $lang = array_pop($chunks); $chunks[] = $chunk; $chunks[] = $lang; }else{ $chunks[] = $chunk; } if($chunks[0] == 'index') unset($chunks[0]); return '/' . implode('/', array_filter($chunks)) . '/'; } return false; } /** * Function to get all array values from depth of an array * * @author Mareks Keišs * @category LIB Map Urls * @param array $arr - array to walk * @return mixed - data gathered */ private function array_value_recursive($arr){ $vals = array(); $this->array_walk_recursive($vals, $arr); return $vals; } private function array_walk_recursive(&$vals, $arr){ if(is_array($arr)){ foreach($arr as $v) $this->array_walk_recursive($vals, $v); }else{ array_push($vals, $arr); } } }