Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1046556
D120.id371.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Jun 28, 8:41 PM
Size
33 KB
Mime Type
text/x-diff
Expires
Sun, Jun 29, 8:41 PM (7 h, 33 m)
Engine
blob
Format
Raw Data
Handle
676576
Attached To
D120: INP-1470 - Google Sitemap support
D120.id371.diff
View Options
Index: core/admin_templates/categories/categories_edit.tpl
===================================================================
--- core/admin_templates/categories/categories_edit.tpl
+++ core/admin_templates/categories/categories_edit.tpl
@@ -78,7 +78,7 @@
<inp2:m_RenderElement name="inp_edit_category" prefix="c" field="SymLinkCategoryId" title="la_fld_SymLinkCategoryId"/>
- <inp2:m_RenderElement name="subsection" prefix="c" fields="Title,MenuTitle,FriendlyURL,ParentId,Template,FormId,FormSubmittedTemplate,IsMenu,Type,Protected" title="la_section_Page"/>
+ <inp2:m_RenderElement name="subsection" prefix="c" fields="Title,MenuTitle,FriendlyURL,ParentId,Template,FormId,FormSubmittedTemplate,IsMenu,Type,Protected,IncludeInSitemap" title="la_section_Page"/>
<inp2:m_RenderElement name="inp_edit_box_ml" prefix="c" field="Title" title="la_fld_PageContentTitle" size="40"/>
<inp2:m_RenderElement name="inp_edit_box_ml" prefix="c" field="MenuTitle" title="la_fld_PageMentTitle" size="40"/>
@@ -147,6 +147,8 @@
<inp2:m_RenderElement name="inp_label" prefix="c" field="Protected" title="la_fld_Protected"/>
</inp2:m_if>
+ <inp2:m_RenderElement name="inp_edit_checkbox" prefix="c" field="IncludeInSitemap" title="la_fld_IncludeInSitemap"/>
+
<inp2:m_RenderElement name="subsection" prefix="c" fields="Status,DirectLinkEnabled,RequireSSL,RequireLogin,NewItem,EditorsPick,Priority,UseMenuIconUrl,MenuIconUrl,UseExternalUrl,ExternalUrl,CreatedOn,MetaKeywords,MetaDescription,IndexTools" title="la_section_Properties"/>
<inp2:m_if check="c_PageEditable">
<inp2:m_RenderElement name="inp_edit_radio" prefix="c" field="Status" title="la_fld_Status"/>
@@ -315,4 +317,4 @@
disable_categories('<inp2:c_InputName name="ParentId"/>', <inp2:c_AllowedCategoriesJSON/>);
</script>
-<inp2:m_include t="incs/footer"/>
\ No newline at end of file
+<inp2:m_include t="incs/footer"/>
Index: core/install/cache/class_structure.php
===================================================================
--- core/install/cache/class_structure.php
+++ core/install/cache/class_structure.php
@@ -167,6 +167,7 @@
'SiteConfigTagProcessor' => '/core/units/sections/site_config_tp.php',
'SiteDomainEventHandler' => '/core/units/site_domains/site_domain_eh.php',
'SiteHelper' => '/core/units/helpers/site_helper.php',
+ 'SitemapHelper' => '/core/units/helpers/sitemap_helper.php',
'SkinEventHandler' => '/core/units/skins/skin_eh.php',
'SkinHelper' => '/core/units/helpers/skin_helper.php',
'SpamHelper' => '/core/units/helpers/spam_helper.php',
Index: core/install/english.lang
===================================================================
--- core/install/english.lang
+++ core/install/english.lang
@@ -208,6 +208,7 @@
<PHRASE Label="la_config_SessionBrowserSignatureCheck" Module="Core" Type="1">U2Vzc2lvbiBTZWN1cml0eSBDaGVjayBiYXNlZCBvbiBCcm93c2VyIFNpZ25hdHVyZQ==</PHRASE>
<PHRASE Label="la_config_SessionCookieDomains" Module="Core" Type="1">U2Vzc2lvbiBDb29raWUgRG9tYWlucyAoc2luZ2xlIGRvbWFpbiBwZXIgbGluZSk=</PHRASE>
<PHRASE Label="la_config_SessionIPAddressCheck" Module="Core" Type="1">U2Vzc2lvbiBTZWN1cml0eSBDaGVjayBiYXNlZCBvbiBJUA==</PHRASE>
+ <PHRASE Label="la_config_SitemapInvisibleCategoriesCatalogVisibility" Module="Core" Type="1">U2VjdGlvbnMgaGlkZGVuIGZyb20gU2l0ZW1hcA==</PHRASE>
<PHRASE Label="la_config_SiteNameSubTitle" Module="Core" Type="1">V2Vic2l0ZSBTdWJ0aXRsZQ==</PHRASE>
<PHRASE Label="la_config_site_zone" Module="Core" Type="1">VGltZSB6b25lIG9mIHRoZSBzaXRl</PHRASE>
<PHRASE Label="la_config_SoftMaintenanceTemplate" Module="Core" Type="1" Hint="VGhpcyB0ZW1wbGF0ZSB3aWxsIGJlIHNob3duIHRvIHRoZSBGcm9udCBFbmQgdXNlcnMgd2hlbiBTb2Z0IE1haW50ZW5hbmNlIG1vZGUgaXMgYWN0aXZlLg==">VGVtcGxhdGUgZm9yIFNvZnQgTWFpbnRlbmFuY2U=</PHRASE>
@@ -489,6 +490,7 @@
<PHRASE Label="la_fld_ImportOverwrite" Module="Core" Type="1" Hint="RW5hYmxpbmcgdGhpcyBvcHRpb24gd2lsbCB1bmRvIGFueSBjaGFuZ2VzIHlvdSBoYXZlIG1hZGUgdG8gZXhpc3RpbmcgcGhyYXNlcw==">T3ZlcndyaXRlIEV4aXN0aW5nIFBocmFzZXM=</PHRASE>
<PHRASE Label="la_fld_ImportSynced" Module="Core" Type="1" Hint="RW5hYmxpbmcgdGhpcyBvcHRpb24gd2lsbCBtYXJrIGFsbCBuZXcgbGFiZWxzIGZyb20gdGhpcyBsYW5ndWFnZSBwYWNrIHN5bmNlZCB3aXRoIGFsbCBvdGhlciBsYW5ndWFnZXMu">SW1wb3J0IE5ldyBQaHJhc2VzIGFzIFN5bmNlZA==</PHRASE>
<PHRASE Label="la_fld_IncludeFieldTitles" Module="Core" Type="1">SW5jbHVkZSBmaWVsZCB0aXRsZXM=</PHRASE>
+ <PHRASE Label="la_fld_IncludeInSitemap" Module="Core" Type="1">SW5jbHVkZSBpbiBTaXRlbWFw</PHRASE>
<PHRASE Label="la_fld_IncludeSublevels" Module="Core" Type="1" Column="SW5jbHVkZSBTdWJsZXZlbHM=">SW5jbHVkZSBTdWJsZXZlbHM=</PHRASE>
<PHRASE Label="la_fld_InputDateFormat" Module="Core" Type="1">SW5wdXQgRGF0ZSBGb3JtYXQ=</PHRASE>
<PHRASE Label="la_fld_InputTimeFormat" Module="Core" Type="1">SW5wdXQgVGltZSBGb3JtYXQ=</PHRASE>
@@ -840,6 +842,7 @@
<PHRASE Label="la_opt_Address" Module="Core" Type="1">QWRkcmVzcw==</PHRASE>
<PHRASE Label="la_opt_After" Module="Core" Type="1">QWZ0ZXI=</PHRASE>
<PHRASE Label="la_opt_Allow" Module="Core" Type="1">QWxsb3c=</PHRASE>
+ <PHRASE Label="la_opt_AlwaysShownInCatalog" Module="Core" Type="1">QWx3YXlzIFNob3duIGluIENhdGFsb2c=</PHRASE>
<PHRASE Label="la_opt_AnimationCustom" Module="Core" Type="1">Q3VzdG9t</PHRASE>
<PHRASE Label="la_opt_AnimationFade" Module="Core" Type="1">RmFkZQ==</PHRASE>
<PHRASE Label="la_opt_AnimationSlide" Module="Core" Type="1">U2xpZGU=</PHRASE>
@@ -980,6 +983,7 @@
<PHRASE Label="la_opt_Semicolon" Module="Core" Type="1">U2VtaS1jb2xvbg==</PHRASE>
<PHRASE Label="la_opt_Sent" Module="Core" Type="1">U2VudA==</PHRASE>
<PHRASE Label="la_opt_September" Module="Core" Type="1">U2VwdGVtYmVy</PHRASE>
+ <PHRASE Label="la_opt_ShownInCatalogOnlyInDebugMode" Module="Core" Type="1">U2hvd24gaW4gQ2F0YWxvZyBPbmx5IGluIERlYnVnIE1vZGU=</PHRASE>
<PHRASE Label="la_opt_Silent" Module="Core" Type="1">U2lsZW50</PHRASE>
<PHRASE Label="la_opt_Skipped" Module="Core" Type="1">U2tpcHBlZA==</PHRASE>
<PHRASE Label="la_opt_Space" Module="Core" Type="1">U3BhY2U=</PHRASE>
Index: core/install/install_data.sql
===================================================================
--- core/install/install_data.sql
+++ core/install/install_data.sql
@@ -13,10 +13,11 @@
INSERT INTO SystemSettings VALUES(DEFAULT, 'RecycleBinFolder', '', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_RecycleBinFolder', 'text', NULL, NULL, 10.10, 0, 0, NULL);
INSERT INTO SystemSettings VALUES(DEFAULT, 'CheckViewPermissionsInCatalog', '0', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_CheckViewPermissionsInCatalog', 'radio', NULL, '1=la_Yes||0=la_No', 10.11, 0, 1, 'hint:la_config_CheckViewPermissionsInCatalog');
INSERT INTO SystemSettings VALUES(DEFAULT, 'CategoryPermissionRebuildMode', '3', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_CategoryPermissionRebuildMode', 'select', NULL, '1=la_opt_Manual||2=la_opt_Silent||3=la_opt_Automatic', 10.12, 0, 0, 'hint:la_config_CategoryPermissionRebuildMode');
-INSERT INTO SystemSettings VALUES(DEFAULT, 'FilenameSpecialCharReplacement', '-', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_FilenameSpecialCharReplacement', 'select', NULL, '_=+_||-=+-', 10.13, 0, 0, NULL);
-INSERT INTO SystemSettings VALUES(DEFAULT, 'Search_MinKeyword_Length', '3', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_Search_MinKeyword_Length', 'text', NULL, NULL, 10.14, 0, 0, NULL);
-INSERT INTO SystemSettings VALUES(DEFAULT, 'ExcludeTemplateSectionsFromSearch', '0', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_ExcludeTemplateSectionsFromSearch', 'checkbox', '', '', 10.15, 0, 0, NULL);
-INSERT INTO SystemSettings VALUES(DEFAULT, 'UpdateCountersOnFilterChange', '1', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_UpdateCountersOnFilterChange', 'checkbox', '', '', 10.16, 0, 0, NULL);
+INSERT INTO SystemSettings VALUES(DEFAULT, 'SitemapInvisibleCategoriesCatalogVisibility', '1', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_SitemapInvisibleCategoriesCatalogVisibility', 'radio', NULL, '1=la_opt_AlwaysShownInCatalog||2=la_opt_ShownInCatalogOnlyInDebugMode', 10.13, 0, 0, '');
+INSERT INTO SystemSettings VALUES(DEFAULT, 'FilenameSpecialCharReplacement', '-', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_FilenameSpecialCharReplacement', 'select', NULL, '_=+_||-=+-', 10.14, 0, 0, NULL);
+INSERT INTO SystemSettings VALUES(DEFAULT, 'Search_MinKeyword_Length', '3', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_Search_MinKeyword_Length', 'text', NULL, NULL, 10.15, 0, 0, NULL);
+INSERT INTO SystemSettings VALUES(DEFAULT, 'ExcludeTemplateSectionsFromSearch', '0', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_ExcludeTemplateSectionsFromSearch', 'checkbox', '', '', 10.16, 0, 0, NULL);
+INSERT INTO SystemSettings VALUES(DEFAULT, 'UpdateCountersOnFilterChange', '1', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_UpdateCountersOnFilterChange', 'checkbox', '', '', 10.17, 0, 0, NULL);
INSERT INTO SystemSettings VALUES(DEFAULT, 'Category_MetaKey', '', 'In-Portal', 'in-portal:configure_categories', 'la_Text_MetaInfo', 'la_category_metakey', 'textarea', '', '', 20.01, 0, 1, NULL);
INSERT INTO SystemSettings VALUES(DEFAULT, 'Category_MetaDesc', '', 'In-Portal', 'in-portal:configure_categories', 'la_Text_MetaInfo', 'la_category_metadesc', 'textarea', '', '', 20.02, 0, 1, NULL);
Index: core/install/install_schema.sql
===================================================================
--- core/install/install_schema.sql
+++ core/install/install_schema.sql
@@ -597,6 +597,7 @@
PromoBlockGroupId int(10) unsigned NOT NULL DEFAULT '0',
RequireSSL tinyint(4) NOT NULL DEFAULT '0',
RequireLogin tinyint(4) NOT NULL DEFAULT '0',
+ IncludeInSitemap tinyint(4) NOT NULL DEFAULT '1',
PRIMARY KEY (CategoryId),
UNIQUE KEY ResourceId (ResourceId),
KEY ParentId (ParentId),
Index: core/install/upgrades.sql
===================================================================
--- core/install/upgrades.sql
+++ core/install/upgrades.sql
@@ -3026,3 +3026,9 @@
UPDATE Modules
SET ClassNamespace = 'InPortal\\Core'
WHERE `Name` IN ('Core', 'In-Portal');
+
+ALTER TABLE Categories ADD IncludeInSitemap TINYINT(4) NOT NULL DEFAULT 1;
+UPDATE SystemSettings
+SET DisplayOrder = ROUND(DisplayOrder + 0.01, 2)
+WHERE (DisplayOrder BETWEEN 10.13 AND 10.18) AND (ModuleOwner = 'In-Portal') AND (Section = 'in-portal:configure_categories');
+INSERT INTO SystemSettings VALUES(DEFAULT, 'SitemapInvisibleCategoriesCatalogVisibility', '1', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_SitemapInvisibleCategoriesCatalogVisibility', 'radio', NULL, '1=la_opt_AlwaysShownInCatalog||2=la_opt_ShownInCatalogOnlyInDebugMode', 10.13, 0, 0, '');
Index: core/kernel/constants.php
===================================================================
--- core/kernel/constants.php
+++ core/kernel/constants.php
@@ -233,3 +233,9 @@
const STATUS_SKIPPED = 3;
}
+
+ class NonSitemapSectionVisibility
+ {
+ const ALWAYS_SHOWN = 1;
+ const SHOWN_ONLY_IN_DEBUG_MODE = 2;
+ }
Index: core/units/admin/admin_config.php
===================================================================
--- core/units/admin/admin_config.php
+++ core/units/admin/admin_config.php
@@ -29,6 +29,7 @@
'ScheduledTasks' => Array (
'optimize_performance' => Array ('EventName' => 'OnOptimizePerformance', 'RunSchedule' => '0 0 * * *'),
'pre_resize_images' => Array ('EventName' => 'OnPreResizeImages', 'RunSchedule' => '0 * * * *'),
+ 'generate_sitemap' => array('EventName' => 'OnGenerateSitemap', 'RunSchedule' => '0 0 * * *'),
),
'TitlePresets' => Array (
@@ -98,4 +99,4 @@
'Content' => Array ('type' => 'string', 'default' => ''),
),
-);
\ No newline at end of file
+);
Index: core/units/admin/admin_events_handler.php
===================================================================
--- core/units/admin/admin_events_handler.php
+++ core/units/admin/admin_events_handler.php
@@ -1220,6 +1220,21 @@
}
}
}
+
+ /**
+ * [SCHEDULED TASK] Generate sitemaps.
+ *
+ * @param kEvent $event Event object.
+ *
+ * @return void
+ */
+ protected function OnGenerateSitemap(kEvent $event)
+ {
+ /** @var $sitemap_helper SitemapHelper */
+ $sitemap_helper = $this->Application->recallObject('SitemapHelper');
+ $sitemap_helper->build();
+ }
+
}
/**
Index: core/units/categories/categories_config.php
===================================================================
--- core/units/categories/categories_config.php
+++ core/units/categories/categories_config.php
@@ -426,6 +426,11 @@
'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
'not_null' => 1, 'default' => 0
),
+ 'IncludeInSitemap' => array(
+ 'type' => 'int',
+ 'formatter' => 'kOptionsFormatter', 'options' => array(1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
+ 'not_null' => 1, 'default' => 1,
+ ),
),
'VirtualFields' => Array (
@@ -540,4 +545,4 @@
'DefaultSorting1Dir' => 'Category_Sortorder',
'DefaultSorting2Dir' => 'Category_Sortorder2',
),
-);
\ No newline at end of file
+);
Index: core/units/categories/categories_event_handler.php
===================================================================
--- core/units/categories/categories_event_handler.php
+++ core/units/categories/categories_event_handler.php
@@ -549,6 +549,28 @@
/* @var $search_helper kSearchHelper */
$search_helper->SetComplexFilter($event, $type_clauses, implode(',', $types), implode(',', $except_types));
+ $this->setSitemapFilter($object);
+ }
+
+ /**
+ * Sets sitemap filter
+ *
+ * @param kDBList $object Object.
+ *
+ * @return void
+ */
+ protected function setSitemapFilter(kDBList $object)
+ {
+ if ( !$this->Application->isAdmin ) {
+ return;
+ }
+
+ /** @var CategoryHelper $category_helper */
+ $category_helper = $this->Application->recallObject('CategoryHelper');
+
+ if ( $category_helper->showSitemapOnlyCategories() ) {
+ $object->addFilter('sitemap_filter', '%1$s.IncludeInSitemap = 1');
+ }
}
/**
@@ -2017,6 +2039,10 @@
// this will override any global "m_cat_id"
$page_category = $this->_getParentCategoryFromPath(explode('||', $template_info['section']), $root_category, $theme_id);
}
+
+ if ( array_key_exists('in_sitemap', $template_info) ) {
+ $in_sitemap = $template_info['in_sitemap'] ? 1 : 0;
+ }
}
}
else {
@@ -2045,6 +2071,10 @@
$object->SetDBField('l' . $primary_language . '_Description', $page_description);
$object->SetDBField('l' . $current_language . '_Description', $page_description);
+ if ( isset($in_sitemap) ) {
+ $object->SetDBField('IncludeInSitemap', $in_sitemap);
+ }
+
return $object->Create();
}
Index: core/units/helpers/category_helper.php
===================================================================
--- core/units/helpers/category_helper.php
+++ core/units/helpers/category_helper.php
@@ -31,6 +31,22 @@
var $_primaryLanguageId = false;
/**
+ * Show sitemap only categories.
+ *
+ * @var boolean
+ */
+ protected $showSitemapOnlyCategories = false;
+
+ /**
+ * Set showSitemapOnlyCategories property
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->showSitemapOnlyCategories = $this->showSitemapOnlyCategories();
+ }
+
+ /**
* Returns module information based on given module name or current category (relative to module root categories)
*
* @param Array $params
@@ -98,6 +114,10 @@
return Array ();
}
+ if ( !$data['IncludeInSitemap'] && $this->showSitemapOnlyCategories ) {
+ return array();
+ }
+
$category_language = $data['l' . $language_id . '_Name'] ? $language_id : $this->_primaryLanguageId;
$ret = Array ($parent_category_id => str_repeat('—', $level) . ' ' . $data['l' . $category_language . '_Name']);
@@ -113,6 +133,22 @@
}
/**
+ * Checks if need show sitemap only categories
+ *
+ * @return boolean
+ */
+ public function showSitemapOnlyCategories()
+ {
+ if ( $this->Application->isDebugMode() ) {
+ return false;
+ }
+
+ $visibility = $this->Application->ConfigValue('SitemapInvisibleCategoriesCatalogVisibility');
+
+ return $visibility == NonSitemapSectionVisibility::SHOWN_ONLY_IN_DEBUG_MODE;
+ }
+
+ /**
* Returns information about children under parent path (recursive)
*
* @param int $parent_category_id
@@ -131,7 +167,8 @@
$fields[] = 'l' . $language_id . '_Name';
}
- $sql = 'SELECT CategoryId AS id, ' . implode(', ', $fields) . ', ParentId, Template, ThemeId
+ $sql = 'SELECT CategoryId AS id, ' . implode(', ', $fields) . ',
+ ParentId, Template, ThemeId, IncludeInSitemap
FROM ' . TABLE_PREFIX . 'Categories
ORDER BY Priority DESC';
$items = $this->Conn->Query($sql, 'id');
@@ -378,4 +415,4 @@
return $text;
}
- }
\ No newline at end of file
+ }
Index: core/units/helpers/helpers_config.php
===================================================================
--- core/units/helpers/helpers_config.php
+++ core/units/helpers/helpers_config.php
@@ -66,6 +66,7 @@
Array ('pseudo' => 'MimeDecodeHelper', 'class' => 'MimeDecodeHelper', 'file' => 'mime_decode_helper.php', 'build_event' => ''),
Array ('pseudo' => 'UserHelper', 'class' => 'UserHelper', 'file' => 'user_helper.php', 'build_event' => ''),
Array ('pseudo' => 'SiteHelper', 'class' => 'SiteHelper', 'file' => 'site_helper.php', 'build_event' => ''),
+ array('pseudo' => 'SitemapHelper', 'class' => 'SitemapHelper', 'file' => 'sitemap_helper.php', 'build_event' => ''),
Array ('pseudo' => 'DeploymentHelper', 'class' => 'DeploymentHelper', 'file' => 'deployment_helper.php', 'build_event' => ''),
Array ('pseudo' => 'PageHelper', 'class' => 'PageHelper', 'file' => 'page_helper.php', 'build_event' => ''),
Index: core/units/helpers/sitemap_helper.php
===================================================================
--- /dev/null
+++ core/units/helpers/sitemap_helper.php
@@ -0,0 +1,487 @@
+<?php
+
+class SitemapHelper extends kHelper
+{
+
+ /**
+ * Base folder, where given site-domain sitemaps will be saved.
+ *
+ * @var string
+ */
+ protected $baseFolder = '';
+
+ /**
+ * Files list.
+ *
+ * @var string[]
+ */
+ protected $files;
+
+ /**
+ * Current file.
+ *
+ * @var string
+ */
+ protected $curFile;
+
+ /**
+ * Current file size.
+ *
+ * @var integer
+ */
+ protected $curFileSize;
+
+ /**
+ * Quantity if current file urls.
+ *
+ * @var integer
+ */
+ protected $curFileURLs = 0;
+
+ /**
+ * Number of current file.
+ *
+ * @var integer
+ */
+ protected $curFileNumber = 0;
+
+ /**
+ * Sitemap prefix.
+ *
+ * @var string
+ */
+ protected $sitemapPrefix = '';
+
+ /**
+ * Maximum file size.
+ *
+ * @var integer
+ */
+ protected $maxFileSize = 10000000;
+
+ /**
+ * Maximum quantity of urls.
+ *
+ * @var integer
+ */
+ protected $maxURLs = 50000;
+
+ /**
+ * Gap.
+ *
+ * @var integer
+ */
+ protected $gap = 500;
+
+ /**
+ * Last sitemap modification date in W3C date format
+ *
+ * @var string
+ */
+ protected $lastmod;
+
+ /**
+ * Prefix of links.
+ *
+ * @var string
+ */
+ protected $linkPrefix = '';
+
+ /**
+ * Init helper.
+ *
+ * @param string $sitemap_prefix Sitemap prefix.
+ */
+ public function __construct($sitemap_prefix = '')
+ {
+ parent::__construct();
+
+ $this->sitemapPrefix = $this->prepareSitemapPrefix($sitemap_prefix);
+
+ // Link from Admin to Front-end.
+ $this->linkPrefix = $this->Application->isAdmin ? '_FRONT_END_' : '';
+
+ // XML documents are usually long.
+ set_time_limit(0);
+ ini_set('memory_limit', -1);
+
+ $this->lastmod = date('Y-m-d\TH:i:s') . preg_replace('/([0-9]{2})$/', ':$1', date('O')); // W3C date format.
+
+ $this->baseFolder = WRITEABLE . '/user_files/sitemaps';
+
+ /** @var $file_helper FileHelper */
+ $file_helper = $this->Application->recallObject('FileHelper');
+
+ $file_helper->CheckFolder($this->baseFolder);
+ }
+
+ /**
+ * Write sitemap header.
+ *
+ * @return void
+ */
+ protected function startFile()
+ {
+ $this->curFileSize = 0;
+ $this->curFileURLs = 0;
+ $this->curFile = fopen(
+ $this->baseFolder . '/' . $this->sitemapPrefix . ++$this->curFileNumber . '.xml.tmp',
+ 'w'
+ );
+
+ $this->write("<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n", false);
+ }
+
+ /**
+ * Write sitemap footer.
+ *
+ * @return void
+ */
+ protected function endFile()
+ {
+ fwrite($this->curFile, "</urlset>\n");
+ fclose($this->curFile);
+ }
+
+ /**
+ * Write sitemap item.
+ *
+ * @param string $data Item data.
+ * @param boolean $increase_urls If yes, increase urls of file.
+ *
+ * @return void
+ */
+ protected function write($data, $increase_urls = true)
+ {
+ $len = strlen($data);
+
+ if ( $this->curFileSize + $len + $this->gap > $this->maxFileSize || $this->curFileURLs > $this->maxURLs ) {
+ $this->endFile();
+ $this->startFile();
+ }
+
+ fwrite($this->curFile, $data);
+ $this->curFileSize += $len;
+
+ if ( $increase_urls ) {
+ $this->curFileURLs++;
+ }
+ }
+
+ /**
+ * Build sitemap file.
+ *
+ * @return void
+ */
+ public function build()
+ {
+ $this->startFile();
+
+ $this->addCategories();
+
+ /*
+ $this->addCategoryItems('l');
+ $this->addCategoryItems('n');
+ $this->addCategoryItems('bb');
+ */
+
+ $this->finalize();
+ }
+
+ /**
+ * Write URL to sitemap.
+ *
+ * @param string $url URL.
+ * @param integer $modified_on Modified timestamp.
+ * @param integer $priority Priority.
+ *
+ * @return void
+ */
+ protected function writeURL($url, $modified_on = null, $priority = null)
+ {
+ $lastmod = $this->lastmod;
+
+ if ( isset($modified_on) ) {
+ $lastmod = date('Y-m-d\TH:i:s', $modified_on) .
+ preg_replace('/([0-9]{2})$/', ':$1', date('O', $modified_on)); // W3C date format.
+ }
+
+ if ( isset($priority) ) {
+ $priority_row = <<<PRIORITY_XML
+
+<priority>{$priority}</priority>
+PRIORITY_XML;
+ }
+ else {
+ $priority_row = '';
+ }
+
+ $block = <<<END_XML
+<url>
+<loc>{$url}</loc>
+<lastmod>{$lastmod}</lastmod>{$priority_row}
+</url>
+
+END_XML;
+ $this->write($block);
+ }
+
+ /**
+ * Add all categories to sitemap
+ *
+ * @return void
+ */
+ protected function addCategories()
+ {
+ // Get top categories.
+ $tag_params = array('per_page' => -1, 'parent_cat_id' => 'any', 'skip_counting' => 1);
+
+ $category_list = $this->Application->recallObject('c', 'c_List', $tag_params);
+ /* @var $category_list kDBList */
+ $category_list->addFilter('status_filter', '%1$s.Status = ' . STATUS_ACTIVE);
+ $category_list->addFilter('sitemap_filter', '%1$s.IncludeInSitemap = 1');
+ $category_list->setOrderFields(array(array('ParentPath', 'ASC')));
+
+ $categories = $this->Conn->Query($category_list->GetSelectSQL());
+ $category_helper = $this->Application->recallObject('CategoryHelper');
+ /* @var $category_helper CategoryHelper */
+
+ $template_mapping = $category_helper->getTemplateMapping();
+
+ foreach ( $categories as $category_data ) {
+ // Add link to top category.
+ $category_id = $category_data['CategoryId'];
+
+ if ( isset($template_mapping['id:' . $category_id]) ) {
+ $template = $template_mapping['id:' . $category_id];
+ }
+ else {
+ $template = '__default__';
+ }
+
+ $url_params = $this->getUrlParams(array(
+ 'm_cat_id' => $category_id,
+ 'pass_category' => 1,
+ ));
+
+ $this->writeURL($this->Application->HREF($template, $this->linkPrefix, $url_params));
+ }
+ }
+
+ /**
+ * Add all items from allowed categories.
+ *
+ * @param string $prefix Item prefix.
+ * @param integer $top_category Top category id.
+ * @param string $where_clause Additional filter.
+ *
+ * @return void
+ */
+ protected function addCategoryItems($prefix, $top_category = null, $where_clause = null)
+ {
+ $id_field = $this->Application->getUnitOption($prefix, 'IDField');
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+
+ $sql = 'SELECT item.' . $id_field . ', ci.CategoryId
+ FROM ' . $table_name . ' item
+ JOIN ' . TABLE_PREFIX . 'CategoryItems ci ON ci.ItemResourceId = item.ResourceId AND ci.PrimaryCat = 1
+ JOIN ' . TABLE_PREFIX . 'Categories c ON c.CategoryId = ci.CategoryId
+ WHERE item.Status = ' . STATUS_ACTIVE . ' AND c.Status = ' . STATUS_ACTIVE;
+
+ if ( isset($top_category) ) {
+ list ($tree_left, $tree_right) = $this->Application->getTreeIndex($top_category);
+ $sql .= ' AND c.TreeLeft BETWEEN ' . $tree_left . ' AND ' . $tree_right;
+ }
+
+ if ( isset($where_clause) ) {
+ $sql .= ' AND ' . $where_clause;
+ }
+
+ $items = $this->Conn->Query($sql);
+
+ foreach ( $items as $item_data ) {
+ $url_params = $this->getUrlParams(array(
+ 'm_cat_id' => $item_data['CategoryId'],
+ 'pass_category' => 1,
+ $prefix . '_id' => $item_data[$id_field],
+ 'pass' => 'm,' . $prefix,
+ ));
+
+ $this->writeURL($this->Application->HREF('__default__', $this->linkPrefix, $url_params));
+ }
+ }
+
+ /**
+ * Finalize sitemap file.
+ *
+ * @return void
+ */
+ protected function finalize()
+ {
+ $this->endFile();
+
+ $files = glob($this->baseFolder . '/' . $this->sitemapPrefix . '*.xml.gz');
+
+ if ( file_exists($this->baseFolder . '/' . $this->sitemapPrefix . '.xml.gz') ) {
+ unlink($this->baseFolder . '/' . $this->sitemapPrefix . '.xml.gz');
+ }
+
+ if ( $this->curFileNumber > 1 ) {
+ $master = fopen($this->baseFolder . '/' . $this->sitemapPrefix . '.xml', 'w');
+ fwrite($master, "<sitemapindex>\n");
+
+ $site = preg_replace(
+ '/^' . preg_quote(FULL_PATH, '/') . '/',
+ rtrim($this->Application->BaseURL('', 0), '/'),
+ $this->baseFolder,
+ 1
+ );
+
+ for ( $i = 1; $i <= $this->curFileNumber; $i++ ) {
+ $block = <<<END_XML
+<sitemap>
+<loc>{$site}/{$this->sitemapPrefix}{$i}.xml.gz</loc>
+</sitemap>
+
+END_XML;
+ fwrite($master, $block);
+
+ if ( file_exists($this->baseFolder . '/' . $this->sitemapPrefix . $i . '.xml.gz') ) {
+ unlink($this->baseFolder . '/' . $this->sitemapPrefix . $i . '.xml.gz');
+ }
+
+ rename(
+ $this->baseFolder . '/' . $this->sitemapPrefix . $i . '.xml.tmp',
+ $this->baseFolder . '/' . $this->sitemapPrefix . $i . '.xml'
+ );
+ shell_exec('gzip ' . $this->baseFolder . '/' . $this->sitemapPrefix . $i . '.xml');
+
+ if ( $files ) {
+ $key = array_search($this->baseFolder . '/' . $this->sitemapPrefix . $i . '.xml.gz', $files);
+
+ if ( $key !== false ) {
+ unset($files[$key]);
+ }
+ }
+ }
+
+ fwrite($master, "</sitemapindex>\n");
+ fclose($master);
+ }
+ else {
+ // Single sitemap file.
+ rename(
+ $this->baseFolder . '/' . $this->sitemapPrefix . '1.xml.tmp',
+ $this->baseFolder . '/' . $this->sitemapPrefix . '.xml'
+ );
+ }
+
+ shell_exec('gzip ' . $this->baseFolder . '/' . $this->sitemapPrefix . '.xml');
+
+ if ( $files ) {
+ $key = array_search($this->baseFolder . '/' . $this->sitemapPrefix . '.xml.gz', $files);
+
+ if ( $key !== false ) {
+ unset($files[$key]);
+ }
+
+ // Removing files left.
+ foreach ( $files as $a_file ) {
+ unlink($a_file);
+ }
+ }
+ }
+
+ /**
+ * Generate index of sitemap files.
+ *
+ * @param array $sitemap_prefixes List of sitemap prefixes.
+ *
+ * @return void
+ */
+ public function generateSitemapIndex(array $sitemap_prefixes)
+ {
+ $sitemap_prefixes[] = 'static';
+
+ $file = new SplFileObject($this->baseFolder . '/' . $this->sitemapPrefix . '.xml.tmp', 'w');
+ $file->fwrite('<sitemapindex>' . PHP_EOL);
+
+ $site = preg_replace(
+ '/^' . preg_quote(FULL_PATH, '/') . '/',
+ rtrim($this->Application->BaseURL('', 0), '/'),
+ $this->baseFolder,
+ 1
+ );
+
+ foreach ( $sitemap_prefixes as $sitemap_prefix ) {
+ $sitemap_file = '';
+ $sitemap_prefix = $this->prepareSitemapPrefix($sitemap_prefix);
+
+ if ( file_exists($this->baseFolder . '/' . $sitemap_prefix . '.xml.gz') ) {
+ $sitemap_file = $sitemap_prefix . '.xml.gz';
+ }
+ elseif ( file_exists($this->baseFolder . '/' . $sitemap_prefix . '.xml') ) {
+ $sitemap_file = $sitemap_prefix . '.xml';
+ }
+
+ if ( $sitemap_file ) {
+ $block = <<<END_XML
+<sitemap>
+<loc>{$site}/{$sitemap_file}</loc>
+</sitemap>
+
+END_XML;
+ $file->fwrite($block);
+ }
+ }
+
+ $file->fwrite('</sitemapindex>');
+
+ if ( file_exists($this->baseFolder . '/sitemap.xml') ) {
+ unlink($this->baseFolder . '/sitemap.xml');
+ }
+
+ rename($file->getPathname(), $this->baseFolder . '/sitemap.xml');
+ }
+
+ /**
+ * Prepare sitemap prefix.
+ *
+ * @param string $sitemap_prefix Prefix.
+ *
+ * @return string
+ */
+ protected function prepareSitemapPrefix($sitemap_prefix)
+ {
+ return $sitemap_prefix ? 'sitemap.' . trim($sitemap_prefix, '.') : 'sitemap';
+ }
+
+ /**
+ * Returns base url params.
+ *
+ * @param array $custom_params Params.
+ *
+ * @return array
+ */
+ protected function getUrlParams(array $custom_params = array())
+ {
+ $url_params = array(
+ 'pass' => 'm',
+ '__SSL__' => 0, // To change BaseURL too.
+ '__NO_SID__' => 1, // Don't add sid on domain change.
+ );
+
+ if ( $this->Application->isAdmin ) {
+ // Link from Admin to Front-end.
+ if ( $this->Application->ConfigValue('UseModRewrite') ) {
+ $url_params['__MOD_REWRITE__'] = 1;
+ }
+ else {
+ $url_params['index_file'] = 'index.php';
+ }
+ }
+
+ return array_merge($url_params, $custom_params);
+ }
+
+}
Index: core/units/helpers/themes_helper.php
===================================================================
--- core/units/helpers/themes_helper.php
+++ core/units/helpers/themes_helper.php
@@ -475,47 +475,90 @@
return $this->parseTemplateMetaInfo($template_file);
}
- function parseTemplateMetaInfo($template_file)
+ /**
+ * Parses template meta info
+ *
+ * @param string $template_file Template file.
+ *
+ * @return array
+ * @throws Exception When invalid template meta tag is found.
+ */
+ public function parseTemplateMetaInfo($template_file)
{
- if (!file_exists($template_file)) {
+ if ( !file_exists($template_file) ) {
// when template without info it's placed in top category
- return Array ();
+ return array();
}
$template_data = file_get_contents($template_file);
- if (substr($template_data, 0, 6) == '<!--##') {
- // template starts with comment in such format
- /*<!--##
- <NAME></NAME>
- <DESC></DESC>
- <SECTION>||</SECTION>
- ##-->*/
-
- $comment_end = strpos($template_data, '##-->');
- if ($comment_end === false) {
- // badly formatted comment
- return Array ();
- }
-
- $comment = trim( substr($template_data, 6, $comment_end - 6) );
- if (preg_match_all('/<(NAME|DESC|SECTION)>(.*?)<\/(NAME|DESC|SECTION)>/is', $comment, $regs)) {
- $ret = Array ();
- foreach ($regs[1] as $param_order => $param_name) {
- $ret[ strtolower($param_name) ] = trim($regs[2][$param_order]);
- }
+ // template starts with comment in such format
+ /*<!--##
+ <NAME></NAME>
+ <DESC></DESC>
+ <SECTION>||</SECTION>
+ ##-->*/
- if (array_key_exists('section', $ret) && $ret['section']) {
- $category_path = explode('||', $ret['section']);
- $category_path = array_map('trim', $category_path);
- $ret['section'] = implode('||', $category_path);
- }
+ if ( substr($template_data, 0, 6) != '<!--##' ) {
+ return array();
+ }
+
+ $comment_end = strpos($template_data, '##-->');
+
+ if ( $comment_end === false ) {
+ // Badly formatted comment.
+ return array();
+ }
+
+ $ret = array();
+ $comment = trim(substr($template_data, 6, $comment_end - 6));
+ $allowed_settings = array('name', 'desc', 'section', 'in_sitemap');
- return $ret;
+ /** @var SimpleXMLElement[] $meta_info */
+ $meta_info = simplexml_load_string('<meta_info>' . $comment . '</meta_info>');
+
+ if ( $meta_info === false ) {
+ // Malformed XML. SimpleXML will print an error itself.
+ return array();
+ }
+
+ foreach ( $meta_info as $setting ) {
+ $setting_name = strtolower($setting->getName());
+
+ if ( !in_array($setting_name, $allowed_settings) ) {
+ trigger_error(
+ 'Setting "' . $setting_name . '" not supported in "' . $template_file . '" template',
+ E_USER_WARNING
+ );
+ continue;
+ }
+
+ $ret[$setting_name] = trim($setting);
+ }
+
+ if ( array_key_exists('section', $ret) && $ret['section'] ) {
+ $category_path = explode('||', $ret['section']);
+ $category_path = array_map('trim', $category_path);
+ $ret['section'] = implode('||', $category_path);
+ }
+
+ if ( array_key_exists('in_sitemap', $ret) ) {
+ $value = strtolower($ret['in_sitemap']);
+
+ if ( strlen($value) == 0 || in_array($value, array('yes', 'true', '1')) ) {
+ $ret['in_sitemap'] = true;
+ }
+ elseif ( in_array($value, array('no', 'false', '0')) ) {
+ $ret['in_sitemap'] = false;
+ }
+ else {
+ $error_msg = 'The "IN_SITEMAP" setting in "' . $template_file . '" template ';
+ $error_msg .= 'has unsupported value. Please use "yes" or "no".';
+ throw new Exception($error_msg);
}
}
- return Array ();
+ return $ret;
}
/**
Index: core/units/structure/structure_config.php
===================================================================
--- core/units/structure/structure_config.php
+++ core/units/structure/structure_config.php
@@ -215,7 +215,12 @@
'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
'not_null' => 1, 'default' => 1
),
- 'DirectLinkAuthKey' => Array ('type' => 'string', 'max_len' => 20, 'not_null' => 1, 'default' => '')
+ 'DirectLinkAuthKey' => array('type' => 'string', 'max_len' => 20, 'not_null' => 1, 'default' => ''),
+ 'IncludeInSitemap' => array(
+ 'type' => 'int',
+ 'formatter' => 'kOptionsFormatter', 'options' => array(1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
+ 'not_null' => 1, 'default' => 1,
+ ),
),
'VirtualFields' => Array (
@@ -274,4 +279,4 @@
'DefaultSorting1Dir' => 'Category_Sortorder',
'DefaultSorting2Dir' => 'Category_Sortorder2',
),
-);
\ No newline at end of file
+);
Event Timeline
Log In to Comment