Esempio n. 1
0
 /**
  * Display the XML sitemap
  * @access public
  * @return void
  */
 function display($tpl = null)
 {
     $document = $this->document;
     $document->setMimeEncoding('application/xml');
     $session = JFactory::getSession();
     // Call by cache handler get no params, so recover from model state
     if (!$tpl) {
         $tpl = $this->getModel()->getState('documentformat');
     }
     $this->data = $this->get('SitemapData');
     $this->cparams = $this->getModel()->getState('cparams');
     // Transport wrapper
     $this->HTTPClient = new JMapHttp(null, $this->cparams);
     $this->outputtedLinksBuffer = array();
     // Reload $this->outputtedVideosBuffer from previous session if process_status === run, AKA an ongoing JS AJAX precaching is running
     $this->outputtedVideosBuffer = $this->app->input->get('process_status', null) === 'run' ? $session->get('com_jmap.videos_buffer') : array();
     $this->application = JFactory::getApplication();
     $this->xslt = $this->getModel()->getState('xslt');
     $this->videoApisEndpoints = array('youtube' => 'https://gdata.youtube.com/feeds/api/videos/%s?v=2&alt=json', 'vimeo' => 'http://vimeo.com/api/v2/video/%s.json', 'dailymotion' => 'https://api.dailymotion.com/video/%s?fields=title,duration,description,thumbnail_360_url');
     $uriInstance = JURI::getInstance();
     $customHttpPort = trim($this->cparams->get('custom_http_port', ''));
     $getPort = $customHttpPort ? ':' . $customHttpPort : '';
     $customDomain = trim($this->cparams->get('custom_sitemap_domain', ''));
     $getDomain = $customDomain ? rtrim($customDomain, '/') : rtrim($uriInstance->getScheme() . '://' . $uriInstance->getHost(), '/');
     if ($this->cparams->get('append_livesite', true)) {
         $this->liveSite = rtrim($getDomain . $getPort, '/');
     } else {
         $this->liveSite = null;
     }
     // Crawler live site management
     if ($this->cparams->get('sh404sef_multilanguage', 0) && JMapLanguageMultilang::isEnabled()) {
         $lang = '/' . $this->app->input->get('lang');
         // Check if sh404sef insert language code param is off, otherwise the result would be doubled language chunk in liveSiteCrawler
         $sh404SefParams = JComponentHelper::getParams('com_sh404sef');
         if ($sh404SefParams->get('shInsertLanguageCode', 0) || !$sh404SefParams->get('Enabled', 1)) {
             $lang = null;
         }
         $this->liveSiteCrawler = rtrim($getDomain . $getPort . $lang, '/');
     } else {
         $this->liveSiteCrawler = rtrim($getDomain . $getPort, '/');
     }
     // Add include path
     $this->addTemplatePath(JPATH_COMPONENT . '/views/sitemap/tmpl/videos');
     $this->setLayout('default');
     parent::display($tpl);
     // Assign $this->outputtedVideosBuffer for next session if process_status == start/run
     if (in_array($this->app->input->get('process_status', null), array('start', 'run'))) {
         $session->set('com_jmap.videos_buffer', $this->outputtedVideosBuffer);
     }
     // Delete $this->outputtedVideosBuffer session if process_status == end
     if ($this->app->input->get('process_status', null) === 'end') {
         $session->clear('com_jmap.videos_buffer');
     }
 }
