/** * Main get data methods * * @access public * @return Object[] */ public function getData() { // Build query $query = $this->buildListQuery(); $this->_db->setQuery($query, $this->getState('limitstart'), $this->getState('limit')); try { $result = $this->_db->loadObjectList(); if ($this->_db->getErrorNum()) { throw new JMapException(JText::_('COM_JMAP_ERROR_RETRIEVING_DATASETS') . $this->_db->getErrorMsg(), 'error'); } // Attach names for included data sources if (count($result)) { foreach ($result as &$row) { $subQuery = "SELECT" . "\n " . $this->_db->quoteName('name') . "\n FROM " . $this->_db->quoteName('#__jmap') . "\n WHERE " . $this->_db->quoteName('id') . ' IN ( ' . preg_replace('/\\[|\\]/i', '', $row->sources) . ' )'; $subQueryResults = $this->_db->setQuery($subQuery)->loadColumn(); $row->sourcesNames = $subQueryResults; if ($this->_db->getErrorNum()) { throw new JMapException(JText::_('COM_JMAP_ERROR_RETRIEVING_DATASETS') . $this->_db->getErrorMsg(), 'error'); } } } } catch (JMapException $e) { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); $result = array(); } catch (Exception $e) { $jmapException = new JMapException($e->getMessage(), 'error'); $this->app->enqueueMessage($jmapException->getMessage(), $jmapException->getErrorLevel()); $result = array(); } return $result; }
/** * Main get data method, retrieve model data using the Google API * Search results are based on parsing of automated queries * * @access public * @return Object[] */ public function getData() { // Check if it's a search by keyword $keyword = $this->getState('searchword', null); $serpSearch = $keyword ? $keyword : 'site:' . $this->getComponentParams()->get('seostats_custom_link', JUri::root(false)); $customHeaders = array('countrytld' => $this->getState('countriestld', null), 'acceptlanguage' => $this->getState('acceptlanguage', null)); try { if (!function_exists('curl_init')) { throw new JMapException(JText::_('COM_JMAP_CURL_NOT_SUPPORTED'), 'error'); } $result = JMapSeostatsServicesGoogle::getSerps($serpSearch, $this->getState('limitstart', 0), $customHeaders); if (!$result) { throw new JMapException(JText::_('COM_JMAP_ERROR_RETRIEVING_INDEXING') . $this->_db->getErrorMsg(), 'notice'); } $this->setState('serpsearch', $serpSearch); } catch (JMapException $e) { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); $result = array(); } catch (Exception $e) { $jmapException = new JMapException($e->getMessage(), 'error'); $this->app->enqueueMessage($jmapException->getMessage(), $jmapException->getErrorLevel()); $result = array(); } return $result; }
/** * Main get data methods * * @access public * @return Object[] */ public function getData() { // Build query $query = $this->buildListQuery(); $this->_db->setQuery($query, $this->getState('limitstart'), $this->getState('limit')); try { $result = $this->_db->loadObjectList(); if ($this->_db->getErrorNum()) { throw new JMapException(JText::_('COM_JMAP_ERROR_RETRIEVING_PINGOMATIC_LINKS') . $this->_db->getErrorMsg(), 'error'); } } catch (JMapException $e) { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); $result = array(); } catch (Exception $e) { $jmapException = new JMapException($e->getMessage(), 'error'); $this->app->enqueueMessage($jmapException->getMessage(), $jmapException->getErrorLevel()); $result = array(); } return $result; }
/** * Store meta info for a given url * * @access private * @param Object $dataObject * @param Object[] $additionalModels Array for additional injected models type hinted by interface * @return Object */ private function stateMeta($dataObject, $additionalModels = null) { // Response JSON object $response = new stdClass(); try { // Check if the link already exists in this table $selectQuery = "SELECT" . $this->_db->quoteName('id') . "\n FROM " . $this->_db->quoteName('#__jmap_metainfo') . "\n WHERE" . $this->_db->quoteName('linkurl') . " = " . $this->_db->quote($dataObject->linkurl); $linkExists = $this->_db->setQuery($selectQuery)->loadResult(); // If the link exists just update it, otherwise insert a new one if ($linkExists) { $query = "UPDATE" . "\n " . $this->_db->quoteName('#__jmap_metainfo') . "\n SET " . "\n " . $this->_db->quoteName('published') . " = " . (int) $dataObject->published . "\n WHERE " . "\n " . $this->_db->quoteName('linkurl') . " = " . $this->_db->quote($dataObject->linkurl); $this->_db->setQuery($query); $this->_db->execute(); if ($this->_db->getErrorNum()) { throw new JMapException(JText::sprintf('COM_JMAP_METAINFO_ERROR_STORING_DATA', $this->_db->getErrorMsg()), 'error'); } } else { $response->result = true; $response->exception_message = JText::_('COM_JMAP_NO_METAINFO_SAVED'); return $response; } // All completed succesfully $response->result = true; } catch (JMapException $e) { $response->result = false; $response->exception_message = $e->getMessage(); return $response; } catch (Exception $e) { $jmapException = new JMapException(JText::sprintf('COM_JMAP_ERROR_RETRIEVING_DATA', $e->getMessage()), 'error'); $response->result = false; $response->exception_message = $jmapException->getMessage(); return $response; } return $response; }
/** * Manage robots.txt entry * * @access private * @param $idEntity * @param $additionalModels * * @Return array */ private function robotsSitemapEntry($queryStringLink, $additionalModels = null) { // Response JSON object $response = new stdClass(); try { // Resource Action detection dall'HTTP method name $HTTPMethod = $this->app->input->server->get('REQUEST_METHOD', 'GET'); if ($HTTPMethod !== 'POST') { throw new JMapException(JText::_('COM_JMAP_INVALID_RESTFUL_METHOD'), 'error'); } // Update robots.txt add entry Sitemap if not exists $targetRobot = null; // Try standard robots.txt if (JFile::exists(JPATH_ROOT . '/robots.txt')) { $targetRobot = JPATH_ROOT . '/robots.txt'; } elseif (JFile::exists(JPATH_ROOT . '/robots.txt.dist')) { // Fallback on distribution version $targetRobot = JPATH_ROOT . '/robots.txt.dist'; } else { throw new JMapException(JText::_('COM_JMAP_ROBOTS_NOTFOUND'), 'error'); } // Robots.txt found! if ($targetRobot !== false) { // If file permissions ko if (!($robotContents = JFile::read($targetRobot))) { throw new JMapException(JText::_('COM_JMAP_ERROR_READING_ROBOTS'), 'error'); } $newEntry = null; // Entry for this sitemap if (!stristr($robotContents, 'Sitemap: ' . $queryStringLink)) { $toAppend = null; // Check if JSitemap added already some entries if (!stristr($robotContents, '# JSitemap')) { // Empty line double EOL $toAppend = PHP_EOL . PHP_EOL . '# JSitemap entries'; } $toAppend .= PHP_EOL . 'Sitemap: ' . $queryStringLink; $newEntry = $robotContents . $toAppend; } // If file permissions ko on rewrite updated contents if ($newEntry) { if (!is_writable($targetRobot)) { @chmod($targetRobot, 0777); } if (@(!JFile::write($targetRobot, $newEntry))) { throw new JMapException(JText::_('COM_JMAP_ERROR_WRITING_ROBOTS'), 'error'); } } else { throw new JMapException(JText::_('COM_JMAP_ENTRY_ALREADY_ADDED'), 'error'); } } // All completed succesfully $response->result = true; } catch (JMapException $e) { $response->result = false; $response->errorMsg = $e->getMessage(); return $response; } catch (Exception $e) { $jmapException = new JMapException($e->getMessage(), 'error'); $response->result = false; $response->errorMsg = $jmapException->getMessage(); return $response; } return $response; }
/** * Main get data method * * @access public * @return Object[] */ public function getData() { // Load data from XML file, parse it to load records $cachedSitemapFilePath = JPATH_COMPONENT_ADMINISTRATOR . '/cache/metainfo/'; // Has sitemap some vars such as lang or Itemid? $sitemapLang = $this->getState('sitemaplang', ''); $sitemapLinksLang = $sitemapLang ? $sitemapLang . '/' : ''; $sitemapLang = $sitemapLang ? '_' . $sitemapLang : ''; $sitemapDataset = $this->getState('sitemapdataset', ''); $sitemapDataset = $sitemapDataset ? '_dataset' . (int) $sitemapDataset : ''; $sitemapItemid = $this->getState('sitemapitemid', ''); $sitemapItemid = $sitemapItemid ? '_menuid' . (int) $sitemapItemid : ''; // Final name $cachedSitemapFilename = 'sitemap_xml' . $sitemapLang . $sitemapDataset . $sitemapItemid . '.xml'; // Start processing try { // Now check if the file correctly exists if (JFile::exists($cachedSitemapFilePath . $cachedSitemapFilename)) { $loadedSitemapXML = simplexml_load_file($cachedSitemapFilePath . $cachedSitemapFilename); } else { throw new JMapException(JText::sprintf('COM_JMAP_METAINFO_NOCACHED_FILE_EXISTS', $this->_db->getErrorMsg()), 'error'); } // Execute HTTP request and associate HTTP response code with each record links $httpClient = new JMapHttp(); if ($loadedSitemapXML->url->count()) { // Manage splice pagination here for the XML records $convertedIteratorToArray = iterator_to_array($loadedSitemapXML->url, false); // Store number of records for pagination $this->recordsNumber = count($convertedIteratorToArray); // Execute pagination splicing if any limit is set $limit = $this->getState('limit'); if ($limit) { $loadedSitemapXML = array_splice($convertedIteratorToArray, $this->getState('limitstart'), $this->getState('limit')); } else { $loadedSitemapXML = $convertedIteratorToArray; } // Get a search filter $searchFilter = $this->state->get('searchword', null); $stateFilter = $this->state->get('state', null); // Cycle on every links, filter by search word if any and augment with link metainfo foreach ($loadedSitemapXML as $index => &$url) { // Evaluate filtering by search word if ($searchFilter) { $isMatching = stripos($url->loc, $searchFilter) !== false; if (!$isMatching) { array_splice($loadedSitemapXML, $index, 1); continue; } } $url = (object) (array) $url; // Load meta info for this link from the table and augment the array and object $query = "SELECT *" . "\n FROM " . $this->_db->quoteName('#__jmap_metainfo') . "\n WHERE " . $this->_db->quoteName('linkurl') . " = " . $this->_db->quote($url->loc); $metaInfos = $this->_db->setQuery($query)->loadObject(); // This link has valid metainfo if (isset($metaInfos->id)) { $url->metainfos = $metaInfos; } // Evaluate filtering by state if ($stateFilter) { if (isset($url->metainfos->published)) { $isMatching = (int) $url->metainfos->published === ($stateFilter == 'P' ? 1 : 0); if (!$isMatching) { array_splice($loadedSitemapXML, $index, 1); } } else { array_splice($loadedSitemapXML, $index, 1); } } } // Perform array sorting if any $order = $this->getState('order', null); $jmapMetainfoOrderDir = $this->getState('order_dir', 'asc'); if ($order == 'link') { function cmpAsc($a, $b) { return strcmp($a->loc, $b->loc); } function cmpDesc($a, $b) { return strcmp($b->loc, $a->loc); } $callbackName = $jmapMetainfoOrderDir == 'asc' ? 'cmpAsc' : 'cmpDesc'; usort($loadedSitemapXML, $callbackName); } } else { throw new JMapException(JText::sprintf('COM_JMAP_METAINFO_EMPTY_SITEMAP', $this->_db->getErrorMsg()), 'notice'); } } catch (JMapException $e) { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); $loadedSitemapXML = array(); } catch (Exception $e) { $jmapException = new JMapException($e->getMessage(), 'error'); $this->app->enqueueMessage($jmapException->getMessage(), $jmapException->getErrorLevel()); $loadedSitemapXML = array(); } return $loadedSitemapXML; }
/** * Return the google token * * @access public * @return string */ public function getToken() { $clientID = (int) $this->app->getClientId(); try { $query = "SELECT token FROM #__jmap_google WHERE id = " . $clientID; $this->_db->setQuery($query); $result = $this->_db->loadResult(); } catch (JMapException $e) { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); $result = null; } catch (Exception $e) { $jmapException = new JMapException($e->getMessage(), 'error'); $this->app->enqueueMessage($jmapException->getMessage(), $jmapException->getErrorLevel()); $result = null; } return $result; }
/** * Get the Data for a view * * @access private * @param object $source * @param array $accessLevels * * @return Object */ private function getSourceData($source, $accessLevels) { // Create di un nuovo result source object popolato delle properties necessarie alla view e degli items recuperati da DB $resultSourceObject = new stdClass(); $resultSourceObject->id = $source->id; $resultSourceObject->name = $source->name; $resultSourceObject->type = $source->type; if ($source->sqlquery_managed) { $resultSourceObject->chunks = json_decode($source->sqlquery_managed); } // If sitemap format is gnews, allow only content data source and 3PD user data source that are supported as compatible, avoid calculate unuseful data and return immediately if ($this->documentFormat === 'gnews') { if ($source->type === 'menu') { return false; } if ($source->type === 'user') { if (isset($resultSourceObject->chunks)) { if (!in_array($resultSourceObject->chunks->table_maintable, $this->supportedGNewsTablesOptions)) { return false; } } } } // If sitemap format is rss, allow only content data source and 3PD user data source that are supported as compatible, avoid calculate unuseful data and return immediately if ($this->documentFormat === 'rss') { if ($source->type === 'menu') { return false; } // Load always manifest, both content and third party data sources $this->rssExtensionsManifest = $this->loadManifest('rss'); // If third party data sources check if it's supported, otherwise return false if ($source->type === 'user' && isset($resultSourceObject->chunks)) { // Add dynamic Virtuemart $vmProperty = '#__virtuemart_products_' . $this->siteLanguageRFC; $this->rssExtensionsManifest->{$vmProperty} = 'product_desc'; // Skip extensions not supported for RSS feed generation if (!property_exists($this->rssExtensionsManifest, $resultSourceObject->chunks->table_maintable)) { return false; } } } // Already a JRegistry object! Please note object cloning to avoid reference overwriting! // Component -> menu view specific level params override $resultSourceObject->params = clone $this->cparams; // Item specific level params override $resultSourceObject->params->merge(new JRegistry($source->params)); // Ensure the current datasource is enabled for the current sitemap format otherwise skip processing if (!$resultSourceObject->params->get('htmlinclude', 1) && $this->documentFormat == 'html') { return false; } if (!$resultSourceObject->params->get('xmlinclude', 1) && $this->documentFormat == 'xml') { return false; } if (!$resultSourceObject->params->get('xmlimagesinclude', 1) && $this->documentFormat == 'images') { return false; } if (!$resultSourceObject->params->get('xmlmobileinclude', 1) && $this->documentFormat == 'mobile') { return false; } if (!$resultSourceObject->params->get('gnewsinclude', 1) && $this->documentFormat == 'gnews') { return false; } if (!$resultSourceObject->params->get('rssinclude', 1) && $this->documentFormat == 'rss') { return false; } // ACL filtering $disableAcl = $resultSourceObject->params->get('disable_acl'); $sourceItems = array(); switch ($source->type) { case 'user': $query = $source->sqlquery; $debugMode = $resultSourceObject->params->get('debug_mode', 0); // Do runtime preprocessing if any for selected data source extension $query = $this->runtimePreProcessing($query, $resultSourceObject); // Se la raw query è stata impostata if ($query) { $query = str_replace('{aid}', '(' . implode(',', $accessLevels) . ')', $query); $query = str_replace('{langtag}', $this->_db->quote($this->langTag), $query); $query = str_replace('{languagetag}', $this->_db->quote($this->langTag), $query); // Manage for latest months placeholder if found one if (preg_match("/'?{(\\d+)months}'?/i", $query, $matches)) { $minValidCreatedDate = gmdate("Y-m-d H:i:s", strtotime("-" . $matches[1] . " months", time())); // All items need to be created after the minimum valid created date $query = preg_replace("/'?{(\\d+)months}'?/i", $this->_db->quote($minValidCreatedDate), $query); } // Runtime preprocessing for RSS description field if ($this->documentFormat === 'rss') { $query = $this->runtimeRssPreProcessing($resultSourceObject->chunks->table_maintable, $query); } // Check if a limit for query rows has been set, this means we are in precaching process by JS App client if (!$this->limitRows) { $this->_db->setQuery($query); } else { $this->_db->setQuery($query, $this->limitStart, $this->limitRows); } try { // Security safe check: only SELECT allowed if (preg_match('/(delete|update|insert|password)/i', $query)) { throw new JMapException(sprintf(JText::_('COM_JMAP_QUERY_NOT_ALLOWED_FROM_USER_DATASOURCE'), $source->name), 'warning'); } $sourceItems = $this->_db->loadObjectList(); if ($this->_db->getErrorNum() && !$sourceItems) { $queryExplained = null; if ($debugMode) { $queryExplained = '<br /><br />' . $this->_db->getErrorMsg() . '<br /><br />' . JText::_('COM_JMAP_SQLQUERY_EXPLAINED') . '<br /><br />' . $this->_db->getQuery() . '<br /><br />' . JText::_('COM_JMAP_SQLQUERY_EXPLAINED_END'); } throw new JMapException(sprintf(JText::_('COM_JMAP_ERROR_RETRIEVING_DATA_FROM_USER_DATASOURCE'), $source->name) . $queryExplained, 'warning'); } // Detected a precaching call, so store in the model state the number of affected rows for JS app if ($this->limitRows) { $this->setState('affected_rows', $this->_db->getAffectedRows()); } // Start subQueriesPostProcessor if needed for nested multilevel categories if ($resultSourceObject->params->get('multilevel_categories', 0) && $this->hasCategorization($resultSourceObject)) { // Pre assignment $resultSourceObject->data = $sourceItems; // Start post processor $this->subQueriesPostProcessor($resultSourceObject); } } catch (JMapException $e) { if ($e->getErrorLevel() == 'notice' && $debugMode) { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); } elseif ($e->getErrorLevel() != 'notice') { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); } $resultSourceObject->data = array(); return $resultSourceObject; } catch (Exception $e) { $jmapException = new JMapException($e->getMessage(), 'warning'); $this->app->enqueueMessage(sprintf(JText::_('COM_JMAP_ERROR_RETRIEVING_DATA_FROM_USER_DATASOURCE'), $source->name), 'warning'); if ($debugMode) { $this->app->enqueueMessage($jmapException->getMessage(), $jmapException->getErrorLevel()); } $resultSourceObject->data = array(); return $resultSourceObject; } } break; case 'menu': $menuAccess = null; $originalSourceItems = array(); // Unpublished items $doUnpublishedItems = $resultSourceObject->params->get('dounpublished', 0); // Exclusion menu $subQueryExclusion = null; $exclusionMenuItems = $resultSourceObject->params->get('exclusion', array()); if ($exclusionMenuItems && !is_array($exclusionMenuItems)) { $exclusionMenuItems = array($exclusionMenuItems); } if (count($exclusionMenuItems)) { $subQueryExclusion = "\n AND menuitems.id NOT IN (" . implode(',', $exclusionMenuItems) . ")"; } $queryChunk = null; if (!$doUnpublishedItems) { $queryChunk = "\n AND menuitems.published = 1"; } // Filter by access if ACL option enabled if ($disableAcl !== 'disabled') { $menuAccess = "\n AND menuitems.access IN ( " . implode(',', $accessLevels) . " )"; } // Filter by language only if multilanguage is correctly enabled by Joomla! plugin $menuLanguageFilter = null; if (JMapLanguageMultilang::isEnabled()) { $menuLanguageFilter = "\n AND ( menuitems.language = " . $this->_db->quote('*') . " OR menuitems.language = " . $this->_db->quote($this->langTag) . " ) "; } $menuQueryItems = "SELECT menuitems.*, menuitems.parent_id AS parent, menuitems.level AS sublevel, menuitems.title AS name, menupriorities.priority" . "\n FROM #__menu as menuitems" . "\n INNER JOIN #__menu_types AS menutypes" . "\n ON menuitems.menutype = menutypes.menutype" . "\n LEFT JOIN #__jmap_menu_priorities AS menupriorities" . "\n ON menupriorities.id = menuitems.id" . "\n WHERE\tmenuitems.published >= 0" . $queryChunk . $menuAccess . "\n AND menutypes.title = " . $this->_db->quote($source->name) . $menuLanguageFilter . $subQueryExclusion . "\n ORDER BY menuitems.menutype, menuitems.parent_id, menuitems.level, menuitems.lft"; // Check if a limit for query rows has been set, this means we are in precaching process by JS App client if (!$this->limitRows) { $this->_db->setQuery($menuQueryItems); } else { $this->_db->setQuery($menuQueryItems, $this->limitStart, $this->limitRows); } try { $originalSourceItems = $this->_db->loadObjectList(); if ($this->_db->getErrorNum()) { throw new JMapException(sprintf(JText::_('COM_JMAP_ERROR_RETRIEVING_DATA'), $source->name), 'notice'); } // Detected a precaching call, so store in the model state the number of affected rows for JS app if ($this->limitRows) { $this->setState('affected_rows', $this->_db->getAffectedRows()); } // Recursive ordering for menu rows ONLY if HTML format, otherwise make no sense so save resources and time if ($this->documentFormat == 'html') { $sourceItems = $this->sortMenu($originalSourceItems, $resultSourceObject->params); } else { $sourceItems = $originalSourceItems; } } catch (JMapException $e) { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); $resultSourceObject->data = array(); return $resultSourceObject; } catch (Exception $e) { $jmapException = new JMapException($e->getMessage(), 'error'); $this->app->enqueueMessage($jmapException->getMessage(), $jmapException->getErrorLevel()); $resultSourceObject->data = array(); return $resultSourceObject; } break; case 'content': $access = null; $catAccess = null; $limitRecent = null; $dynamicSelectFields = null; $dynamicOrdering = null; $now = gmdate('Y-m-d H:i:s', time()); // Exclusion access for Google News Sitemap and if ACL is disabled $format = $this->getState('format'); // Set select fields only if html sitemap format is detected, save memory if XML and not needed if ($format == 'html') { $dynamicSelectFields = 'c.title AS title, cat.title AS category, cat.level,'; } // Set select fields only if RSS sitemap format is detected, save memory if not needed if ($format == 'rss' || $format == 'gnews') { $dynamicSelectFields = 'c.title AS title, cat.title AS category,'; } // Manage content articles order if ($format == 'rss' || $format != 'html' && $resultSourceObject->params->get('orderbydate', 0)) { $dynamicOrdering = "created DESC,"; } if ($format != 'gnews' && $disableAcl !== 'disabled') { $access = "\n AND c.access IN ( " . implode(',', $accessLevels) . " )"; $catAccess = "\n AND cat.access IN ( " . implode(',', $accessLevels) . " )"; } // Choose to limit valid articles for Google News Sitemap to last n most recent days if ($format == 'gnews' && $this->cparams->get('gnews_limit_recent', false)) { $validDays = $this->cparams->get('gnews_limit_valid_days', 2); $limitRecent = "\n AND UNIX_TIMESTAMP(c.publish_up) > " . (time() - 24 * 60 * 60 * $validDays); } // Exclusion categories $subQueryCatExclusion = null; $subQueryCategoryExclusion = null; $exclusionCategories = $resultSourceObject->params->get('catexclusion', array()); // Normalize select options if ($exclusionCategories && !is_array($exclusionCategories)) { $exclusionCategories = array($exclusionCategories); } // Exclusion children categories da table orm nested set model if (count($exclusionCategories)) { JTable::addIncludePath(JPATH_LIBRARIES . '/joomla/database/table'); $categoriesTableNested = JTable::getInstance('Category'); $children = array(); foreach ($exclusionCategories as $topCatID) { // Load Children categories se presenti $categoriesTableNested->load($topCatID); $tempChildren = $categoriesTableNested->getTree(); if (is_array($tempChildren) && count($tempChildren)) { foreach ($tempChildren as $child) { if (!in_array($child->id, $children) && !in_array($child->id, $exclusionCategories)) { $exclusionCategories[] = $child->id; } } } } $subQueryCatExclusion = "\n AND c.catid NOT IN (" . implode(',', $exclusionCategories) . ")"; $subQueryCategoryExclusion = "\n AND cat.id NOT IN (" . implode(',', $exclusionCategories) . ")"; } // Exclusion articles $subQueryArticleExclusion = null; $exclusionArticles = $resultSourceObject->params->get('articleexclusion', array()); // Normalize select options if ($exclusionArticles && !is_array($exclusionArticles)) { $exclusionArticles = array($exclusionArticles); } if (count($exclusionArticles)) { $subQueryArticleExclusion = "\n AND c.id NOT IN (" . implode(',', $exclusionArticles) . ")"; } // Evaluate content levels to include $includeArchived = $this->cparams->get('include_archived', 0); $contentLevel = $includeArchived ? ' > 0' : ' = 1'; // Filter by language only if multilanguage is correctly enabled by Joomla! plugin $contentLanguageFilter = null; $categoryLanguageFilter = null; if (JMapLanguageMultilang::isEnabled()) { $contentLanguageFilter = "\n AND ( c.language = " . $this->_db->quote('*') . " OR c.language = " . $this->_db->quote($this->langTag) . " ) "; $categoryLanguageFilter = "\n AND ( cat.language = " . $this->_db->quote('*') . " OR cat.language = " . $this->_db->quote($this->langTag) . " ) "; } // Check if pagebreaks analysis is required $pageBreaksFullText = null; if ($pageBreaksLinks = $this->cparams->get('show_pagebreaks', 0)) { $pageBreaksFullText = "\n ,CONCAT(c.introtext, c.fulltext) AS completetext"; } // Check if limit by recent months is set for content data source // Manage for latest months placeholder if found one $limitLatestItems = null; if ($monthsLimit = $resultSourceObject->params->get('created_date', null)) { $minValidCreatedDate = gmdate("Y-m-d H:i:s", strtotime("-" . $monthsLimit . " months", time())); $limitLatestItems = "\n AND c.created > " . $this->_db->quote($minValidCreatedDate); } $contentQueryItems = "SELECT c.id, c.language, c.publish_up, c.access, c.metakey, catspriorities.priority," . $dynamicSelectFields . "\n cat.id AS catid," . "\n UNIX_TIMESTAMP(c.modified) AS modified," . "\n CONCAT('index.php?option=com_content&view=article&id=', c.id) AS link , c.catid AS catslug," . "\n CASE WHEN CHAR_LENGTH(c.alias) THEN CONCAT_WS(':', c.id, c.alias) ELSE c.id END AS slug" . $pageBreaksFullText . "\n FROM " . $this->_db->quoteName('#__content') . " AS c" . "\n LEFT JOIN #__jmap_cats_priorities AS catspriorities ON catspriorities.id = c.catid" . "\n RIGHT JOIN #__categories AS cat ON cat.id = c.catid" . "\n AND c.state {$contentLevel}" . "\n AND ( c.publish_up = '0000-00-00 00:00:00' OR c.publish_up <= '{$now}' )" . "\n AND ( c.publish_down = '0000-00-00 00:00:00' OR c.publish_down >= '{$now}' )" . $limitRecent . $limitLatestItems . $access . $contentLanguageFilter . $subQueryCatExclusion . $subQueryArticleExclusion . "\n WHERE cat.published = '1'" . $catAccess . "\n AND cat.extension = " . $this->_db->quote('com_content') . $categoryLanguageFilter . $subQueryCategoryExclusion . "\n ORDER BY {$dynamicOrdering} cat.lft, c.ordering"; // Runtime preprocessing for RSS description field if ($this->documentFormat === 'rss') { $contentQueryItems = $this->runtimeRssPreProcessing('c', $contentQueryItems); } // Check if a limit for query rows has been set, this means we are in precaching process by JS App client if (!$this->limitRows) { $this->_db->setQuery($contentQueryItems); } else { $this->_db->setQuery($contentQueryItems, $this->limitStart, $this->limitRows); } try { $sourceItems = $this->_db->loadObjectList(); if ($this->_db->getErrorNum()) { throw new JMapException(sprintf(JText::_('COM_JMAP_ERROR_RETRIEVING_DATA'), $source->name), 'notice'); } // Detected a precaching call, so store in the model state the number of affected rows for JS app if ($this->limitRows) { $this->setState('affected_rows', $this->_db->getAffectedRows()); } // Sub article pagebreaks processing if ($pageBreaksLinks) { foreach ($sourceItems as $article) { $this->addPagebreaks($article); } } } catch (JMapException $e) { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); $resultSourceObject->data = array(); return $resultSourceObject; } catch (Exception $e) { $jmapException = new JMapException($e->getMessage(), 'error'); $this->app->enqueueMessage($jmapException->getMessage(), $jmapException->getErrorLevel()); $resultSourceObject->data = array(); return $resultSourceObject; } break; case 'plugin': // Call the plugin interface and retrieve data $pluginName = strtolower($source->name); $className = 'JMapFilePlugin' . ucfirst($source->name); try { // Check if the plugin interface implementation exists if (!file_exists(JPATH_COMPONENT_ADMINISTRATOR . '/plugins/' . $pluginName . '/' . $pluginName . '.php')) { throw new JMapException(sprintf(JText::_('COM_JMAP_ERROR_PLUGIN_DATASOURCE_NOT_EXISTS'), $pluginName . '.php'), 'warning'); } // Include for multiple instances of this data source include_once JPATH_COMPONENT_ADMINISTRATOR . '/plugins/' . $pluginName . '/' . $pluginName . '.php'; // Check if the concrete class exists now if (!class_exists($className)) { throw new JMapException(sprintf(JText::_('COM_JMAP_ERROR_PLUGIN_CLASS_NOT_EXISTS'), $className), 'warning'); } // Load the language file for the plugin, manage partial language translations $jLang = JFactory::getLanguage(); $jLang->load($pluginName, JPATH_COMPONENT_ADMINISTRATOR . '/plugins/' . $pluginName, 'en-GB', true, true); if ($jLang->getTag() != 'en-GB') { $jLang->load($pluginName, JPATH_COMPONENT_ADMINISTRATOR . '/plugins/' . $pluginName, null, true, false); } // Instantiate the plugin class, inject $this class and manage limitRows for precaching in third party plugins $pluginInstance = new $className(); $retrievedData = $pluginInstance->getSourceData($resultSourceObject->params, $this->_db, $this); // 1) first structure required: plain list of items -> PLAIN LIST OF ELEMENTS if (!array_key_exists('items', $retrievedData)) { throw new JMapException(sprintf(JText::_('COM_JMAP_ERROR_PLUGIN_NODATA_RETURNED'), $pluginName), 'warning'); } $sourceItems = $retrievedData['items']; // Check if additional structures for nested categories tree are returned // 2) second structure optional: plain list of items grouped by cats -> LIST OF ELEMENTS GROUPED BY PLAIN CATS STRUCTURE if (array_key_exists('items_tree', $retrievedData)) { $resultSourceObject->itemsTree = $retrievedData['items_tree']; } // 3) third structure optional: nested tree of cats by parents -> LIST OF ELEMENTS GROUPED BY NESTED CATS STRUCTURE if (array_key_exists('categories_tree', $retrievedData)) { $resultSourceObject->categoriesTree = $retrievedData['categories_tree']; } } catch (JMapException $e) { if ($e->getErrorLevel() == 'notice' && $debugMode) { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); } elseif ($e->getErrorLevel() != 'notice') { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); } $resultSourceObject->data = array(); return $resultSourceObject; } catch (Exception $e) { $debugMode = $this->cparams->get('enable_debug', 0); $jmapException = new JMapException($e->getMessage(), 'warning'); $this->app->enqueueMessage(sprintf(JText::_('COM_JMAP_ERROR_RETRIEVING_DATA_FROM_USER_DATASOURCE'), $source->name), 'warning'); if ($debugMode) { $this->app->enqueueMessage($jmapException->getMessage(), $jmapException->getErrorLevel()); } $resultSourceObject->data = array(); return $resultSourceObject; } break; } // Final assignment $resultSourceObject->data = $sourceItems; return $resultSourceObject; }
/** * Try to check if the component table has entity ruled by create date, * and if yes filtering by latest months can be shown and afterwards applied at runtime * * @param Object $record * @return boolean */ public function getHasCreatedDate($record) { // Always true for content type data source if ($record->type == 'content') { return true; } // Available only for content and user data source that supports created field not newly created if (!$record->id || $record->type == 'menu') { return false; } if (strpos($record->sqlquery_managed->table_maintable, 'categor')) { return false; } // Build query $query = "SHOW COLUMNS FROM " . $this->_db->quoteName($record->sqlquery_managed->table_maintable); $this->_db->setQuery($query); try { $tableFields = $this->_db->loadColumn(); if ($this->_db->getErrorNum()) { throw new JMapException(JText::sprintf('COM_JMAP_ERROR_RETRIEVING_CREATEDATE_INFO', $this->_db->getErrorMsg()), 'notice'); } // Search in fields array we have found the create date reserved field if (in_array('created', $tableFields)) { return true; } } catch (JMapException $e) { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); return false; } catch (Exception $e) { $jmapException = new JMapException($e->getMessage(), 'error'); $this->app->enqueueMessage($jmapException->getMessage(), $jmapException->getErrorLevel()); return false; } return false; }
/** * Main get data method * * @access public * @return Object[] */ public function getData() { // Load data from XML file, parse it to load records $cachedSitemapFilePath = JPATH_COMPONENT_ADMINISTRATOR . '/cache/analyzer/'; // Has sitemap some vars such as lang or Itemid? $sitemapLang = $this->getState('sitemaplang', ''); $sitemapLinksLang = $sitemapLang ? $sitemapLang . '/' : ''; $sitemapLang = $sitemapLang ? '_' . $sitemapLang : ''; $sitemapDataset = $this->getState('sitemapdataset', ''); $sitemapDataset = $sitemapDataset ? '_dataset' . (int) $sitemapDataset : ''; $sitemapItemid = $this->getState('sitemapitemid', ''); $sitemapItemid = $sitemapItemid ? '_menuid' . (int) $sitemapItemid : ''; // Final name $cachedSitemapFilename = 'sitemap_xml' . $sitemapLang . $sitemapDataset . $sitemapItemid . '.xml'; // Start processing try { // Now check if the file correctly exists if (JFile::exists($cachedSitemapFilePath . $cachedSitemapFilename)) { $loadedSitemapXML = simplexml_load_file($cachedSitemapFilePath . $cachedSitemapFilename); } else { throw new JMapException(JText::sprintf('COM_JMAP_ANALYZER_NOCACHED_FILE_EXISTS', $this->_db->getErrorMsg()), 'error'); } // Execute HTTP request and associate HTTP response code with each record links $httpClient = new JMapHttp(); if ($loadedSitemapXML->url->count()) { // Manage splice pagination here for the XML records $convertedIteratorToArray = iterator_to_array($loadedSitemapXML->url, false); // Store number of records for pagination $this->recordsNumber = count($convertedIteratorToArray); // Execute pagination splicing if any limit is set $limit = $this->getState('limit'); if ($limit) { $loadedSitemapXML = array_splice($convertedIteratorToArray, $this->getState('limitstart'), $this->getState('limit')); } else { $loadedSitemapXML = $convertedIteratorToArray; } // Now start the Analyzer $siteRouter = JRouterSite::getInstance('site', array('mode' => JROUTER_MODE_SEF)); if (version_compare(JVERSION, '3.4', '>=')) { JApplicationCms::getInstance('site')->loadLanguage(); } $headers = array('Accept' => 'text/html', 'User-Agent' => 'Googlebot-Image/1.0'); foreach ($loadedSitemapXML as $url) { $httpResponse = $httpClient->get($url->loc, $headers); $url->httpstatus = $httpResponse->code; // Find informations about the link, component and menu itemid if any, need a workaround to parse correctly from backend $baseAdmin = JURI::base(); $baseSite = str_replace('/administrator', '', $baseAdmin); $fakedUrl = str_replace($baseSite, $baseAdmin, $url->loc); $fakedUrl = str_replace($sitemapLinksLang, '', $fakedUrl); // Now instantiate and parse the faked url from backend, replacing the uri base it will be = site $uriObject = JURI::getInstance((string) $fakedUrl); $parseUri = $siteRouter->parse($uriObject); // Now augment the object to show informations $url->component = isset($parseUri['option']) ? $parseUri['option'] : JText::_('COM_JMAP_ANALYZER_NOINFO'); $url->menuId = isset($parseUri['Itemid']) ? $parseUri['Itemid'] : JText::_('COM_JMAP_ANALYZER_NOINFO'); $url->menuTitle = JText::_('COM_JMAP_ANALYZER_NOINFO'); // Translate human menu if (isset($parseUri['Itemid'])) { $query = "SELECT" . $this->_db->quoteName('title') . "\n FROM #__menu" . "\n WHERE " . $this->_db->quoteName('id') . " = " . (int) $parseUri['Itemid']; $menuTitle = $this->_db->setQuery($query)->loadResult(); $url->menuTitle = $menuTitle; } } // Perform array sorting if any $order = $this->getState('order', null); $jmapAnalyzerOrderDir = $this->getState('order_dir', 'asc'); if ($order == 'httpstatus') { function cmpAsc($a, $b) { return (int) $a->httpstatus < (int) $b->httpstatus ? -1 : 1; } function cmpDesc($a, $b) { return (int) $a->httpstatus > (int) $b->httpstatus ? -1 : 1; } $callbackName = $jmapAnalyzerOrderDir == 'asc' ? 'cmpAsc' : 'cmpDesc'; usort($loadedSitemapXML, $callbackName); } if ($order == 'link') { function cmpAsc($a, $b) { return strcmp($a->loc, $b->loc); } function cmpDesc($a, $b) { return strcmp($b->loc, $a->loc); } $callbackName = $jmapAnalyzerOrderDir == 'asc' ? 'cmpAsc' : 'cmpDesc'; usort($loadedSitemapXML, $callbackName); } } else { throw new JMapException(JText::sprintf('COM_JMAP_ANALYZER_EMPTY_SITEMAP', $this->_db->getErrorMsg()), 'notice'); } } catch (JMapException $e) { $this->app->enqueueMessage($e->getMessage(), $e->getErrorLevel()); $loadedSitemapXML = array(); } catch (Exception $e) { $jmapException = new JMapException($e->getMessage(), 'error'); $this->app->enqueueMessage($jmapException->getMessage(), $jmapException->getErrorLevel()); $loadedSitemapXML = array(); } return $loadedSitemapXML; }