Page MenuHomeIn-Portal Phabricator

D11.id260.diff
No OneTemporary

File Metadata

Created
Wed, Feb 26, 9:02 AM

D11.id260.diff

Index: core/admin_templates/themes/themes_list.tpl
===================================================================
--- core/admin_templates/themes/themes_list.tpl
+++ core/admin_templates/themes/themes_list.tpl
@@ -7,6 +7,12 @@
<tr>
<td>
<script type="text/javascript">
+ function copy_from_theme($theme_id)
+ {
+ set_hidden_field('copy_from', $theme_id);
+ submit_event('theme','OnCopyData');
+ }
+
//do not rename - this function is used in default grid for double click!
function edit()
{
@@ -24,7 +30,20 @@
function() {
std_delete_items('theme')
} ) );
-
+ a_toolbar.AddButton( new ToolBarButton('copy', '<inp2:m_phrase label="la_ToolTip_CopyDataFrom" escape="1"/>',
+ function() {
+ themes_menu = menuMgr.createMenu(rs('copy_from_theme_menu'));
+ themes_menu.applyBorder(false, false, false, false);
+ themes_menu.dropShadow("none");
+ themes_menu.showIcon = true;
+
+ <inp2:m_DefineElement name="theme_elem">
+ themes_menu.addItem(rs('theme<inp2:Field name="ThemeId"/>'),'<inp2:Field name="Name" js_escape="1"/>','javascript:copy_from_theme(<inp2:Field name="ThemeId"/>);');
+ </inp2:m_DefineElement>
+ <inp2:theme.all_PrintList render_as="theme_elem" per_page="-1"/>
+ renderMenus();
+ nls_showMenu(rs('copy_from_theme_menu'), a_toolbar.GetButtonImage('copy'));
+ } ) );
a_toolbar.AddButton( new ToolBarSeparator('sep1') );
@@ -54,9 +73,21 @@
</tbody>
</table>
+<inp2:m_if check="m_Get" var="not_matched_theme_ids">
+ <inp2:m_RenderElement design="form_message">
+ <inp2:m_Phrase label="la_error_SomeOfThemesWerentMatched"/>
+ <inp2:m_DefineElement name="theme_item">
+ <li><inp2:Field name="Name"/></li>
+ </inp2:m_DefineElement>
+ <ul>
+ <inp2:theme.not-matched_PrintList render_as="theme_item" per_page="-1"/>
+ </ul>
+ </inp2:m_RenderElement>
+</inp2:m_if>
+
<inp2:m_RenderElement name="grid" PrefixSpecial="theme" IdField="ThemeId" grid="Default"/>
<script type="text/javascript">
- Grids['theme'].SetDependantToolbarButtons( new Array('edit', 'delete', 'setprimary') );
+ Grids['theme'].SetDependantToolbarButtons( new Array('edit', 'delete', 'setprimary', 'copy') );
</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
@@ -36,6 +36,7 @@
'ConfigurationItem' => '/core/units/configuration/configuration.php',
'ConfigurationTagProcessor' => '/core/units/configuration/configuration_tag_processor.php',
'ConfigurationValidator' => '/core/units/configuration/configuration_validator.php',
+ 'ContentBlockCopier' => '/core/units/helpers/content_block_copier.php',
'ContentEventHandler' => '/core/units/content/content_eh.php',
'ContentTagProcessor' => '/core/units/content/content_tp.php',
'CoreUpgrades' => '/core/install/upgrades.php',
@@ -546,6 +547,13 @@
0 => 'kValidator',
),
),
+ 'ContentBlockCopier' => array(
+ 'type' => 1,
+ 'modifiers' => 0,
+ 'extends' => array(
+ 0 => 'kBase',
+ ),
+ ),
'ContentEventHandler' => array(
'type' => 1,
'modifiers' => 0,
Index: core/install/english.lang
===================================================================
--- core/install/english.lang
+++ core/install/english.lang
@@ -288,6 +288,7 @@
<PHRASE Label="la_error_RequiredColumnsMissing" Module="Core" Type="1">cmVxdWlyZWQgY29sdW1ucyBtaXNzaW5n</PHRASE>
<PHRASE Label="la_error_RootCategoriesDelete" Module="Core" Type="1">Um9vdCBzZWN0aW9uIG9mIHRoZSBtb2R1bGUocykgY2FuIG5vdCBiZSBkZWxldGVkIQ==</PHRASE>
<PHRASE Label="la_error_SelectItemToMove" Module="Core" Type="1">U2VsZWN0IGF0IGxlYXN0IG9uZSBpdGVtIHRvIG1vdmU=</PHRASE>
+ <PHRASE Label="la_error_SomeOfThemesWerentMatched" Module="Core" Type="1">U29tZSBvZiB0aGVtZXMgd2VyZW4ndCBtYXRjaGVk</PHRASE>
<PHRASE Label="la_error_TemplateFileMissing" Module="Core" Type="1">VGVtcGxhdGUgZmlsZSBpcyBtaXNzaW5n</PHRASE>
<PHRASE Label="la_error_TemporaryTableCopyingFailed" Module="Core" Type="1">Q29weWluZyBvcGVyYXRpb24gaW4gVGVtcG9yYXJ5IHRhYmxlcyBoYXMgZmFpbGVkLiBQbGVhc2UgY29udGFjdCB3ZWJzaXRlIGFkbWluaXN0cmF0b3Iu</PHRASE>
<PHRASE Label="la_error_unique" Module="Core" Type="1">UmVjb3JkIGlzIG5vdCB1bmlxdWU=</PHRASE>
@@ -1611,6 +1612,7 @@
<PHRASE Label="la_ToolTip_CloneUser" Module="Core" Type="1">Q2xvbmUgVXNlcnM=</PHRASE>
<PHRASE Label="la_ToolTip_close" Module="Core" Type="1">Q2xvc2U=</PHRASE>
<PHRASE Label="la_ToolTip_Copy" Module="Core" Type="1">Q29weQ==</PHRASE>
+ <PHRASE Label="la_ToolTip_CopyDataFrom" Module="Core" Type="1">Q29weSBEYXRhIEZyb20=</PHRASE>
<PHRASE Label="la_ToolTip_Cut" Module="Core" Type="1">Q3V0</PHRASE>
<PHRASE Label="la_ToolTip_Decline" Module="Core" Type="1">RGVjbGluZQ==</PHRASE>
<PHRASE Label="la_ToolTip_Delete" Module="Core" Type="1">RGVsZXRl</PHRASE>
Index: core/units/helpers/content_block_copier.php
===================================================================
--- /dev/null
+++ core/units/helpers/content_block_copier.php
@@ -0,0 +1,191 @@
+<?php
+/**
+* @version $Id$
+* @package In-Portal
+* @copyright Copyright (C) 1997 - 2015 Intechnic. All rights reserved.
+* @license GNU/GPL
+* In-Portal is Open Source software.
+* This means that this software may have been modified pursuant
+* the GNU General Public License, and as distributed it includes
+* or is derivative of works licensed under the GNU General Public License
+* or other free or open source software licenses.
+* See http://www.in-portal.org/license for copyright notices and details.
+*/
+
+defined('FULL_PATH') or die('restricted access!');
+
+class ContentBlockCopier extends kBase
+{
+
+ /**
+ * Id of theme to copy from.
+ *
+ * @var integer
+ */
+ protected $sourceThemeId;
+
+ /**
+ * Id of theme to copy to.
+ *
+ * @var integer
+ */
+ protected $targetThemeId;
+
+ /**
+ * Categories table name.
+ *
+ * @var string
+ */
+ protected $categoriesTableName;
+
+ /**
+ * Content table name.
+ *
+ * @var string
+ */
+ protected $contentTableName;
+
+ /**
+ * Page revision table name.
+ *
+ * @var string
+ */
+ protected $pageRevisionTableName;
+
+ /**
+ * Sets source theme id, prepares used table names.
+ *
+ * @param integer $source_theme_id Source Theme Id.
+ * @param integer $target_theme_id Target Theme Id.
+ *
+ * @throws LogicException When source and target themes match.
+ */
+ public function __construct($source_theme_id, $target_theme_id)
+ {
+ parent::__construct();
+
+ if ( $source_theme_id == $target_theme_id ) {
+ throw new LogicException('Source theme must differ from target theme');
+ }
+
+ $this->sourceThemeId = $source_theme_id;
+ $this->targetThemeId = $target_theme_id;
+ $this->categoriesTableName = $this->Application->getUnitConfig('c')->getTableName();
+ $this->contentTableName = $this->Application->getUnitConfig('content')->getTableName();
+ $this->pageRevisionTableName = $this->Application->getUnitConfig('page-revision')->getTableName();
+ }
+
+ /**
+ * Copies content blocks from source theme to target theme.
+ *
+ * @return boolean
+ */
+ public function copy()
+ {
+ $matches = $this->getMatchingTemplates();
+
+ if ( !$matches ) {
+ return false;
+ }
+
+ $this->deleteTargetBlocks();
+
+ foreach ( $matches as $match ) {
+ $where_clause = array(
+ 'PageId = ' . $match['SourceCategoryId'],
+ 'RevisionNumber = ' . $match['LiveRevisionNumber'],
+ );
+
+ $sql = 'SELECT *
+ FROM ' . $this->pageRevisionTableName . '
+ WHERE (' . implode(') AND (', $where_clause) . ')';
+ $revision_data = $this->Conn->GetRow($sql);
+
+ if ( !$revision_data ) {
+ continue;
+ }
+
+ $revision_data['PageId'] = $match['TargetCategoryId'];
+ $revision_data['RevisionNumber'] = 1;
+ $live_revision_id = $revision_data['RevisionId'];
+ unset($revision_data['RevisionId']);
+ $this->Conn->doInsert($revision_data, $this->pageRevisionTableName);
+
+ $new_revision_id = $this->Conn->getInsertID();
+
+ $this->Conn->doUpdate(
+ array('LiveRevisionNumber' => 1),
+ $this->categoriesTableName,
+ 'CategoryId = ' . $match['TargetCategoryId']
+ );
+
+ $sql = 'SELECT *
+ FROM ' . $this->contentTableName . '
+ WHERE PageId = ' . $match['SourceCategoryId'] . ' AND RevisionId = ' . $live_revision_id;
+ $blocks = $this->Conn->Query($sql);
+
+ foreach ( $blocks as $block_data ) {
+ $block_data['RevisionId'] = $new_revision_id;
+ $block_data['PageId'] = $match['TargetCategoryId'];
+ unset($block_data['PageContentId']);
+ $this->Conn->doInsert($block_data, $this->contentTableName);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Determines matching templates.
+ *
+ * @return array
+ */
+ protected function getMatchingTemplates()
+ {
+ $on_clause = array(
+ 'target.ThemeId = ' . $this->targetThemeId,
+ 'target.Template = source.Template',
+ 'target.Type = source.Type',
+ );
+
+ $sql = 'SELECT
+ source.LiveRevisionNumber,
+ source.CategoryId AS SourceCategoryId,
+ target.CategoryId AS TargetCategoryId,
+ source.Template
+ FROM ' . $this->categoriesTableName . ' source
+ JOIN ' . $this->categoriesTableName . ' target
+ ON (' . implode(') AND (', $on_clause) . ')
+ WHERE source.ThemeId = ' . $this->sourceThemeId . ' AND source.Type = 2';
+
+ return $this->Conn->Query($sql);
+ }
+
+ /**
+ * Delete all target blocks.
+ *
+ * @return void
+ */
+ protected function deleteTargetBlocks()
+ {
+ $sql = 'SELECT CategoryId
+ FROM ' . $this->categoriesTableName . '
+ WHERE ThemeId = ' . $this->targetThemeId . ' AND Type = 2';
+ $target_categories = $this->Conn->GetCol($sql);
+
+ if ( !$target_categories ) {
+ return;
+ }
+
+ $target_categories = implode(',', $target_categories);
+
+ $sql = 'DELETE FROM ' . $this->contentTableName . '
+ WHERE PageId IN (' . $target_categories . ')';
+ $this->Conn->Query($sql);
+
+ $sql = 'DELETE FROM ' . $this->pageRevisionTableName . '
+ WHERE PageId IN (' . $target_categories . ')';
+ $this->Conn->Query($sql);
+ }
+
+}
Index: core/units/themes/themes_config.php
===================================================================
--- core/units/themes/themes_config.php
+++ core/units/themes/themes_config.php
@@ -59,7 +59,7 @@
'themes_list' => Array (
'prefixes' => Array ('theme_List'), 'format' => "!la_tab_Themes!",
- 'toolbar_buttons' => Array ('new_item', 'edit', 'delete', 'setprimary', 'refresh', 'view', 'dbl-click'),
+ 'toolbar_buttons' => array('new_item', 'edit', 'delete', 'setprimary', 'refresh', 'view', 'dbl-click', 'copy'),
),
'themes_edit_general' => Array (
@@ -161,4 +161,4 @@
),
),
),
-);
\ No newline at end of file
+);
Index: core/units/themes/themes_eh.php
===================================================================
--- core/units/themes/themes_eh.php
+++ core/units/themes/themes_eh.php
@@ -27,8 +27,9 @@
{
parent::mapPermissions();
- $permissions = Array(
- 'OnChangeTheme' => Array('self' => true),
+ $permissions = array(
+ 'OnChangeTheme' => array('self' => true),
+ 'OnCopyData' => array('self' => 'edit'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
@@ -220,6 +221,36 @@
}
/**
+ * Copies content blocks between themes.
+ *
+ * @param kEvent $event Event.
+ *
+ * @return void
+ */
+ protected function OnCopyData(kEvent $event)
+ {
+ $ids = $this->StoreSelectedIDs($event);
+ $not_matched_theme_ids = array();
+ $source_theme_id = (int)$this->Application->GetVar('copy_from');
+
+ foreach ( $ids as $target_theme_id ) {
+ /** @var ContentBlockCopier $content_block_copier */
+ $content_block_copier = $this->Application->makeClass(
+ 'ContentBlockCopier',
+ array($source_theme_id, $target_theme_id)
+ );
+
+ if ( !$content_block_copier->copy() ) {
+ $not_matched_theme_ids[] = $target_theme_id;
+ }
+ }
+
+ if ( count($not_matched_theme_ids) ) {
+ $event->setRedirectParam('not_matched_theme_ids', implode(',', $not_matched_theme_ids));
+ }
+ }
+
+ /**
* Apply system filter to themes list
*
* @param kEvent $event
@@ -254,5 +285,17 @@
$themes = explode('|', substr($themes, 1, -1));
$object->addFilter('domain_filter', '%1$s.ThemeId IN (' . implode(',', $themes) . ')');
}
+
+ if ( $event->Special == 'not-matched' ) {
+ $ids = $this->Application->GetVar('not_matched_theme_ids');
+ $ids = array_filter(array_map('intval', explode(',', $ids)));
+
+ if ( $ids ) {
+ $object->addFilter('not_matched_filter', '%1$s.ThemeId IN (' . implode(',', $ids) . ')');
+ }
+ else {
+ $object->addFilter('not_matched_filter', 'FALSE');
+ }
+ }
}
}

Event Timeline