diff --git a/README.md b/README.md index ef50ea798..7be410712 100644 --- a/README.md +++ b/README.md @@ -126,11 +126,11 @@ Component Builder is mapped as a component in itself on my local development env + *Author*: [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) + *Name*: [Component Builder](http://joomlacomponentbuilder.com) + *First Build*: 30th April, 2015 -+ *Last Build*: 15th April, 2018 ++ *Last Build*: 17th April, 2018 + *Version*: 2.7.5 + *Copyright*: Copyright (C) 2015. All Rights Reserved + *License*: GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html -+ *Line count*: **182585** ++ *Line count*: **182878** + *Field count*: **1012** + *File count*: **1199** + *Folder count*: **193** diff --git a/admin/README.txt b/admin/README.txt index ef50ea798..7be410712 100644 --- a/admin/README.txt +++ b/admin/README.txt @@ -126,11 +126,11 @@ Component Builder is mapped as a component in itself on my local development env + *Author*: [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) + *Name*: [Component Builder](http://joomlacomponentbuilder.com) + *First Build*: 30th April, 2015 -+ *Last Build*: 15th April, 2018 ++ *Last Build*: 17th April, 2018 + *Version*: 2.7.5 + *Copyright*: Copyright (C) 2015. All Rights Reserved + *License*: GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html -+ *Line count*: **182585** ++ *Line count*: **182878** + *Field count*: **1012** + *File count*: **1199** + *Folder count*: **193** diff --git a/admin/access.xml b/admin/access.xml index 2bded6af0..eea0f6756 100644 --- a/admin/access.xml +++ b/admin/access.xml @@ -232,6 +232,7 @@ + diff --git a/admin/controllers/joomla_components.php b/admin/controllers/joomla_components.php index a843fbc7c..d16eab8fd 100644 --- a/admin/controllers/joomla_components.php +++ b/admin/controllers/joomla_components.php @@ -398,6 +398,56 @@ class ComponentbuilderControllerJoomla_components extends JControllerAdmin return; } + public function cloner() + { + // Get the model + $model = $this->getModel('Joomla_components'); + // check if export is allowed for this user. + $model->user = JFactory::getUser(); + if ($model->user->authorise('joomla_component.cloner', 'com_componentbuilder') && $model->user->authorise('core.copy', 'com_componentbuilder')) + { + // Get the input + $input = JFactory::getApplication()->input; + $pks = $input->post->get('cid', array(), 'array'); + // Sanitize the input + JArrayHelper::toInteger($pks); + // check if there is any selections + if (!ComponentbuilderHelper::checkArray($pks)) + { + // Redirect to the list screen with error. + $message = JText::_('COM_COMPONENTBUILDER_NO_COMPONENT_WAS_SELECTED_PLEASE_MAKE_A_SELECTION_OF_ONE_COMPONENT_AND_TRY_AGAIN'); + $this->setRedirect(JRoute::_('index.php?option=com_componentbuilder&view=joomla_components', false), $message, 'error'); + return; + } + // only one component allowed at this time + elseif (count( (array) $pks) !== 1) + { + // Redirect to the list screen with error. + $message = JText::_('COM_COMPONENTBUILDER_ONLY_ONE_COMPONENT_CAN_BE_CLONED_AT_A_TIME_PLEASE_SELECT_ONE_AND_TRY_AGAIN'); + $this->setRedirect(JRoute::_('index.php?option=com_componentbuilder&view=joomla_components', false), $message, 'error'); + return; + } + // set the active type + $model->activeType = 'clone'; + // clone the component and the views and the fields... everything linked to the component. + if ($model->cloner($pks)) + { + // clone was successful + $message = JText::_('COM_COMPONENTBUILDER_THE_COMPONENT_WITH_ALL_LINKED_ADMIN_VIEWS_FIELDS_LINKED_TO_ADMIN_VIEWS_CUSTOM_ADMIN_VIEWS_SITE_VIEWS_TEMPLATES_AND_LAYOUTS_WERE_CLONED_SUCCESSFUL'); + $this->setRedirect(JRoute::_('index.php?option=com_componentbuilder&view=joomla_components', false), $message); + return; + } + // Redirect to the list screen with error. + $message = JText::_('COM_COMPONENTBUILDER_CLONE_FAILED'); + $this->setRedirect(JRoute::_('index.php?option=com_componentbuilder&view=joomla_components', false), $message, 'error'); + return; + } + // Redirect to the list screen with error. + $message = JText::_('COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_CLONE_A_COMPONENT_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_HELP'); + $this->setRedirect(JRoute::_('index.php?option=com_componentbuilder&view=joomla_components', false), $message, 'error'); + return; + } + protected function getApiUser() { // admin area does not have API user, only front-end (so we fallback on login user) diff --git a/admin/language/en-GB/en-GB.com_componentbuilder.ini b/admin/language/en-GB/en-GB.com_componentbuilder.ini index 66b7fa495..9a1ac3110 100644 --- a/admin/language/en-GB/en-GB.com_componentbuilder.ini +++ b/admin/language/en-GB/en-GB.com_componentbuilder.ini @@ -954,6 +954,8 @@ COM_COMPONENTBUILDER_CANCEL="Cancel" COM_COMPONENTBUILDER_CHAIN="Chain" COM_COMPONENTBUILDER_CHECK_YOUR_OWNER_DETAILS_IT_HAS_NOT_BEEN_SET_OPEN_THE_JCB_GLOBAL_OPTIONS_GO_TO_THE_COMPANY_TAB_AND_ADD_THE_CORRECT_COMPANY_DETAILS_THERE="Check your owner details, it has not been set. Open the JCB Global Options, go to the Company tab and add the correct company details there." COM_COMPONENTBUILDER_CLEAR_TMP="Clear tmp" +COM_COMPONENTBUILDER_CLONE="Clone" +COM_COMPONENTBUILDER_CLONE_FAILED="Clone failed!" COM_COMPONENTBUILDER_CLOSE_NEW="Close & New" COM_COMPONENTBUILDER_COMPANY="Company" COM_COMPONENTBUILDER_COMPANY_NAME="Company Name" @@ -4310,6 +4312,8 @@ COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BUILDCOMPSQL_LABEL="MySQL" COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BUILDCOMP_DESCRIPTION="To build the component fields and back-end views dynamically using a mySQL table file." COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BUILDCOMP_LABEL="Build Backend-views Dynamically" COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BUILDER_BACKUP_KEY="Joomla Component Builder - Backup Key" +COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CLONE_BUTTON_ACCESS="Joomla Component Clone Button Access" +COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CLONE_BUTTON_ACCESS_DESC=" Allows the users in this group to access the clone button." COM_COMPONENTBUILDER_JOOMLA_COMPONENT_COMPANYNAME="Companyname" COM_COMPONENTBUILDER_JOOMLA_COMPONENT_COMPANYNAME_DESCRIPTION="Enter Company Name Here" COM_COMPONENTBUILDER_JOOMLA_COMPONENT_COMPANYNAME_HINT="Company Name Here" @@ -5320,6 +5324,7 @@ COM_COMPONENTBUILDER_MATCH_BEHAVIOUR="Match Behaviour" COM_COMPONENTBUILDER_MATCH_FIELD="Match Field" COM_COMPONENTBUILDER_MATCH_OPTIONS="Match Options" COM_COMPONENTBUILDER_MAX_LENGTH_ONLY_FOUR_TEXT_FIELD="Max Length (only 4 text_field)" +COM_COMPONENTBUILDER_MERGE="Merge" COM_COMPONENTBUILDER_MIN_LENGTH_ONLY_FOUR_TEXT_FIELD="Min Length (only 4 text_field)" COM_COMPONENTBUILDER_NAME="Name" COM_COMPONENTBUILDER_NAME_ASC="Name (Asc)" @@ -5337,6 +5342,7 @@ COM_COMPONENTBUILDER_NOT_FOUND_OR_ACCESS_DENIED="Not found or access denied!" COM_COMPONENTBUILDER_NOT_SET="not set" COM_COMPONENTBUILDER_NO_ACCESS_GRANTED="No Access Granted!" COM_COMPONENTBUILDER_NO_COMPONENTS_WERE_SELECTED_PLEASE_MAKE_A_SELECTION_AND_TRY_AGAIN="No components were selected, please make a selection and try again!" +COM_COMPONENTBUILDER_NO_COMPONENT_WAS_SELECTED_PLEASE_MAKE_A_SELECTION_OF_ONE_COMPONENT_AND_TRY_AGAIN="No component was selected, please make a selection of one component and try again!" COM_COMPONENTBUILDER_NO_CRONJOB_PATH_FOUND_FOR_S="No cronjob path found for (%s)" COM_COMPONENTBUILDER_NO_CRONJOB_PATH_FOUND_SINCE_INCORRECT_TYPE_REQUESTED="No cronjob path found since incorrect type requested." COM_COMPONENTBUILDER_NO_DESCRIPTION_FOUND="No description found." @@ -5353,6 +5359,7 @@ COM_COMPONENTBUILDER_NO_S_HAVE_BEEN_LINKED_TO_THIS_VIEW_SOON_AS_THIS_IS_DONE_IT_ COM_COMPONENTBUILDER_NO_TYPE="No Type" COM_COMPONENTBUILDER_NO_VALIDATION_RULES_FOUND="No validation rules found." COM_COMPONENTBUILDER_OFFICIAL_VDM_PACKAGES="Official VDM Packages" +COM_COMPONENTBUILDER_ONLY_ONE_COMPONENT_CAN_BE_CLONED_AT_A_TIME_PLEASE_SELECT_ONE_AND_TRY_AGAIN="Only one component can be cloned at a time, please select one and try again!" COM_COMPONENTBUILDER_ONLY_USE_THE_BNONE_DBB_OPTION_IF_YOU_ARE_PLANNING_ON_TARGETING_THIS_FIELD_WITH_JAVASCRIPTCUSTOM_PHP_TO_MOVE_ITS_VALUE_INTO_ANOTHER_FIELD_THAT_DOES_GET_SAVED_TO_THE_DATABASE="Only use the None DB option if you are planning on targeting this field with JavaScript/Custom PHP to move its value into another field that does get saved to the database." COM_COMPONENTBUILDER_ON_GITHUB="on Github" COM_COMPONENTBUILDER_OPEN="Open" @@ -5571,6 +5578,7 @@ COM_COMPONENTBUILDER_SHOULD_THE_ZIPPED_PACKAGE_OF_THE_COMPONENT_BE_MOVED_TO_THE_ COM_COMPONENTBUILDER_SHOULD_THIS_FIELD_BE_ESCAPED_IN_THE_LIST_VIEW="Should this field be escaped in the list view." COM_COMPONENTBUILDER_SHOULD_WE_BE_SHOWING_MORE_ELABORATE_INFORMATION_DURING_IMPORT="Should we be showing more elaborate information during import." COM_COMPONENTBUILDER_SHOULD_WE_FORCE_THE_UPDATE_OF_ALL_LOCAL_DATA_EVEN_IF_IT_IS_NEWER_THEN_THE_DATA_BEING_IMPORTED="Should we force the update of all local data, even if it is newer then the data being imported." +COM_COMPONENTBUILDER_SHOULD_WE_MERGE_THE_COMPONENTS_WITH_SIMILAR_LOCAL_COMPONENTS_MERGING_THE_COMPONENTS_USE_TO_BE_THE_DEFAULT_BEHAVIOUR_BUT_NOW_YOU_CAN_IMPORT_THE_COMPONENTS_AND_FORCE_IT_NOT_TO_MERGE_THE_FOLLOWING_AREAS_VALIDATION_RULE_FIELDTYPE_SNIPPET_LANGUAGE_LANGUAGE_TRANSLATION_BMUST_AND_WILL_STILLB_MERGE_EVEN_OF_YOUR_SELECTION_IS_BNOB_BECAUSE_OF_THE_SINGULAR_NATURE_OF_THOSE_AREAS="Should we merge the component/s with similar local component/s. Merging the component/s use to be the default behaviour, but now you can import the component/s and force it not to merge. The following areas (validation_rule, fieldtype, snippet, language, language_translation) must and will still merge even of your selection is No, because of the singular nature of those areas." COM_COMPONENTBUILDER_SHOW="Show" COM_COMPONENTBUILDER_SHOW_IN_LIST_VIEW="Show in list view" COM_COMPONENTBUILDER_SINCE_THE_OWNER_DETAILS_ARE_DISPLAYED_DURING_BIMPORT_PROCESSB_BEFORE_ADDING_THE_KEY_THIS_WAY_IF_THE_USERDEV_BDOES_NOTB_HAVE_THE_KEY_THEY_CAN_SEE_BWHERE_TO_GET_ITB="Since the owner details are displayed during import process before adding the key, this way if the user/dev does not have the key they can see where to get it." @@ -6411,6 +6419,7 @@ COM_COMPONENTBUILDER_THE_COMPONENT_FILES_FOLDERS="The component files & folders" COM_COMPONENTBUILDER_THE_COMPONENT_MYSQL_TWEAKS="The component mysql tweaks" COM_COMPONENTBUILDER_THE_COMPONENT_SITE_VIEWS="The component site views" COM_COMPONENTBUILDER_THE_COMPONENT_UPDATES="The component updates" +COM_COMPONENTBUILDER_THE_COMPONENT_WITH_ALL_LINKED_ADMIN_VIEWS_FIELDS_LINKED_TO_ADMIN_VIEWS_CUSTOM_ADMIN_VIEWS_SITE_VIEWS_TEMPLATES_AND_LAYOUTS_WERE_CLONED_SUCCESSFUL="The Component with all linked admin views, fields linked to admin views, custom admin views, site views, templates and layouts were cloned successful!" COM_COMPONENTBUILDER_THE_FTP_CONNECTION_FOR_BSB_COULD_NOT_BE_MADE_PLEASE_CHECK_YOUR_SIGNATURE_DETAILS="The FTP connection for %s could not be made. Please check your signature details!" COM_COMPONENTBUILDER_THE_FTP_SIGNATURE_FOR_BSB_WAS_NOT_WELL_FORMED_PLEASE_CHECK_YOUR_SIGNATURE_DETAILS="The FTP signature for %s was not well formed, please check your signature details!" COM_COMPONENTBUILDER_THE_KEY_OF_THIS_PACKAGE="The key of this package." @@ -6570,6 +6579,7 @@ COM_COMPONENTBUILDER_YOUR_DATA_IS_ENCRYPTED_WITH_A_AES_ONE_HUNDRED_AND_TWENTY_EI COM_COMPONENTBUILDER_YOUR_DATA_IS_ENCRYPTED_WITH_A_AES_ONE_HUNDRED_AND_TWENTY_EIGHT_BIT_ENCRYPTION_USING_THE_ABOVE_THIRTY_TWO_CHARACTER_KEY_WITHOUT_THIS_KEY_IT_WILL_TAKE_THE_CURRENT_TECHNOLOGY_WITH_A_BRUTE_FORCE_ATTACK_METHOD_MORE_THEN_A_HREFHTTPRANDOMIZECOMHOWLONGTOHACKPASS_TARGET_BLANK_TITLEHOW_LONG_TO_HACK_PASSSEVEN_HUNDRED_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZERO_ZEROA_YEARS_TO_CRACK_THEORETICALLY_UNLESS_THEY_HAVE_THIS_KEY_ABOVE_SO_DO_KEEP_IT_SAFE="Your data is encrypted with a AES 128 bit encryption using the above 32 character key. Without this key it will take the current technology with a brute force attack method more then 700 000 000 000 000 000 000 000 000 000 000 years to crack theoretically. Unless they have this key above, so do keep it safe." COM_COMPONENTBUILDER_YOU_CAN_NOW_SELECT_THE_COMPONENT_BZIPB_PACKAGE_YOU_WOULD_LIKE_TO_IMPORTBR_SMALLPLEASE_NOTE_THAT_SMART_COMPONENT_IMPORT_ONLY_WORKS_WITH_THE_FOLLOWING_FORMAT_BZIPBSMALL="You can now select the component zip package you would like to import.
Please note that smart component import only works with the following format: (.zip)" COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_ACCESS_THE_SERVER_DETAILS_BS_DENIEDB_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_INFO="You do not have permission to access the server details (%s - denied), please contact your system administrator for more info." +COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_CLONE_A_COMPONENT_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_HELP="You do not have permission to clone a component, please contact your system administrator for more help." COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_IMPORT_A_COMPONENT_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_HELP="You do not have permission to import a component, please contact your system administrator for more help." COM_COMPONENTBUILDER_YOU_DO_NOT_HAVE_PERMISSION_TO_SHARE_THE_SNIPPETS_PLEASE_CONTACT_YOUR_SYSTEM_ADMINISTRATOR_FOR_MORE_HELP="You do not have permission to share the snippets, please contact your system administrator for more help." COM_COMPONENTBUILDER_YOU_HAVE_S_S_ADDING_MORE_THEN_FIFTY_S_IS_CONSIDERED_BAD_PRACTICE="You have %s %s. Adding more then 50 %s is considered bad practice." diff --git a/admin/language/en-GB/en-GB.com_componentbuilder.sys.ini b/admin/language/en-GB/en-GB.com_componentbuilder.sys.ini index b634546e5..356a5dbdc 100644 --- a/admin/language/en-GB/en-GB.com_componentbuilder.sys.ini +++ b/admin/language/en-GB/en-GB.com_componentbuilder.sys.ini @@ -480,6 +480,8 @@ COM_COMPONENTBUILDER_JOOMLA_COMPONENTS_SUBMENU="Joomla Components Submenu" COM_COMPONENTBUILDER_JOOMLA_COMPONENTS_SUBMENU_DESC="Allows the users in this group to update the submenu of the joomla component" COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BACKUP_BUTTON_ACCESS="Joomla Component Backup Button Access" COM_COMPONENTBUILDER_JOOMLA_COMPONENT_BACKUP_BUTTON_ACCESS_DESC=" Allows the users in this group to access the backup button." +COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CLONE_BUTTON_ACCESS="Joomla Component Clone Button Access" +COM_COMPONENTBUILDER_JOOMLA_COMPONENT_CLONE_BUTTON_ACCESS_DESC=" Allows the users in this group to access the clone button." COM_COMPONENTBUILDER_JOOMLA_COMPONENT_EXPORT_JCB_PACKAGES_BUTTON_ACCESS="Joomla Component Export JCB Packages Button Access" COM_COMPONENTBUILDER_JOOMLA_COMPONENT_EXPORT_JCB_PACKAGES_BUTTON_ACCESS_DESC=" Allows the users in this group to access the export jcb packages button." COM_COMPONENTBUILDER_JOOMLA_COMPONENT_IMPORT_JCB_PACKAGES_BUTTON_ACCESS="Joomla Component Import JCB Packages Button Access" diff --git a/admin/models/import_joomla_components.php b/admin/models/import_joomla_components.php index 695852c00..4aad147f7 100644 --- a/admin/models/import_joomla_components.php +++ b/admin/models/import_joomla_components.php @@ -80,14 +80,17 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy parent::populateState(); } - protected $app; + public $canmerge = 1; + public $postfix = false; + public $forceUpdate = 0; + public $hasKey = 0; + public $sleutle = null; + public $data = false; + public $app; + protected $dir = false; - protected $data = false; protected $target = false; protected $newID = array(); - protected $forceUpdate = 0; - protected $hasKey = 0; - protected $sleutle = null; protected $updateAfter = array('field' => array(), 'adminview' => array()); protected $divergedDataMover = array(); protected $fieldTypes = array(); @@ -95,6 +98,7 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy protected $specialValue = false; protected $checksum = null; protected $checksumURLs = array('vdm' => 'https://raw.githubusercontent.com/vdm-io/JCB-Packages/master/'); + protected $mustMerge = array('validation_rule', 'fieldtype', 'snippet', 'language', 'language_translation'); /** * Import an spreadsheet from either folder, url or upload. @@ -225,6 +229,8 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy $this->forceUpdate = $this->app->input->getInt('force_update', 0); // show more information $this->moreInfo = $this->app->input->getInt('more_info', 0); + // allow merge + $this->canmerge = $this->app->input->getInt('canmerge', 1); // has a key $this->hasKey = $this->app->input->getInt('haskey', 0); // die sleutle @@ -695,6 +701,12 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy $this->user = JFactory::getUser(); // set some defaults $this->today = JFactory::getDate()->toSql(); + // if we can't merge add postfix to name + if (!$this->canmerge) + { + // set some postfix + $this->postfix = ' ('.ComponentbuilderHelper::randomkey(2).')'; + } // the array of tables to store $tables = array( 'validation_rule', 'fieldtype', 'field', 'admin_view', 'snippet', 'dynamic_get', 'custom_admin_view', 'site_view', @@ -732,7 +744,7 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy * @return boolean false on failure * **/ - protected function saveSmartItems($table) + public function saveSmartItems($table) { if (isset($this->data[$table]) && ComponentbuilderHelper::checkArray($this->data[$table])) { @@ -741,6 +753,8 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy $canEdit = $canDo->get('core.edit'); $canState = $canDo->get('core.edit.state'); $canCreate = $canDo->get('core.create'); + // check if we should allow merge of local values + $canmerge = $this->allowMerge($table); // set id keeper if (!isset($this->newID[$table])) { @@ -750,7 +764,7 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy { $oldID = (int) $item->id; // first check if exist - if ($local = $this->getLocalItem($item, $table, 1)) + if ($canmerge && $local = $this->getLocalItem($item, $table, 1)) { // display more import info if ($this->moreInfo) @@ -821,6 +835,21 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy return true; } + /** + * Check if we should allow merge for this table + * + * @return boolean + * + **/ + protected function allowMerge($table) + { + if ($this->canmerge == 1 || in_array($table, $this->mustMerge)) + { + return true; + } + return false; + } + /** * Move the smart content (files & folders) into place * @@ -989,7 +1018,7 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy * @return void * **/ - protected function updateAfter() + public function updateAfter() { if (ComponentbuilderHelper::checkArray($this->updateAfter['field'])) { @@ -1097,7 +1126,7 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy * @return void * **/ - protected function moveDivergedData() + public function moveDivergedData() { // check if there is data to move if (ComponentbuilderHelper::checkArray($this->divergedDataMover)) @@ -1429,6 +1458,11 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy $this->app->enqueueMessage(JText::sprintf('COM_COMPONENTBUILDER_BFIELD_TYPEB_IDS_MISMATCH_IN_BSB', $item->fieldtype, ComponentbuilderHelper::safeString($type, 'w').':'.$item->id), 'error'); return false; } + // if we can't merge add postfix to name + if ($this->postfix) + { + $item->name = $item->name.$this->postfix; + } break; case 'dynamic_get': // update the view_table_main ID @@ -1455,6 +1489,11 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy ); // update the subform ids $this->updateSubformsIDs($item, 'dynamic_get', $updaterT); + // if we can't merge add postfix to name + if ($this->postfix) + { + $item->name = $item->name.$this->postfix; + } break; case 'layout': case 'template': @@ -1462,6 +1501,11 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy $item = $this->setNewID($item, 'dynamic_get', 'dynamic_get', $type); // update the snippet $item = $this->setNewID($item, 'snippet', 'snippet', $type); + // if we can't merge add postfix to name + if ($this->postfix) + { + $item->name = $item->name.$this->postfix; + } break; case 'custom_admin_view': case 'site_view': @@ -1481,6 +1525,11 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy ); // update the repeatable fields $item = ComponentbuilderHelper::convertRepeatableFields($item, $updaterR); + // if we can't merge add postfix to name + if ($this->postfix) + { + $item->system_name = $item->system_name.$this->postfix; + } break; case 'admin_view': // set the getters anchors @@ -1530,6 +1579,11 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy ); // update the repeatable fields $item = ComponentbuilderHelper::convertRepeatableFields($item, $updaterR); + // if we can't merge add postfix to name + if ($this->postfix) + { + $item->system_name = $item->system_name.$this->postfix; + } break; case 'joomla_component': // set the anchors getters @@ -1656,6 +1710,11 @@ class ComponentbuilderModelImport_joomla_components extends JModelLegacy ); // update the repeatable fields $item = ComponentbuilderHelper::convertRepeatableFields($item, $updaterR); + // if we can't merge add postfix to name + if ($this->postfix) + { + $item->system_name = $item->system_name.$this->postfix; + } break; case 'component_admin_views': // diverged id already updated diff --git a/admin/models/joomla_components.php b/admin/models/joomla_components.php index 5ce685ea9..749eb03d3 100644 --- a/admin/models/joomla_components.php +++ b/admin/models/joomla_components.php @@ -80,18 +80,300 @@ class ComponentbuilderModelJoomla_components extends JModelList protected $params; protected $tempPath; protected $customPath; - protected $smartExport = array(); - protected $exportIDs = array(); + protected $smartBox = array(); + protected $smartIDs = array(); protected $customCodeM = array(); protected $fieldTypes = array(); protected $isMultiple = array(); + /** + * Method to clone the component + * + * @return bool on success. + */ + public function cloner($pks) + { + // get the components + if ($items = $this->getComponents($pks)) + { + // update $pks with returned IDs + $pks = array(); + // start loading the components + $this->smartBox['joomla_component'] = array(); + foreach ($items as $nr => &$item) + { + // check if user has access + $access = ($this->user->authorise('joomla_component.access', 'com_componentbuilder.joomla_component.' . (int) $item->id) && $this->user->authorise('joomla_component.access', 'com_componentbuilder')); + if (!$access) + { + unset($items[$nr]); + continue; + } + // make sure old fields are not exported any more + $this->removeOldComponentValues($item); + // load to global object + $this->smartBox['joomla_component'][$item->id] = $item; + // add to pks + $pks[] = $item->id; + } + + // has any data been set for this component + if (ComponentbuilderHelper::checkArray($pks)) + { + // load the linked stuff + $this->getLinkedToComponents($pks); + } + + // has any data been set for this component + if (isset($this->smartBox['joomla_component']) && ComponentbuilderHelper::checkArray($this->smartBox['joomla_component'])) + { + // set the folder and move the files of each component to the folder + return $this->smartCloner(); + } + } + return false; + } + /** * Method to build the export package * * @return bool on success. */ public function getSmartExport($pks) + { + // get the components + if ($items = $this->getComponents($pks)) + { + // set custom folder path + $this->customPath = $this->params->get('custom_folder_path', JPATH_COMPONENT_ADMINISTRATOR.'/custom'); + // check what type of export or backup this is + if ('backup' === $this->activeType || 'manualBackup' === $this->activeType) + { + // set the paths + if (!$this->backupPath = $this->params->get('cronjob_backup_folder_path', null)) + { + // set the paths + $comConfig = JFactory::getConfig(); + $this->backupPath = $comConfig->get('tmp_path'); + } + // check what backup type we are working with here + $this->backupType = $this->params->get('cronjob_backup_type', 1); // 1 = local folder; 2 = remote server (default is local) + // if remote server get the ID + if (2 == $this->backupType) + { + $this->backupServer = $this->params->get('cronjob_backup_server', null); + } + // set the date array + $date = JFactory::getDate(); + $placeholderDate = array(); + $placeholderDate['[YEAR]'] = $date->format('Y'); + $placeholderDate['[MONTH]'] = $date->format('m'); + $placeholderDate['[DAY]'] = $date->format('d'); + $placeholderDate['[HOUR]'] = $date->format('H'); + $placeholderDate['[MINUTE]'] = $date->format('i'); + // get the package name + $packageName = $this->params->get('backup_package_name', 'JCB_Backup_[YEAR]_[MONTH]_[DAY]'); + $this->packageName = str_replace(array_keys($placeholderDate), array_values($placeholderDate), $packageName); + } + else + { + // set the paths + $comConfig = JFactory::getConfig(); + $this->backupPath = $comConfig->get('tmp_path'); + // set the package name + if (count($items) == 1) + { + $this->packageName = 'JCB_' . $this->getPackageName($items); + } + else + { + $this->packageName = 'JCB_smartPackage'; + } + } + // set the package path + $this->packagePath = rtrim($this->backupPath, '/') . '/' . $this->packageName; + $this->zipPath = $this->packagePath .'.zip'; + if (JFolder::exists($this->packagePath)) + { + // remove if old folder is found + ComponentbuilderHelper::removeFolder($this->packagePath); + } + // create the folders + JFolder::create($this->packagePath); + // Get the basic encryption. + $basickey = ComponentbuilderHelper::getCryptKey('basic'); + // Get the encription object. + if ($basickey) + { + $basic = new FOFEncryptAes($basickey, 128); + } + // update $pks with returned IDs + $pks = array(); + // start loading the components + $this->smartBox['joomla_component'] = array(); + foreach ($items as $nr => &$item) + { + // check if user has access + $access = ($this->user->authorise('joomla_component.access', 'com_componentbuilder.joomla_component.' . (int) $item->id) && $this->user->authorise('joomla_component.access', 'com_componentbuilder')); + if (!$access) + { + unset($items[$nr]); + continue; + } + // make sure old fields are not exported any more + $this->removeOldComponentValues($item); + // build information data set + $this->info['name'][$item->id] = $item->name; + $this->info['short_description'][$item->id] = $item->short_description; + $this->info['component_version'][$item->id] = $item->component_version; + $this->info['companyname'][$item->id] = $item->companyname; + $this->info['author'][$item->id] = $item->author; + $this->info['email'][$item->id] = $item->email; + $this->info['website'][$item->id] = $item->website; + $this->info['license'][$item->id] = $item->license; + $this->info['copyright'][$item->id] = $item->copyright; + // set the keys + if (isset($item->export_key) && ComponentbuilderHelper::checkString($item->export_key)) + { + // keep the key locked for exported data set + $export_key = $item->export_key; + if ($basickey && !is_numeric($item->export_key) && $item->export_key === base64_encode(base64_decode($item->export_key, true))) + { + $export_key = rtrim($basic->decryptString($item->export_key), "\0"); + } + // make sure we have a string + if (strlen($export_key) > 4 ) + { + $this->key[$item->id] = $export_key; + } + } + // get name of this item key_name + if (isset($item->system_name)) + { + $keyName = ComponentbuilderHelper::safeString($item->system_name, 'cAmel'); + } + else + { + $keyName = ComponentbuilderHelper::safeString($item->name_code); + } + // set the export buy links + if (isset($item->export_buy_link) && ComponentbuilderHelper::checkString($item->export_buy_link)) + { + // keep the key locked for exported data set + $this->exportBuyLinks[$keyName] = $item->export_buy_link; + } + // set the export buy links + if (isset($item->export_package_link) && ComponentbuilderHelper::checkString($item->export_package_link)) + { + // keep the key locked for exported data set + $this->exportPackageLinks[$keyName] = $item->export_package_link; + } + // component image + $this->moveIt(array($item->image), 'image'); + // set the custom code ID's + $this->setCustomCodeIds($item, 'joomla_component'); + // set the language strings for this component + $this->setLanguageTranslation($item->id); + // load to global object + $this->smartBox['joomla_component'][$item->id] = $item; + // add to pks + $pks[] = $item->id; + } + + // has any data been set for this component + if (ComponentbuilderHelper::checkArray($pks)) + { + // load the linked stuff + $this->getLinkedToComponents($pks); + } + + // has any data been set for this component + if (isset($this->smartBox['joomla_component']) && ComponentbuilderHelper::checkArray($this->smartBox['joomla_component'])) + { + // set the folder and move the files of each component to the folder + return $this->smartExportBuilder(); + } + } + return false; + } + + /** + * Get Everything Linked to Components + * + * @return void + */ + protected function getLinkedToComponents($pks) + { + // array of tables linked to joomla_component + $linkedTables = array( + 'custom_code' => 'component', + 'component_files_folders' => 'joomla_component', + 'component_admin_views' => 'joomla_component', + 'component_config' => 'joomla_component', + 'component_site_views' => 'joomla_component', + 'component_custom_admin_views' => 'joomla_component', + 'component_updates' => 'joomla_component', + 'component_mysql_tweaks' => 'joomla_component', + 'component_custom_admin_menus' => 'joomla_component', + 'component_dashboard' => 'joomla_component' ); + // load all tables linked to joomla_component + foreach($linkedTables as $table => $field) + { + $this->setData($table, $pks, $field); + } + // add fields and conditions + if (isset($this->smartIDs['admin_view']) && ComponentbuilderHelper::checkArray($this->smartIDs['admin_view'])) + { + $this->setData('admin_fields', array_values($this->smartIDs['admin_view']), 'admin_view'); + $this->setData('admin_fields_conditions', array_values($this->smartIDs['admin_view']), 'admin_view'); + } + // add validation rules + if (isset($this->smartIDs['validation_rule']) && ComponentbuilderHelper::checkArray($this->smartIDs['validation_rule'])) + { + $this->setData('validation_rule', array_values($this->smartIDs['validation_rule']), 'name'); + } + // add field types + if (isset($this->smartIDs['fieldtype']) && ComponentbuilderHelper::checkArray($this->smartIDs['fieldtype'])) + { + $this->setData('fieldtype', array_values($this->smartIDs['fieldtype']), 'id'); + } + // add templates + if (isset($this->smartIDs['template']) && ComponentbuilderHelper::checkArray($this->smartIDs['template'])) + { + $this->setData('template', array_values($this->smartIDs['template']), 'id'); + } + // add layouts + if (isset($this->smartIDs['layout']) && ComponentbuilderHelper::checkArray($this->smartIDs['layout'])) + { + $this->setData('layout', array_values($this->smartIDs['layout']), 'id'); + } + // add dynamic get + if (isset($this->smartIDs['dynamic_get']) && ComponentbuilderHelper::checkArray($this->smartIDs['dynamic_get'])) + { + $this->setData('dynamic_get', array_values($this->smartIDs['dynamic_get']), 'id'); + } + // only if exporting + if ('clone' !== $this->activeType) + { + // add snippets + if (isset($this->smartIDs['snippet']) && ComponentbuilderHelper::checkArray($this->smartIDs['snippet'])) + { + $this->setData('snippet', array_values($this->smartIDs['snippet']), 'id'); + } + // add custom code + if (isset($this->smartIDs['custom_code']) && ComponentbuilderHelper::checkArray($this->smartIDs['custom_code'])) + { + $this->setData('custom_code', array_values($this->smartIDs['custom_code']), 'id'); + } + } + } + + /** + * Get Components + * + * @return array of objects. + */ + protected function getComponents($pks) { // setup the query if (ComponentbuilderHelper::checkArray($pks)) @@ -140,233 +422,45 @@ class ComponentbuilderModelJoomla_components extends JModelList { $this->params = JComponentHelper::getParams('com_componentbuilder'); } - // set custom folder path - $this->customPath = $this->params->get('custom_folder_path', JPATH_COMPONENT_ADMINISTRATOR.'/custom'); - // check what type of export or backup this is - if ('backup' === $this->activeType || 'manualBackup' === $this->activeType) - { - // set the paths - if (!$this->backupPath = $this->params->get('cronjob_backup_folder_path', null)) - { - // set the paths - $comConfig = JFactory::getConfig(); - $this->backupPath = $comConfig->get('tmp_path'); - } - // check what backup type we are working with here - $this->backupType = $this->params->get('cronjob_backup_type', 1); // 1 = local folder; 2 = remote server (default is local) - // if remote server get the ID - if (2 == $this->backupType) - { - $this->backupServer = $this->params->get('cronjob_backup_server', null); - } - // set the date array - $date = JFactory::getDate(); - $placeholderDate = array(); - $placeholderDate['[YEAR]'] = $date->format('Y'); - $placeholderDate['[MONTH]'] = $date->format('m'); - $placeholderDate['[DAY]'] = $date->format('d'); - $placeholderDate['[HOUR]'] = $date->format('H'); - $placeholderDate['[MINUTE]'] = $date->format('i'); - // get the package name - $packageName = $this->params->get('backup_package_name', 'JCB_Backup_[YEAR]_[MONTH]_[DAY]'); - $this->packageName = str_replace(array_keys($placeholderDate), array_values($placeholderDate), $packageName); - } - else - { - // set the paths - $comConfig = JFactory::getConfig(); - $this->backupPath = $comConfig->get('tmp_path'); - // set the package name - if (count($items) == 1) - { - $this->packageName = 'JCB_' . $this->getPackageName($items); - } - else - { - $this->packageName = 'JCB_smartPackage'; - } - } - // set the package path - $this->packagePath = rtrim($this->backupPath, '/') . '/' . $this->packageName; - $this->zipPath = $this->packagePath .'.zip'; - if (JFolder::exists($this->packagePath)) - { - // remove if old folder is found - ComponentbuilderHelper::removeFolder($this->packagePath); - } - // create the folders - JFolder::create($this->packagePath); - // Get the basic encryption. - $basickey = ComponentbuilderHelper::getCryptKey('basic'); - // Get the encription object. - if ($basickey) - { - $basic = new FOFEncryptAes($basickey, 128); - } - // update $pks with returned IDs - $pks = array(); - // start loading the components - $this->smartExport['joomla_component'] = array(); - foreach ($items as $nr => &$item) - { - // check if user has access - $access = ($this->user->authorise('joomla_component.access', 'com_componentbuilder.joomla_component.' . (int) $item->id) && $this->user->authorise('joomla_component.access', 'com_componentbuilder')); - if (!$access) - { - unset($items[$nr]); - continue; - } - // make sure old fields are not exported any more - unset($item->addconfig); - unset($item->addadmin_views); - unset($item->addcustom_admin_views); - unset($item->addsite_views); - unset($item->version_update); - unset($item->sql_tweak); - unset($item->addcustommenus); - unset($item->dashboard_tab); - unset($item->php_dashboard_methods); - unset($item->addfiles); - unset($item->addfolders); - // build information data set - $this->info['name'][$item->id] = $item->name; - $this->info['short_description'][$item->id] = $item->short_description; - $this->info['component_version'][$item->id] = $item->component_version; - $this->info['companyname'][$item->id] = $item->companyname; - $this->info['author'][$item->id] = $item->author; - $this->info['email'][$item->id] = $item->email; - $this->info['website'][$item->id] = $item->website; - $this->info['license'][$item->id] = $item->license; - $this->info['copyright'][$item->id] = $item->copyright; - // set the keys - if (isset($item->export_key) && ComponentbuilderHelper::checkString($item->export_key)) - { - // keep the key locked for exported data set - $export_key = $item->export_key; - if ($basickey && !is_numeric($item->export_key) && $item->export_key === base64_encode(base64_decode($item->export_key, true))) - { - $export_key = rtrim($basic->decryptString($item->export_key), "\0"); - } - // make sure we have a string - if (strlen($export_key) > 4 ) - { - $this->key[$item->id] = $export_key; - } - } - // get name of this item key_name - if (isset($item->system_name)) - { - $keyName = ComponentbuilderHelper::safeString($item->system_name, 'cAmel'); - } - else - { - $keyName = ComponentbuilderHelper::safeString($item->name_code); - } - // set the export buy links - if (isset($item->export_buy_link) && ComponentbuilderHelper::checkString($item->export_buy_link)) - { - // keep the key locked for exported data set - $this->exportBuyLinks[$keyName] = $item->export_buy_link; - } - // set the export buy links - if (isset($item->export_package_link) && ComponentbuilderHelper::checkString($item->export_package_link)) - { - // keep the key locked for exported data set - $this->exportPackageLinks[$keyName] = $item->export_package_link; - } - // component image - $this->moveIt(array($item->image), 'image'); - // set the custom code ID's - $this->setCustomCodeIds($item, 'joomla_component'); - // set the language strings for this component - $this->setLanguageTranslation($item->id); - // load to global object - $this->smartExport['joomla_component'][$item->id] = $item; - // add to pks - $pks[] = $item->id; - } - // array of tables linked to joomla_component - $linkedTables = array( - 'custom_code' => 'component', - 'component_files_folders' => 'joomla_component', - 'component_admin_views' => 'joomla_component', - 'component_config' => 'joomla_component', - 'component_site_views' => 'joomla_component', - 'component_custom_admin_views' => 'joomla_component', - 'component_updates' => 'joomla_component', - 'component_mysql_tweaks' => 'joomla_component', - 'component_custom_admin_menus' => 'joomla_component', - 'component_dashboard' => 'joomla_component' ); - // load all tables linked to joomla_component - foreach($linkedTables as $table => $field) - { - $this->setData($table, $pks, $field); - } - // add fields and conditions - if (isset($this->exportIDs['admin_view']) && ComponentbuilderHelper::checkArray($this->exportIDs['admin_view'])) - { - $this->setData('admin_fields', array_values($this->exportIDs['admin_view']), 'admin_view'); - $this->setData('admin_fields_conditions', array_values($this->exportIDs['admin_view']), 'admin_view'); - } - // add validation rules - if (isset($this->exportIDs['validation_rule']) && ComponentbuilderHelper::checkArray($this->exportIDs['validation_rule'])) - { - $this->setData('validation_rule', array_values($this->exportIDs['validation_rule']), 'name'); - } - // add field types - if (isset($this->exportIDs['fieldtype']) && ComponentbuilderHelper::checkArray($this->exportIDs['fieldtype'])) - { - $this->setData('fieldtype', array_values($this->exportIDs['fieldtype']), 'id'); - } - // add templates - if (isset($this->exportIDs['template']) && ComponentbuilderHelper::checkArray($this->exportIDs['template'])) - { - $this->setData('template', array_values($this->exportIDs['template']), 'id'); - } - // add layouts - if (isset($this->exportIDs['layout']) && ComponentbuilderHelper::checkArray($this->exportIDs['layout'])) - { - $this->setData('layout', array_values($this->exportIDs['layout']), 'id'); - } - // add dynamic get - if (isset($this->exportIDs['dynamic_get']) && ComponentbuilderHelper::checkArray($this->exportIDs['dynamic_get'])) - { - $this->setData('dynamic_get', array_values($this->exportIDs['dynamic_get']), 'id'); - } - // add snippets - if (isset($this->exportIDs['snippet']) && ComponentbuilderHelper::checkArray($this->exportIDs['snippet'])) - { - $this->setData('snippet', array_values($this->exportIDs['snippet']), 'id'); - } - // add custom code - if (isset($this->exportIDs['custom_code']) && ComponentbuilderHelper::checkArray($this->exportIDs['custom_code'])) - { - $this->setData('custom_code', array_values($this->exportIDs['custom_code']), 'id'); - } - - // has any data been set for this component - if (isset($this->smartExport['joomla_component']) && ComponentbuilderHelper::checkArray($this->smartExport['joomla_component'])) - { - // set the folder and move the files of each component to the folder - return $this->smartExportBuilder(); - } + return $items; } } } return false; } + /** + * Remove all values that are no longer relevant. + * + * @return void. + */ + protected function removeOldComponentValues(&$item) + { + // make sure old fields are not used any more + unset($item->addconfig); + unset($item->addadmin_views); + unset($item->addcustom_admin_views); + unset($item->addsite_views); + unset($item->version_update); + unset($item->sql_tweak); + unset($item->addcustommenus); + unset($item->dashboard_tab); + unset($item->php_dashboard_methods); + unset($item->addfiles); + unset($item->addfolders); + } + /** * Set export IDs. * * @return void. */ - protected function setExportIDs($value, $table, $int = true) + protected function setSmartIDs($value, $table, $int = true) { // check if table has been set - if (!isset($this->exportIDs[$table])) + if (!isset($this->smartIDs[$table])) { - $this->exportIDs[$table] = array(); + $this->smartIDs[$table] = array(); } // convert if value is in json if (ComponentbuilderHelper::checkJson($value)) @@ -380,21 +474,21 @@ class ComponentbuilderModelJoomla_components extends JModelList { if ($int && (ComponentbuilderHelper::checkString($id) || is_numeric($id)) && 0 !== (int) $id) { - $this->exportIDs[$table][(int) $id] = (int) $id; + $this->smartIDs[$table][(int) $id] = (int) $id; } elseif (!$int && ComponentbuilderHelper::checkString($id)) { - $this->exportIDs[$table][$id] = $this->_db->quote($id); + $this->smartIDs[$table][$id] = $this->_db->quote($id); } } } elseif ($int && (ComponentbuilderHelper::checkString($value) || is_numeric($value)) && 0 !== (int) $value) { - $this->exportIDs[$table][(int) $value] = (int) $value; + $this->smartIDs[$table][(int) $value] = (int) $value; } elseif (!$int && ComponentbuilderHelper::checkString($value)) { - $this->exportIDs[$table][$value] = $this->_db->quote($value); + $this->smartIDs[$table][$value] = $this->_db->quote($value); } } @@ -519,22 +613,22 @@ class ComponentbuilderModelJoomla_components extends JModelList // reset the global array if ('template' === $table) { - $this->exportIDs['template'] = array(); + $this->smartIDs['template'] = array(); } elseif ('layout' === $table) { - $this->exportIDs['layout'] = array(); + $this->smartIDs['layout'] = array(); } // start loading the data - if (!isset($this->smartExport[$table])) + if (!isset($this->smartBox[$table])) { - $this->smartExport[$table] = array(); + $this->smartBox[$table] = array(); } // start loading the found items foreach ($items as $nr => &$item) { // set the data per id only once - if (!isset($item->id) || 0 === (int) $item->id || isset($this->smartExport[$table][$item->id])) + if (!isset($item->id) || 0 === (int) $item->id || isset($this->smartBox[$table][$item->id])) { continue; } @@ -571,11 +665,11 @@ class ComponentbuilderModelJoomla_components extends JModelList unset($item->addconditions); } // load to global object - $this->smartExport[$table][$item->id] = $item; + $this->smartBox[$table][$item->id] = $item; // set the custom code ID's $this->setCustomCodeIds($item, $table); // actions to take if table is component_files_folders - if ('component_files_folders' === $table) + if ('component_files_folders' === $table && 'clone' !== $this->activeType) { // build files $this->moveIt($this->getValues($item->addfiles, 'subform', 'file', null), 'file'); @@ -614,13 +708,17 @@ class ComponentbuilderModelJoomla_components extends JModelList if ('admin_view' === $table) { // add fields & conditions - $this->setExportIDs($item->id, 'admin_view'); - // admin icon - $this->moveIt(array($item->icon), 'image'); - // admin icon_add - $this->moveIt(array($item->icon_add), 'image'); - // admin icon_category - $this->moveIt(array($item->icon_category), 'image'); + $this->setSmartIDs($item->id, 'admin_view'); + // do not move anything if clone + if ('clone' !== $this->activeType) + { + // admin icon + $this->moveIt(array($item->icon), 'image'); + // admin icon_add + $this->moveIt(array($item->icon_add), 'image'); + // admin icon_category + $this->moveIt(array($item->icon_category), 'image'); + } } // actions to take if table is admin_fields if ('admin_fields' === $table) @@ -639,7 +737,7 @@ class ComponentbuilderModelJoomla_components extends JModelList if ('field' === $table) { // add field types - $this->setExportIDs($item->fieldtype, 'fieldtype'); + $this->setSmartIDs($item->fieldtype, 'fieldtype'); // check if this field has multiple fields if ($this->checkMultiFields($item->fieldtype)) { @@ -674,7 +772,7 @@ class ComponentbuilderModelJoomla_components extends JModelList if (!in_array($validationRule, (array) $coreValidationRules)) { // okay load the rule - $this->setExportIDs($validationRule, 'validation_rule', false); + $this->setSmartIDs($validationRule, 'validation_rule', false); } } } @@ -693,11 +791,11 @@ class ComponentbuilderModelJoomla_components extends JModelList } } // add dynamic gets - $this->setExportIDs($item->main_get, 'dynamic_get'); - $this->setExportIDs($item->custom_get, 'dynamic_get'); - $this->setExportIDs($item->dynamic_get, 'dynamic_get'); + $this->setSmartIDs($item->main_get, 'dynamic_get'); + $this->setSmartIDs($item->custom_get, 'dynamic_get'); + $this->setSmartIDs($item->dynamic_get, 'dynamic_get'); // move the icon - if ('custom_admin_view' === $table && isset($item->icon)) + if ('custom_admin_view' === $table && isset($item->icon) && 'clone' !== $this->activeType) { // view icon $this->moveIt(array($item->icon), 'image'); @@ -705,7 +803,7 @@ class ComponentbuilderModelJoomla_components extends JModelList // add snippets (was removed please use snippet importer) if (isset($item->snippet) && is_numeric($item->snippet)) { - $this->setExportIDs((int) $item->snippet, 'snippet'); + $this->setSmartIDs((int) $item->snippet, 'snippet'); } } // actions to take if table is template and layout @@ -714,7 +812,7 @@ class ComponentbuilderModelJoomla_components extends JModelList // add snippets (was removed please use snippet importer) if (isset($item->snippet) && is_numeric($item->snippet)) { - $this->setExportIDs((int) $item->snippet, 'snippet'); + $this->setSmartIDs((int) $item->snippet, 'snippet'); } // search for templates & layouts $this->getTemplateLayout(base64_decode($item->$table), $this->user); @@ -724,25 +822,80 @@ class ComponentbuilderModelJoomla_components extends JModelList $this->getTemplateLayout($item->php_view, $this->user); } // add dynamic gets - $this->setExportIDs((int) $item->dynamic_get, 'dynamic_get'); + $this->setSmartIDs((int) $item->dynamic_get, 'dynamic_get'); } } } } } + /** + * Method to do the smart cloning + * + * @return bool + */ + protected function smartCloner() + { + // check if data is set + if (isset($this->smartBox) && ComponentbuilderHelper::checkArray($this->smartBox)) + { + // get the import_joomla_components + $model = ComponentbuilderHelper::getModel('import_joomla_components'); + // do not show more information + $model->moreInfo = 0; + // trigger the create new (clone) feature + $model->canmerge = 0; + // set some postfix + $model->postfix = ' ('.ComponentbuilderHelper::randomkey(2).')'; + // get App + $model->app = JFactory::getApplication(); + // set user + $model->user = $this->user; + // set today's date + $model->today = JFactory::getDate()->toSql(); + // load the data + $model->data = $this->smartBox; + // remove smart box to safe on memory + unset($this->smartBox); + // the array of tables to store + $tables = array( + 'fieldtype', 'field', 'admin_view', 'snippet', 'dynamic_get', 'custom_admin_view', 'site_view', + 'template', 'layout', 'joomla_component', 'language', 'language_translation', 'custom_code', + 'admin_fields', 'admin_fields_conditions', 'component_admin_views', 'component_site_views', + 'component_custom_admin_views', 'component_updates', 'component_mysql_tweaks', + 'component_custom_admin_menus', 'component_config', 'component_dashboard', 'component_files_folders' + ); + // smart table loop + foreach ($tables as $table) + { + // save the table to database + if (!$model->saveSmartItems($table)) + { + return false; + } + } + // do an after all run on all items that need it + $model->updateAfter(); + // finally move the old datasets + $model->moveDivergedData(); + // we had success + return true; + } + return false; + } + /** * Method to build the package to export * - * @return void + * @return bool */ protected function smartExportBuilder() { // check if data is set - if (isset($this->smartExport) && ComponentbuilderHelper::checkArray($this->smartExport)) + if (isset($this->smartBox) && ComponentbuilderHelper::checkArray($this->smartBox)) { // set db data - $data = serialize($this->smartExport); + $data = serialize($this->smartBox); // lock the data if set if (ComponentbuilderHelper::checkArray($this->key)) { @@ -1096,9 +1249,9 @@ class ComponentbuilderModelJoomla_components extends JModelList $data = $this->getDataWithAlias($template, 'template'); if (ComponentbuilderHelper::checkArray($data)) { - if (!isset($this->exportIDs['template']) || !isset($this->exportIDs['template'][$data['id']])) + if (!isset($this->smartIDs['template']) || !isset($this->smartIDs['template'][$data['id']])) { - $this->setExportIDs($data['id'], 'template'); + $this->setSmartIDs($data['id'], 'template'); // call self to get child data $again[] = $data['html']; $again[] = $data['php_view']; @@ -1131,9 +1284,9 @@ class ComponentbuilderModelJoomla_components extends JModelList $data = $this->getDataWithAlias($layout, 'layout'); if (ComponentbuilderHelper::checkArray($data)) { - if (!isset($this->exportIDs['layout']) || !isset($this->exportIDs['layout'][$data['id']])) + if (!isset($this->smartIDs['layout']) || !isset($this->smartIDs['layout'][$data['id']])) { - $this->setExportIDs($data['id'], 'layout'); + $this->setSmartIDs($data['id'], 'layout'); // call self to get child data $again[] = $data['html']; $again[] = $data['php_view']; @@ -1152,14 +1305,14 @@ class ComponentbuilderModelJoomla_components extends JModelList if ($user) { // add templates - if (isset($this->exportIDs['template']) && ComponentbuilderHelper::checkArray($this->exportIDs['template'])) + if (isset($this->smartIDs['template']) && ComponentbuilderHelper::checkArray($this->smartIDs['template'])) { - $this->setData('template', array_values($this->exportIDs['template']), 'id'); + $this->setData('template', array_values($this->smartIDs['template']), 'id'); } // add layouts - if (isset($this->exportIDs['layout']) && ComponentbuilderHelper::checkArray($this->exportIDs['layout'])) + if (isset($this->smartIDs['layout']) && ComponentbuilderHelper::checkArray($this->smartIDs['layout'])) { - $this->setData('layout', array_values($this->exportIDs['layout']), 'id'); + $this->setData('layout', array_values($this->smartIDs['layout']), 'id'); } } } @@ -1247,13 +1400,13 @@ class ComponentbuilderModelJoomla_components extends JModelList // if numeric add to ids if (is_numeric($func)) { - $this->setExportIDs($func, 'custom_code'); + $this->setSmartIDs($func, 'custom_code'); } elseif (ComponentbuilderHelper::checkString($func)) { if ($funcID = ComponentbuilderHelper::getVar('custom_code', $func, 'function_name', 'id')) { - $this->setExportIDs($funcID, 'custom_code'); + $this->setSmartIDs($funcID, 'custom_code'); } } } @@ -1296,19 +1449,19 @@ class ComponentbuilderModelJoomla_components extends JModelList // check if we have items if (ComponentbuilderHelper::checkArray($items)) { - if (!isset($this->smartExport['language_translation'])) + if (!isset($this->smartBox['language_translation'])) { - $this->smartExport['language_translation'] = array(); + $this->smartBox['language_translation'] = array(); } foreach ($items as $item) { - if (!isset($this->smartExport['language_translation'][$item->id]) && ComponentbuilderHelper::checkJson($item->components)) + if (!isset($this->smartBox['language_translation'][$item->id]) && ComponentbuilderHelper::checkJson($item->components)) { $components = json_decode($item->components, true); if (in_array($id, $components)) { // load to global object - $this->smartExport['language_translation'][$item->id] = $item; + $this->smartBox['language_translation'][$item->id] = $item; // add languages if (isset($item->translation)) { diff --git a/admin/views/import_joomla_components/view.html.php b/admin/views/import_joomla_components/view.html.php index 56a985f0e..dadb90135 100644 --- a/admin/views/import_joomla_components/view.html.php +++ b/admin/views/import_joomla_components/view.html.php @@ -153,6 +153,31 @@ class ComponentbuilderViewImport_joomla_components extends JViewLegacy $more_info->setup($more_infoXML,0); // add to form $form[] = $more_info; + + // get the merge radio field + $merge = JFormHelper::loadFieldType('radio',true); + // start merge xml + $mergeXML = new SimpleXMLElement(''); + // merge attributes + $mergeAttributes = array( + 'type' => 'radio', + 'name' => 'canmerge', + 'label' => 'COM_COMPONENTBUILDER_MERGE', + 'class' => 'btn-group btn-group-yesno', + 'description' => 'COM_COMPONENTBUILDER_SHOULD_WE_MERGE_THE_COMPONENTS_WITH_SIMILAR_LOCAL_COMPONENTS_MERGING_THE_COMPONENTS_USE_TO_BE_THE_DEFAULT_BEHAVIOUR_BUT_NOW_YOU_CAN_IMPORT_THE_COMPONENTS_AND_FORCE_IT_NOT_TO_MERGE_THE_FOLLOWING_AREAS_VALIDATION_RULE_FIELDTYPE_SNIPPET_LANGUAGE_LANGUAGE_TRANSLATION_BMUST_AND_WILL_STILLB_MERGE_EVEN_OF_YOUR_SELECTION_IS_BNOB_BECAUSE_OF_THE_SINGULAR_NATURE_OF_THOSE_AREAS', + 'default' => '1'); + // load the merge attributes + ComponentbuilderHelper::xmlAddAttributes($mergeXML, $mergeAttributes); + // set the merge options + $mergeOptions = array( + '1' => 'COM_COMPONENTBUILDER_YES', + '0' => 'COM_COMPONENTBUILDER_NO'); + // load the merge options + ComponentbuilderHelper::xmlAddOptions($mergeXML, $mergeOptions); + // setup the merge radio field + $merge->setup($mergeXML,1); + // add to form + $form[] = $merge; if (!$this->packageInfo || (isset($this->packageInfo['getKeyFrom']) && ComponentbuilderHelper::checkArray($this->packageInfo['getKeyFrom']))) { diff --git a/admin/views/joomla_components/view.html.php b/admin/views/joomla_components/view.html.php index 0f346928b..3d27333da 100644 --- a/admin/views/joomla_components/view.html.php +++ b/admin/views/joomla_components/view.html.php @@ -143,6 +143,11 @@ class ComponentbuilderViewJoomla_components extends JViewLegacy { // add Backup button. JToolBarHelper::custom('joomla_components.backup', 'archive', '', 'COM_COMPONENTBUILDER_BACKUP', false); + } + if ($this->user->authorise('joomla_component.clone', 'com_componentbuilder')) + { + // add Clone button. + JToolBarHelper::custom('joomla_components.cloner', 'save-copy', '', 'COM_COMPONENTBUILDER_CLONE', false); } if ($this->state->get('filter.published') == -2 && ($this->canState && $this->canDelete)) diff --git a/componentbuilder.xml b/componentbuilder.xml index ff5f4a70b..ed5453cf9 100644 --- a/componentbuilder.xml +++ b/componentbuilder.xml @@ -1,7 +1,7 @@ COM_COMPONENTBUILDER - 15th April, 2018 + 17th April, 2018 Llewellyn van der Merwe llewellyn@joomlacomponentbuilder.com http://joomlacomponentbuilder.com