Esempio n. 2
0
 /**
  * Display the XML sitemap
  * @access public
  * @return void
  */
 function display($tpl = null)
 {
     $document = $this->document;
     $document->setMimeEncoding('application/xml');
     // Call by cache handler get no params, so recover from model state
     if (!$tpl) {
         $tpl = $this->getModel()->getState('documentformat');
     }
     $this->data = $this->get('SitemapData');
     $this->cparams = $this->getModel()->getState('cparams');
     // Transport wrapper
     $this->HTTPClient = new JMapHttp(null, $this->cparams);
     $this->outputtedLinksBuffer = array();
     $this->application = JFactory::getApplication();
     $this->xslt = $this->getModel()->getState('xslt');
     // Set regex for the images crawler
     $this->mainImagesRegex = $this->cparams->get('regex_images_crawler', 'advanced') == 'standard' ? '/(<img)([^>])*(src=["\']([^"\']+)["\'])([^>])*/i' : '/(<img)([^>])*(src=["\']?([^"\']+\\.(jpg|jpeg|gif|png))["\']?)([^>])*/i';
     $uriInstance = JURI::getInstance();
     $customHttpPort = trim($this->cparams->get('custom_http_port', ''));
     $getPort = $customHttpPort ? ':' . $customHttpPort : '';
     $customDomain = trim($this->cparams->get('custom_sitemap_domain', ''));
     $getDomain = $customDomain ? rtrim($customDomain, '/') : rtrim($uriInstance->getScheme() . '://' . $uriInstance->getHost(), '/');
     if ($this->cparams->get('append_livesite', true)) {
         $this->liveSite = rtrim($getDomain . $getPort, '/');
     } else {
         $this->liveSite = null;
     }
     // Crawler live site management
     if ($this->cparams->get('sh404sef_multilanguage', 0) && JMapLanguageMultilang::isEnabled()) {
         $lang = '/' . $this->app->input->get('lang');
         // Check if sh404sef insert language code param is off, otherwise the result would be doubled language chunk in liveSiteCrawler
         $sh404SefParams = JComponentHelper::getParams('com_sh404sef');
         if ($sh404SefParams->get('shInsertLanguageCode', 0) || !$sh404SefParams->get('Enabled', 1)) {
             $lang = null;
         }
         $this->liveSiteCrawler = rtrim($getDomain . $getPort . $lang, '/');
     } else {
         $this->liveSiteCrawler = rtrim($getDomain . $getPort, '/');
     }
     $this->setLayout('default');
     parent::display($tpl);
 }
}
$additionalQueryStringParams = trim($additionalQueryStringParams, ',');
if ($additionalQueryStringParams) {
    $additionalQueryStringParams = '&' . preg_replace('/,\\s*/i', '&', $additionalQueryStringParams);
    $additionalQueryStringParams = preg_replace('/\\s+/i', '', $additionalQueryStringParams);
}
$targetOption = $this->source->chunks->option;
$targetViewName = $this->sourceparams->get('view', null);
$targetView = $targetViewName ? '&view=' . $targetViewName : null;
// Supported adapters for Router Helper
$supportedRouterHelperAdapters = array('com_k2' => false, 'com_easyblog' => false, 'com_contact' => false, 'com_weblinks' => false, 'com_newsfeeds' => false, 'com_hwdmediashare' => false, 'com_eventbooking' => false, 'com_edocman' => false, 'com_phocadownload' => false, 'com_ezrealty' => false, 'com_iproperty' => false, 'com_djcatalog2' => false, 'com_jomestate' => false, 'com_eshop' => false, 'com_jomdirectory' => false);
$supportedRouterHelperAdaptersPaths = array('com_eventbooking' => 'helper', 'com_edocman' => 'helper');
$supportedRouterHelperAdaptersFiles = array('com_easyblog' => 'router');
// Adapter for com_eshop
if ($targetOption == 'com_eshop') {
    if (version_compare(JVERSION, '3.0', 'ge') && JMapLanguageMultilang::isEnabled()) {
        $supportedRouterHelperAdaptersFiles['com_eshop'] = 'routev3';
    }
}
if (array_key_exists($targetOption, $supportedRouterHelperAdapters)) {
    $folderPath = array_key_exists($targetOption, $supportedRouterHelperAdaptersPaths) ? $supportedRouterHelperAdaptersPaths[$targetOption] : 'helpers';
    $filePath = array_key_exists($targetOption, $supportedRouterHelperAdaptersFiles) ? $supportedRouterHelperAdaptersFiles[$targetOption] : 'route';
    if (file_exists(JPATH_SITE . '/components/' . $targetOption . '/' . $folderPath . '/' . $filePath . '.php')) {
        include_once JPATH_SITE . '/components/' . $targetOption . '/' . $folderPath . '/' . $filePath . '.php';
        $supportedRouterHelperAdapters[$targetOption] = true;
        $liveSite = $this->liveSite;
    }
}
// Fallback identifiers
$titleIdentifier = !empty($this->source->chunks->titlefield_as) ? $this->source->chunks->titlefield_as : $this->source->chunks->titlefield;
$idIdentifier = !empty($this->source->chunks->idfield_as) ? $this->source->chunks->idfield_as : $this->source->chunks->id;
Esempio n. 4
0
 /**
  * Route save single article to the corresponding SEF link
  *
  * @access private
  * @return string
  */
 private function routeArticleToSefMenu($articleID, $catID, $language, $article)
 {
     // Try to route the article to a single article menu item view
     $helperRouteClass = $this->context['class'];
     $classMethod = $this->context['method'];
     // Route helper native by component, com_content, com_k2
     if (!isset($this->context['routing'])) {
         $articleHelperRoute = $helperRouteClass::$classMethod($articleID, $catID, $language);
     } else {
         // Route helper universal JSitemap, com_zoo
         $articleHelperRoute = $helperRouteClass::$classMethod($article->option, $article->view, $article->id, $article->catid, null);
         if ($articleHelperRoute) {
             $articleHelperRoute = '?Itemid=' . $articleHelperRoute;
         }
     }
     // Extract Itemid from the helper routed URL
     $extractedItemid = preg_match('/Itemid=\\d+/i', $articleHelperRoute, $result);
     if (isset($result[0])) {
         // Get uri instance avoidng subdomains already included in the routing chunks
         $uriInstance = JUri::getInstance();
         $resourceLiveSite = rtrim($uriInstance->getScheme() . '://' . $uriInstance->getHost(), '/');
         $extractedItemid = $result[0];
         $siteRouter = JRouterSite::getInstance('site', array('mode' => JROUTER_MODE_SEF));
         $articleMenuRouted = $siteRouter->build('?' . $extractedItemid)->toString();
         // Check if multilanguage is enabled
         if (JMapLanguageMultilang::isEnabled()) {
             if ($language != '*') {
                 // New language manager instance
                 $languageManager = JMapLanguageMultilang::getInstance($language);
             } else {
                 // Get the default language tag
                 // New language manager instance
                 $languageManager = JMapLanguageMultilang::getInstance();
             }
             // Extract the language tag
             $localeTag = $languageManager->getLocale();
             $sefTag = $localeTag[4];
             $articleMenuRouted = str_replace('/administrator', '/' . $sefTag, $articleMenuRouted);
         } else {
             $articleMenuRouted = str_replace('/administrator', '', $articleMenuRouted);
         }
         $articleMenuRouted = preg_match('/http/i', $articleMenuRouted) ? $articleMenuRouted : $resourceLiveSite . '/' . ltrim($articleMenuRouted, '/');
         return $articleMenuRouted;
     } else {
         // Check if routing is valid otherwise throw exception
         throw new RuntimeException(JText::_('COM_JMAP_AUTOPING_ERROR_NOSEFROUTE_FOUND'));
     }
 }
Esempio n. 5
0
 /**
  * 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;
 }