Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1175856
D11.id149.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
Sun, Oct 5, 4:19 AM
Size
11 KB
Mime Type
text/x-diff
Expires
Mon, Oct 6, 4:19 AM (20 h, 11 m)
Engine
blob
Format
Raw Data
Handle
762708
Attached To
D11: INP-1313 - Add support for copying content blocks between themes
D11.id149.diff
View Options
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/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,164 @@
+<?php
+
+
+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.
+ */
+ public function __construct($source_theme_id)
+ {
+ parent::__construct();
+
+ $this->sourceThemeId = $source_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.
+ *
+ * @param integer $target_theme_id Target Theme Id.
+ *
+ * @return boolean
+ */
+ public function copyTo($target_theme_id)
+ {
+ if ( $target_theme_id == $this->sourceThemeId ) {
+ return true;
+ }
+
+ $this->targetThemeId = $target_theme_id;
+
+ $matches = $this->getMatchingTemplates();
+
+ if ( !$matches ) {
+ return false;
+ }
+
+ $this->deleteTargetBlocks();
+
+ foreach ( $matches as $match ) {
+ if ( !$match['LiveRevisionNumber'] ) {
+ continue;
+ }
+
+ $where_clause = array(
+ 'PageId = ' . $match['SourceCategoryId'],
+ 'RevisionNumber =' . $match['LiveRevisionNumber'],
+ );
+
+ $sql = 'SELECT *
+ FROM ' . $this->pageRevisionTableName . '
+ WHERE (' . implode(') AND (', $where_clause) . ')';
+ $revision = $this->Conn->GetRow($sql);
+
+ if ( !$revision ) {
+ continue;
+ }
+
+ $revision['PageId'] = $match['TargetCategoryId'];
+ $revision['RevisionNumber'] = 1;
+ $live_revision_id = $revision['RevisionId'];
+ unset($revision['RevisionId']);
+ $this->Conn->doInsert($revision, $this->pageRevisionTableName);
+ $new_revision_id = $this->Conn->getInsertID();
+
+ $sql = 'UPDATE ' . $this->categoriesTableName . '
+ SET LiveRevisionNumber = 1
+ WHERE CategoryId = ' . $match['TargetCategoryId'];
+ $this->Conn->Query($sql);
+
+ $sql = 'SELECT *
+ FROM ' . $this->contentTableName . '
+ WHERE PageId = ' . $match['SourceCategoryId'] . ' AND RevisionId =' . $live_revision_id;
+ $blocks = $this->Conn->Query($sql);
+
+ foreach ( $blocks as $block ) {
+ $block['RevisionId'] = $new_revision_id;
+ $block['PageId'] = $match['TargetCategoryId'];
+ unset($block['PageContentId']);
+ $this->Conn->doInsert($block, $this->contentTableName);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Determines matching templates.
+ *
+ * @return array
+ */
+ protected function getMatchingTemplates()
+ {
+ $sql = 'SELECT source.LiveRevisionNumber, source.CategoryId AS SourceCategoryId,
+ target.CategoryId AS TargetCategoryId, source.Template
+ FROM ' . $this->categoriesTableName . ' source
+ LEFT JOIN ' . $this->categoriesTableName . ' target
+ ON target.ThemeId = ' . $this->targetThemeId . ' AND target.Template = source.Template
+ WHERE source.ThemeId = ' . $this->sourceThemeId . '
+ HAVING NOT ISNULL(TargetCategoryId)';
+
+ return $this->Conn->Query($sql);
+ }
+
+ /**
+ * Delete all target blocks.
+ *
+ * @return void
+ */
+ protected function deleteTargetBlocks()
+ {
+ $sql = 'SELECT CategoryId
+ FROM ' . $this->categoriesTableName . '
+ WHERE ThemeId = ' . $this->targetThemeId;
+ $target_categories = implode(',', $this->Conn->GetCol($sql));
+ $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/helpers/helpers_config.php
===================================================================
--- core/units/helpers/helpers_config.php
+++ core/units/helpers/helpers_config.php
@@ -74,5 +74,6 @@
Array ('pseudo' => 'AjaxFormHelper', 'class' => 'AjaxFormHelper', 'file' => 'ajax_form_helper.php', 'build_event' => ''),
Array ('pseudo' => 'kCronHelper', 'class' => 'kCronHelper', 'file' => 'cron_helper.php', 'build_event' => ''),
Array ('pseudo' => 'kUploadHelper', 'class' => 'kUploadHelper', 'file' => 'upload_helper.php', 'build_event' => ''),
+ array('pseudo' => 'ContentBlockCopier', 'class' => 'ContentBlockCopier', 'file' => 'content_block_copier.php', 'build_event' => ''),
),
- );
\ No newline at end of file
+ );
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);
@@ -49,6 +50,12 @@
return true;
}
+ if ( $event->Name == 'OnCopyData' ) {
+ if ( $this->Application->isAdminUser ) {
+ return true;
+ }
+ }
+
return parent::CheckPermission($event);
}
@@ -220,6 +227,31 @@
}
/**
+ * Copies content blocks between themes.
+ *
+ * @param kEvent $event Event.
+ *
+ * @return void
+ */
+ protected function OnCopyData(kEvent $event)
+ {
+ $this->StoreSelectedIDs($event);
+ $ids = $this->getSelectedIDs($event);
+ $content_clock_copier = new ContentBlockCopier($this->Application->GetVar('copy_from'));
+ $not_matched_theme_ids = array();
+
+ foreach ( $ids as $target_theme_id ) {
+ if ( !$content_clock_copier->copyTo($target_theme_id) ) {
+ $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 +286,12 @@
$themes = explode('|', substr($themes, 1, -1));
$object->addFilter('domain_filter', '%1$s.ThemeId IN (' . implode(',', $themes) . ')');
}
+
+ if ( $event->Special == 'not-matched' ) {
+ $object->addFilter(
+ 'not_matched_filter',
+ '%1$s.ThemeId IN (' . $this->Application->GetVar('not_matched_theme_ids') . ')'
+ );
+ }
}
}
Event Timeline
Log In to Comment