/** * Purge urls from database (and cache) * either all automatic, or according to current * sef url list page select options as stored in * in session * @param unknown_type $type */ public function purge($type = 'auto') { // make sure we use latest user state $this->_updateContextData(); // call the appropriate sub-method to get the db query $methodName = '_getPurgeQuery' . ucfirst($type); if (is_callable(array($this, $methodName))) { $deleteQuery = $this->{$methodName}(); } else { $this->setError('Invalid method call _purge' . $type); return; } try { // then run the query $this->_db->setQuery($deleteQuery); $this->_db->shlExecute(); } catch (Exception $e) { ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); $this->setError($e->getMessage()); } // delete from cache : we delete the whole cache anyway, except for 404 pages // which are not in the cache if ($type != '404') { Sh404sefHelperCache::purge(); } // reset limit and limitstart variables, to avoid // issue when displaying again results $this->_setState('limitstart', 0); $this->_setState('limit', 0); // reprocess custom urls, checking there is still at least one per group // of identical SEF url with a rank = 0 // as the "main" url for this group was possibly deleted during the purge $query = 'select ?? from (select * from ?? where ?? <> ? order by ?? asc) as tmp_table group by ??'; $nameQuoted = array('id', '#__sh404sef_urls', 'dateadd', 'rank', 'oldurl'); $quoted = array('0000-00-00'); try { // select custom with lowest rank $customs = ShlDbHelper::quoteQuery($query, $nameQuoted, $quoted)->shlLoadColumn(); // make sure there is at least one of those with rank = 0 if (!empty($customs)) { ShlDbHelper::updateIn('#__sh404sef_urls', array('rank' => 0), 'id', $customs); } } catch (Exception $e) { ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); $this->setError('Internal database error # ' . $e->getMessage()); } }
/** * * @param string $url * @param array $title * @param string $task * @param int $limit * @param int $limitstart * @return sefurl */ public static function sefGetLocation($nonSefUrl, &$title, $task = null, $limit = null, $limitstart = null, $langParam = null, $showall = null, $suppressPagination = false) { try { $shPageInfo =& Sh404sefFactory::getPageInfo(); $sefConfig =& Sh404sefFactory::getConfig(); $lang = empty($langParam) ? $shPageInfo->currentLanguageTag : $langParam; // shumisha : try to avoid duplicate content on multilingual sites by always adding &lang=xx to url (stored in DB). // warning : must add &lang=xx only if it does not exists already if (!strpos($nonSefUrl, 'lang=')) { $shSepString = substr($nonSefUrl, -9) == 'index.php' ? '?' : '&'; $nonSefUrl .= $shSepString . 'lang=' . shGetIsoCodeFromName($lang); } // make sure url is consistent $nonSefUrl = str_replace('&', '&', $nonSefUrl); // detect multipage homepage $shMultiPageHomePageFlag = shIsHomepage($nonSefUrl); // get all the slugs ready for being urls bits $tempSefUrl = array(); foreach ($title as $titlestring) { $decodedTitletring = urldecode($titlestring); $tempSefUrl[] = titleToLocation($decodedTitletring); } // now build the URL $tempSefUrl = implode("/", $tempSefUrl); // remove duplicate / $tempSefUrl = ShlSystem_Strings::pr('/\\/{2,}/u', '/', $tempSefUrl); // and truncate to max length, according to param $tempSefUrl = JString::substr($tempSefUrl, 0, sh404SEF_MAX_SEF_URL_LENGTH); // trim to max length V 1.2.4.t // if URL is empty, and unless this is a paginated home page, or home page in non-default language, stop there if (empty($tempSefUrl)) { if ((!shIsMultilingual() || shIsMultilingual() && shIsDefaultlang($lang)) && !$sefConfig->addFile && !$shMultiPageHomePageFlag) { // return ''; } // if location is empty, and not multilingual site, or multilingual, but this is default language, then there is nothing to add to url } // we have a valid SEF url, built with the data ($title) sent // by plugin. Now we want to check if it's already in the db // and add it if not // first, we search the memory cache for the non-sef url // as it is faster than looking up the db $finalSefUrl = ''; $sefUrlType = Sh404sefHelperCache::getSefUrlFromCache($nonSefUrl, $finalSefUrl); // if non-sef was not found in cache - or found, but it was a 404 last time we saw it - // we should continue and try adding it if ($sefUrlType == sh404SEF_URLTYPE_NONE || $sefUrlType == sh404SEF_URLTYPE_404) { $finalSefUrl = false; // non-sef was not found in cache, let's look up the database if ($sefUrlType == sh404SEF_URLTYPE_NONE) { $finalSefUrl = ShlDbHelper::selectResult('#__sh404sef_urls', 'oldurl', array('newurl' => $nonSefUrl)); } // we found the sef url in database, we're done if (!empty($finalSefUrl)) { return $finalSefUrl; } // the non-sef url is not in memory cache, nor in database // that's a new one, we need to finalize its sef (add pagination and language information) // After finalizing it, we'll also check that sef is not in the db // as it can already be there, associated with another non-sef (ie: a duplicate) // Either way we'll add it in the db, but mark it as a duplicate if needed // add pagination information, unless we were instructed by extension plugin not to // find if we should separate pagination info from sef with a / or not if (!empty($tempSefUrl)) { $shSeparator = JString::substr($tempSefUrl, -1) == '/' ? '' : '/'; } else { $shSeparator = ''; } $finalSefUrl = $suppressPagination ? $tempSefUrl : shAddPaginationInfo($limit, $limitstart, $showall, 1, $nonSefUrl, $tempSefUrl, $shSeparator); // v 1.2.4.t // if home page, we don't record anything, just return "home page" if ($shMultiPageHomePageFlag && '/' . $finalSefUrl == $tempSefUrl && (!shIsMultilingual() || shIsMultilingual() && shIsDefaultLang($lang))) { // but this is default language // this is start page of multipage homepage, return home or forced home if (!empty($sefConfig->shForcedHomePage)) { return str_replace($shPageInfo->getDefaultFrontLiveSite() . '/', '', $sefConfig->shForcedHomePage); } else { return ''; } } // add language information // first, remove languages in non-sef, to see if we're on homepage // as handling is sligthly different for homepage $v1 = shCleanUpLang($nonSefUrl); $v2 = shCleanUpLang($shPageInfo->homeLink); if ($v1 == $v2 || $v1 == 'index.php') { // check if this is homepage if (shIsMultilingual() && !shIsDefaultLang($lang)) { // if homepage in not-default-language, then add language code regardless of user settings // as we otherwise would not be able to switch language on the frontpage $finalSefUrl = shGetIsoCodeFromName($lang) . '/'; } else { $finalSefUrl = ''; } } else { // not on homepage, insert lang code based on user setting $option = shGetURLVar($nonSefUrl, 'option', ''); if (shInsertIsoCodeInUrl($option, $lang)) { // insert language code based on param // pass URL lang info, as may not be current lang $finalSefUrl = shGetIsoCodeFromName($lang) . '/' . $finalSefUrl; // must be forced lang, not default } } // after adding pagination part of SEF, and adding language code // the new SEF url is now complete and we can try adding to it cache and db if ($finalSefUrl != '') { $dburl = null; $dbUrlId = null; $nonSefUrlType = sh404SEF_URLTYPE_NONE; // search the memory cache for this new sef if ($sefConfig->shUseURLCache) { $nonSefUrlType = Sh404sefHelperCache::getNonSefUrlFromCache($finalSefUrl, $dburl); } $newMaxRank = 0; // if the new SEF was not found in memory cache, or if it was found but // we're set to record duplicates, we search for it in the database if ($sefConfig->shRecordDuplicates || $nonSefUrlType == sh404SEF_URLTYPE_NONE) { $dbUrlList = ShlDbHelper::selectObjectList('#__sh404sef_urls', array('id', 'newurl', 'rank', 'dateadd'), array('oldurl' => $finalSefUrl), $aWhereData = array(), $orderBy = array('rank')); if (count($dbUrlList) > 0) { $dburl = $dbUrlList[0]->newurl; $dbUrlId = $dbUrlList[0]->id; if (empty($dburl)) { // V 1.2.4.t url was found in DB, but was a 404 $nonSefUrlType = sh404SEF_URLTYPE_404; } else { $newMaxRank = $dbUrlList[count($dbUrlList) - 1]->rank + 1; $nonSefUrlType = $dbUrlList[0]->dateadd == '0000-00-00' ? sh404SEF_URLTYPE_AUTO : sh404SEF_URLTYPE_CUSTOM; } } } if ($nonSefUrlType != sh404SEF_URLTYPE_NONE && $nonSefUrlType != sh404SEF_URLTYPE_404) { // we found the SEF, one or more times in the db, in records which do have a non-sef attached $isDuplicate = $dburl != $nonSefUrl; // This is a duplicate so we must indert it with incremented rank; if (is_null($dburl) || $isDuplicate && $sefConfig->shRecordDuplicates) { // shAddSefUrlToDBAndCache( $nonSefUrl, $finalSefUrl, ($isDuplicate ? $newMaxRank : 0), $nonSefUrlType); $dateAdd = $nonSefUrlType == sh404SEF_URLTYPE_AUTO ? '0000-00-00' : date("Y-m-d"); ShlDbHelper::insert('#__sh404sef_urls', array('oldurl' => $finalSefUrl, 'newurl' => $nonSefUrl, 'rank' => $isDuplicate ? $newMaxRank : 0, 'dateadd' => $dateAdd)); // store new sef/non-sef pair in memory cache Sh404sefHelperCache::addSefUrlToCache($nonSefUrl, $finalSefUrl, $nonSefUrlType); // create shURL : get a shURL model, and ask url creation $model = ShlMvcModel_Base::getInstance('pageids', 'Sh404sefModel'); $model->createPageId($finalSefUrl, $nonSefUrl); } } else { // we haven't found the non-sef/sef pair, but maybe there is a record for // a 404 with that SEF. If so, we will "upgrade" the 404 record to a // normal non-sef/sef pair $dbUrlId = empty($dbUrlId) ? 0 : intval($dbUrlId); if ($sefConfig->shLog404Errors) { if ($nonSefUrlType == sh404SEF_URLTYPE_404 && !empty($dbUrlId)) { // we already have seen that it is a 404 $id = $dbUrlId; } elseif ($nonSefUrlType == sh404SEF_URLTYPE_404) { $id = ShlDbHelper::selectResult('#__sh404sef_urls', 'id', array('oldurl' => $finalSefUrl, 'newurl' => '')); } else { $id = null; } } else { $id = null; // if we are not logging 404 errors, then no need to check for } // previous hit of this page. if (!empty($id)) { // we found a 404 record matching the SEF url just created. We'll update that record // instead of creating a new one // need to update dateadd to 0, as otherwise this sef/non-sef pair will be seen as custom // this makes all such 404 errors 'disappear' from the 404 log, but no other solution ShlDbHelper::updateIn('#__sh404sef_urls', array('newurl' => $nonSefUrl, 'dateadd' => '0000-00-00'), 'id', array($id)); Sh404sefHelperCache::addSefUrlToCache($nonSefUrl, $finalSefUrl, sh404SEF_URLTYPE_AUTO); } else { // standard case: creation of a totally new sef/non-sef pair ShlDbHelper::insert('#__sh404sef_urls', array('oldurl' => $finalSefUrl, 'newurl' => $nonSefUrl, 'rank' => 0, 'dateadd' => '0000-00-00')); // store new sef/non-sef pair in memory cache Sh404sefHelperCache::addSefUrlToCache($nonSefUrl, $finalSefUrl, sh404SEF_URLTYPE_AUTO); // create shURL : get a shURL model, and ask url creation $model = ShlMvcModel_Base::getInstance('pageids', 'Sh404sefModel'); $model->createPageId($finalSefUrl, $nonSefUrl); } } } } } catch (Exception $e) { $finalSefUrl = ''; ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); } return $finalSefUrl; }
/** * Delete a list of urls from their ids, * passed as params * * @param array of integer $ids the list of url id to delete * @return boolean true if success */ public function deleteByIds($ids = array()) { if (empty($ids)) { return false; } $status = true; // build a list of ids to read $whereIds = ShlDbHelper::arrayToIntValList($ids); // Need to delete urls from db, from cache // and also make sure the ranking is correct for duplicates // so we must find the first duplicate (if any) for all // urls to delete, and set its rank to zero. // First find about duplicates $query = 'select r2.*' . ' from `#__sh404sef_urls` as r1' . ' join `#__sh404sef_urls` as r2' . ' on r1.`oldurl` = r2.`oldurl`' . ' where r1.' . $this->_db->quoteName('id') . ' in (' . $whereIds . ')'; $query .= ' and r2.' . $this->_db->quoteName('rank') . ' > 0'; $query .= ' order by `rank`'; // perform query try { $this->_db->setQuery($query); $duplicates = $this->_db->shlLoadObjectList(); // now delete urls from db and cache $rows = $this->_getNonSefUrls($ids); if (!empty($rows)) { Sh404sefHelperCache::removeURLFromCache($rows); } // finally, we can simply delete from db by ids ShlDbHelper::deleteIn('#__sh404sef_urls', 'id', $ids); } catch (Exception $e) { ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); $this->setError('Internal database error ' . $e->getMessage()); $status = false; } // if successfull, set the new rank 0 duplicate if ($status && !empty($duplicates)) { // array to hold ids of urls that should be set to rank=0 $newMainUrls = array(); // temporary arrays, holding duplicates grouped by nonsef url $groupedDuplicates = array(); // group them by old url foreach ($duplicates as $url) { $groupedDuplicates[md5($url->oldurl)][] = $url; } // now collect the first url of each group, it // will have the lowest rank of the bunch as the initial // db query was ordered by rank asc foreach ($groupedDuplicates as $urlGroup) { $newMainUrls[] = $urlGroup[0]->id; } // now we just set the rank column to 0 for the // selected urls, so as to make them the new main urls // build a list of ids to read try { ShlDbHelper::updateIn('#__sh404sef_urls', array('rank' => 0), 'id', $newMainUrls, ShlDbHelper::INTEGER); } catch (Exception $e) { ShlSystem_Log::error('sh404sef', '%s::%s::%d: %s', __CLASS__, __METHOD__, __LINE__, $e->getMessage()); $this->setError('Internal database error ' . $e->getMessage()); $status = false; } } return $status; }
private function _changeErrorPageCategory($pageTitle = '__404__') { // try find this old category $catid = ShlDbHelper::selectResult('#__categories', array('id'), 'parent_id > 0 and extension = ? and path = ? and level = ?', array('com_content', 'uncategorised', 1)); if (empty($catid)) { return false; } // we have cat id, try to read article $ids = ShlDbHelper::selectAssoc('#__content', array('id'), array('catid' => $catid, 'title' => $pageTitle)); if (empty($ids)) { return false; } // we indeed have one or more such articles (possibly one per language: move them to new category) ShlDbHelper::updateIn('#__content', array('catid' => $this->_errorPageCatId), 'id', $ids); return true; }