From 3610bebc7cdcd725c2078d913374d07e6b88a21c Mon Sep 17 00:00:00 2001 From: Anurag <30978328+Anu1601CS@users.noreply.github.com> Date: Wed, 23 May 2018 17:37:11 +0530 Subject: [PATCH 01/79] Load correct core files of override files (#2) Start implements loadcorefile() in administrator/components/com_templates/Model/TemplateModel.php --- .../com_templates/Model/TemplateModel.php | 173 ++++++++++++++++++ .../language/en-GB/en-GB.com_templates.ini | 2 + 2 files changed, 175 insertions(+) diff --git a/administrator/components/com_templates/Model/TemplateModel.php b/administrator/components/com_templates/Model/TemplateModel.php index f4db172ec041f..6a9663fa63061 100644 --- a/administrator/components/com_templates/Model/TemplateModel.php +++ b/administrator/components/com_templates/Model/TemplateModel.php @@ -12,6 +12,11 @@ use Joomla\CMS\Application\ApplicationHelper; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Factory; +use Joomla\CMS\Date\Date; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Filesystem\File; +use Joomla\CMS\Filesystem\Path; use Joomla\CMS\MVC\Model\FormModel; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Component\Templates\Administrator\Helper\TemplateHelper; @@ -148,6 +153,174 @@ public function getDirectoryTree($dir) return $result; } + /** + * Method to get the core file of override file + * + * @param string $file Override file + * @param integer $client Client Id + * + * @return string $corefile The full path and file name for the target file, or boolean false if the file is not found in any of the paths. + * + * @since __DEPLOY_VERSION__ + */ + public function getCoreFile($file, $client_id) + { + $app = Factory::getApplication(); + $filePath = Path::clean($file); + $explodeArray = explode(DIRECTORY_SEPARATOR, $filePath); + + // Only allow html/ folder + if($explodeArray['1'] !== 'html') + { + $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_ONLY_HTML_FOLDER_ALLOWED'), 'error'); + + return false; + } + + $fileName = basename($filePath); + $type = $explodeArray['2']; + $client = ApplicationHelper::getClientInfo($client_id); + + $componentPath = Path::clean($client->path . '/components/'); + $modulePath = Path::clean($client->path . '/modules/'); + $layoutPath = Path::clean(JPATH_ROOT . '/layouts/'); + + // For modules + if (stristr($type, 'mod_') !== false) + { + $folder = $explodeArray['2']; + $htmlPath = Path::clean($modulePath . $folder . '/tmpl/'); + $fileName = $this->getSafeName($fileName); + $coreFile = $this->findPath($htmlPath, $fileName); + + return $coreFile; + } + elseif (stristr($type, 'com_') !== false) + { + // For components + $folder = $explodeArray['2']; + $subFolder = $explodeArray['3']; + $fileName = $this->getSafeName($fileName); + + // The old scheme, if a view has a tmpl folder + $oldHtmlPath = Path::clean($componentPath . $folder . '/views/' . $subFolder . '/tmpl/'); + + if(!$coreFile = Path::find($oldHtmlPath, $fileName)) + { + // The new scheme, the views are directly in the component/tmpl folder + $newHtmlPath = Path::clean($componentPath . $folder . '/tmpl/' . $subFolder . '/'); + $coreFile = $this->findPath($newHtmlPath, $fileName); + + return $coreFile; + } + + return $coreFile; + } + elseif (stristr($type, 'layouts') !== false) + { + // For Jlayouts + $subtype = $explodeArray['3']; + + if(stristr($subtype, 'com_')) + { + $folder = $explodeArray['3']; + $subFolder = array_slice($explodeArray, 4, -1); + $subFolder = implode(DIRECTORY_SEPARATOR, $subFolder); + $htmlPath = Path::clean($componentPath . $folder . '/layouts/' . $subFolder); + $fileName = $this->getSafeName($fileName); + $coreFile = $this->findPath($htmlPath, $fileName); + + return $coreFile; + } + elseif (stristr($subtype, 'joomla') || stristr($subtype, 'libraries') || stristr($subtype, 'plugins')) + { + $subFolder = array_slice($explodeArray, 3, -1); + $subFolder = implode(DIRECTORY_SEPARATOR, $subFolder); + $htmlPath = Path::clean($layoutPath . $subFolder); + $fileName = $this->getSafeName($fileName); + $coreFile = $this->findPath($htmlPath, $fileName); + + return $coreFile; + } + } + + $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND'), 'error'); + + return false; + } + + /** + * Creates a safe file name for the given name. + * + * @param string $name The filename + * + * @return string $fileName The filtered name without Date + * + * @since __DEPLOY_VERSION__ + */ + private function getSafeName($name) + { + if (preg_match('/[0-9]/', $name)) + { + // Get the extension + $extension = File::getExt($name); + + // Remove ( Date ) from file + $explodeArray = explode('-', $name); + $size = count($explodeArray); + $date = $explodeArray[$size-2] . '-' . str_replace('.' . $extension, '', $explodeArray[$size-1]); + + if($this->validateDate($date)) + { + $nameWithoutExtension = implode('-', array_slice($explodeArray, 0, -2)); + + //Filtered name + $name = $nameWithoutExtension . '.' . $extension; + } + } + + return $name; + } + + /** + * Validate Date in file name. + * + * @param string $date Date to validate. + * + * @return boolean Return true if date is valid and false if not. + * + * @since __DEPLOY_VERSION__ + */ + private function validateDate($date) + { + $format = 'Ymd-His'; + $valid = Date::createFromFormat($format, $date); + + return $valid && $valid->format($format) == $date; + } + + /** + * Find file in given folde + * + * @param string $path An path or array of path to search. + * @param string $file The file name to look for. + * + * @return mixed $path The full path and file name for the target file, or boolean false if the file is not found in any of the paths. + * + * @since __DEPLOY_VERSION__ + */ + private function findPath($paths, $file) + { + $app = Factory::getApplication(); + + if(!$path = Path::find($paths, $file)) + { + $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND'), 'error'); + } + + return $path; + } + /** * Method to auto-populate the model state. * diff --git a/administrator/language/en-GB/en-GB.com_templates.ini b/administrator/language/en-GB/en-GB.com_templates.ini index e74b635285d6b..b28de3618608b 100644 --- a/administrator/language/en-GB/en-GB.com_templates.ini +++ b/administrator/language/en-GB/en-GB.com_templates.ini @@ -43,6 +43,7 @@ COM_TEMPLATES_DIRECTORY_NOT_WRITABLE="The template folder is not writable. Some COM_TEMPLATES_ERR_XML="Template XML data not available" COM_TEMPLATES_ERROR_CANNOT_DELETE_LAST_STYLE="Can't delete the last style of a template. To uninstall/delete a template go to: Extensions-> Manage-> Manage-> Select template to be deleted-> Select 'Uninstall'." COM_TEMPLATES_ERROR_CANNOT_UNSET_DEFAULT_STYLE="Can't unset default style." +COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND="Core file not found." COM_TEMPLATES_ERROR_COULD_NOT_COPY="Unable to copy template files to temporary folder." COM_TEMPLATES_ERROR_COULD_NOT_INSTALL="Unable to install new template from temporary folder." COM_TEMPLATES_ERROR_COULD_NOT_WRITE="Unable to delete temporary folder." @@ -63,6 +64,7 @@ COM_TEMPLATES_ERROR_IMAGE_FILE_NOT_FOUND="Image file not found." COM_TEMPLATES_ERROR_INDEX_DELETE="The file index.php can't be deleted. Make changes in the editor if you want to change the file." COM_TEMPLATES_ERROR_INVALID_FROM_NAME="Template to copy from can't be found." COM_TEMPLATES_ERROR_INVALID_TEMPLATE_NAME="Invalid template name. Please use only letters, numbers, dashes and underscores." +COM_TEMPLATES_ERROR_ONLY_HTML_FOLDER_ALLOWED="Only html/ folder allowed." COM_TEMPLATES_ERROR_RENAME_INDEX="The file index.php can't be renamed." COM_TEMPLATES_ERROR_ROOT_DELETE="The root folder can't be deleted." COM_TEMPLATES_ERROR_SAVE_DISABLED_TEMPLATE="Unable to save a style associated to a disabled template." From d4a3b55e41180b896511503646b212abbde8867c Mon Sep 17 00:00:00 2001 From: Anurag <30978328+Anu1601CS@users.noreply.github.com> Date: Thu, 24 May 2018 02:13:02 +0530 Subject: [PATCH 02/79] CS (#3) Coding Standards --- .../com_templates/Model/TemplateModel.php | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/administrator/components/com_templates/Model/TemplateModel.php b/administrator/components/com_templates/Model/TemplateModel.php index 6a9663fa63061..058a938ac0e87 100644 --- a/administrator/components/com_templates/Model/TemplateModel.php +++ b/administrator/components/com_templates/Model/TemplateModel.php @@ -156,8 +156,8 @@ public function getDirectoryTree($dir) /** * Method to get the core file of override file * - * @param string $file Override file - * @param integer $client Client Id + * @param string $file Override file + * @param integer $client_id Client Id * * @return string $corefile The full path and file name for the target file, or boolean false if the file is not found in any of the paths. * @@ -170,7 +170,7 @@ public function getCoreFile($file, $client_id) $explodeArray = explode(DIRECTORY_SEPARATOR, $filePath); // Only allow html/ folder - if($explodeArray['1'] !== 'html') + if ($explodeArray['1'] !== 'html') { $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_ONLY_HTML_FOLDER_ALLOWED'), 'error'); @@ -205,7 +205,7 @@ public function getCoreFile($file, $client_id) // The old scheme, if a view has a tmpl folder $oldHtmlPath = Path::clean($componentPath . $folder . '/views/' . $subFolder . '/tmpl/'); - if(!$coreFile = Path::find($oldHtmlPath, $fileName)) + if (!$coreFile = Path::find($oldHtmlPath, $fileName)) { // The new scheme, the views are directly in the component/tmpl folder $newHtmlPath = Path::clean($componentPath . $folder . '/tmpl/' . $subFolder . '/'); @@ -221,7 +221,7 @@ public function getCoreFile($file, $client_id) // For Jlayouts $subtype = $explodeArray['3']; - if(stristr($subtype, 'com_')) + if (stristr($subtype, 'com_')) { $folder = $explodeArray['3']; $subFolder = array_slice($explodeArray, 4, -1); @@ -270,11 +270,11 @@ private function getSafeName($name) $size = count($explodeArray); $date = $explodeArray[$size-2] . '-' . str_replace('.' . $extension, '', $explodeArray[$size-1]); - if($this->validateDate($date)) + if ($this->validateDate($date)) { $nameWithoutExtension = implode('-', array_slice($explodeArray, 0, -2)); - //Filtered name + // Filtered name $name = $nameWithoutExtension . '.' . $extension; } } @@ -300,10 +300,10 @@ private function validateDate($date) } /** - * Find file in given folde + * Find file in given folder. * - * @param string $path An path or array of path to search. - * @param string $file The file name to look for. + * @param string $paths An path or array of path to search. + * @param string $file The file name to look for. * * @return mixed $path The full path and file name for the target file, or boolean false if the file is not found in any of the paths. * @@ -313,7 +313,7 @@ private function findPath($paths, $file) { $app = Factory::getApplication(); - if(!$path = Path::find($paths, $file)) + if (!$path = Path::find($paths, $file)) { $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND'), 'error'); } From c5a2eda0472812f54e74171d8751628b6833f251 Mon Sep 17 00:00:00 2001 From: astridx Date: Wed, 23 May 2018 22:53:30 +0200 Subject: [PATCH 03/79] codingstandards --- .../com_templates/Model/TemplateModel.php | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/administrator/components/com_templates/Model/TemplateModel.php b/administrator/components/com_templates/Model/TemplateModel.php index 058a938ac0e87..7cf88d6881118 100644 --- a/administrator/components/com_templates/Model/TemplateModel.php +++ b/administrator/components/com_templates/Model/TemplateModel.php @@ -156,8 +156,8 @@ public function getDirectoryTree($dir) /** * Method to get the core file of override file * - * @param string $file Override file - * @param integer $client_id Client Id + * @param string $file Override file + * @param integer $client_id Client Id * * @return string $corefile The full path and file name for the target file, or boolean false if the file is not found in any of the paths. * @@ -224,7 +224,7 @@ public function getCoreFile($file, $client_id) if (stristr($subtype, 'com_')) { $folder = $explodeArray['3']; - $subFolder = array_slice($explodeArray, 4, -1); + $subFolder = array_slice($explodeArray, 4, -1); $subFolder = implode(DIRECTORY_SEPARATOR, $subFolder); $htmlPath = Path::clean($componentPath . $folder . '/layouts/' . $subFolder); $fileName = $this->getSafeName($fileName); @@ -267,8 +267,8 @@ private function getSafeName($name) // Remove ( Date ) from file $explodeArray = explode('-', $name); - $size = count($explodeArray); - $date = $explodeArray[$size-2] . '-' . str_replace('.' . $extension, '', $explodeArray[$size-1]); + $size = count($explodeArray); + $date = $explodeArray[$size - 2] . '-' . str_replace('.' . $extension, '', $explodeArray[$size - 1]); if ($this->validateDate($date)) { @@ -285,25 +285,25 @@ private function getSafeName($name) /** * Validate Date in file name. * - * @param string $date Date to validate. + * @param string $date Date to validate. * * @return boolean Return true if date is valid and false if not. * * @since __DEPLOY_VERSION__ */ - private function validateDate($date) - { - $format = 'Ymd-His'; - $valid = Date::createFromFormat($format, $date); + private function validateDate($date) + { + $format = 'Ymd-His'; + $valid = Date::createFromFormat($format, $date); - return $valid && $valid->format($format) == $date; - } + return $valid && $valid->format($format) == $date; + } /** * Find file in given folder. * - * @param string $paths An path or array of path to search. - * @param string $file The file name to look for. + * @param string $paths An path or array of path to search. + * @param string $file The file name to look for. * * @return mixed $path The full path and file name for the target file, or boolean false if the file is not found in any of the paths. * From 880c20314ccff038a7273f4695e85e5330a983c7 Mon Sep 17 00:00:00 2001 From: Astrid Date: Thu, 24 May 2018 06:45:22 +0200 Subject: [PATCH 04/79] codingstandards (#4) --- .../com_templates/Model/TemplateModel.php | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/administrator/components/com_templates/Model/TemplateModel.php b/administrator/components/com_templates/Model/TemplateModel.php index 058a938ac0e87..7cf88d6881118 100644 --- a/administrator/components/com_templates/Model/TemplateModel.php +++ b/administrator/components/com_templates/Model/TemplateModel.php @@ -156,8 +156,8 @@ public function getDirectoryTree($dir) /** * Method to get the core file of override file * - * @param string $file Override file - * @param integer $client_id Client Id + * @param string $file Override file + * @param integer $client_id Client Id * * @return string $corefile The full path and file name for the target file, or boolean false if the file is not found in any of the paths. * @@ -224,7 +224,7 @@ public function getCoreFile($file, $client_id) if (stristr($subtype, 'com_')) { $folder = $explodeArray['3']; - $subFolder = array_slice($explodeArray, 4, -1); + $subFolder = array_slice($explodeArray, 4, -1); $subFolder = implode(DIRECTORY_SEPARATOR, $subFolder); $htmlPath = Path::clean($componentPath . $folder . '/layouts/' . $subFolder); $fileName = $this->getSafeName($fileName); @@ -267,8 +267,8 @@ private function getSafeName($name) // Remove ( Date ) from file $explodeArray = explode('-', $name); - $size = count($explodeArray); - $date = $explodeArray[$size-2] . '-' . str_replace('.' . $extension, '', $explodeArray[$size-1]); + $size = count($explodeArray); + $date = $explodeArray[$size - 2] . '-' . str_replace('.' . $extension, '', $explodeArray[$size - 1]); if ($this->validateDate($date)) { @@ -285,25 +285,25 @@ private function getSafeName($name) /** * Validate Date in file name. * - * @param string $date Date to validate. + * @param string $date Date to validate. * * @return boolean Return true if date is valid and false if not. * * @since __DEPLOY_VERSION__ */ - private function validateDate($date) - { - $format = 'Ymd-His'; - $valid = Date::createFromFormat($format, $date); + private function validateDate($date) + { + $format = 'Ymd-His'; + $valid = Date::createFromFormat($format, $date); - return $valid && $valid->format($format) == $date; - } + return $valid && $valid->format($format) == $date; + } /** * Find file in given folder. * - * @param string $paths An path or array of path to search. - * @param string $file The file name to look for. + * @param string $paths An path or array of path to search. + * @param string $file The file name to look for. * * @return mixed $path The full path and file name for the target file, or boolean false if the file is not found in any of the paths. * From c1241de6cdefc4994d7b4a8ebeac2b84dcfd28fb Mon Sep 17 00:00:00 2001 From: Anurag <30978328+Anu1601CS@users.noreply.github.com> Date: Tue, 29 May 2018 14:30:26 +0530 Subject: [PATCH 05/79] Test (#6) Phase 2 (2 part) Mechanism to find correct core file and implementation. --- .../com_templates/Model/TemplateModel.php | 12 ++++++-- .../components/com_templates/forms/source.xml | 18 +++++++++-- .../com_templates/tmpl/template/default.php | 30 ++++++++----------- .../language/en-GB/en-GB.com_templates.ini | 5 ++-- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/administrator/components/com_templates/Model/TemplateModel.php b/administrator/components/com_templates/Model/TemplateModel.php index 7cf88d6881118..fc4e3d9ce6007 100644 --- a/administrator/components/com_templates/Model/TemplateModel.php +++ b/administrator/components/com_templates/Model/TemplateModel.php @@ -172,7 +172,7 @@ public function getCoreFile($file, $client_id) // Only allow html/ folder if ($explodeArray['1'] !== 'html') { - $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_ONLY_HTML_FOLDER_ALLOWED'), 'error'); + $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_ONLY_HTML_FOLDER_ALLOWED'), 'notice'); return false; } @@ -244,7 +244,7 @@ public function getCoreFile($file, $client_id) } } - $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND'), 'error'); + $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND'), 'warning'); return false; } @@ -315,7 +315,7 @@ private function findPath($paths, $file) if (!$path = Path::find($paths, $file)) { - $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND'), 'error'); + $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND'), 'warning'); } return $path; @@ -630,6 +630,12 @@ public function &getSource() $item->extension_id = $this->getState('extension.id'); $item->filename = $fileName; $item->source = file_get_contents($filePath); + + if ($coreFile = $this->getCoreFile($fileName, $this->template->client_id)) + { + $item->coreFile = $coreFile; + $item->core = file_get_contents($coreFile); + } } else { diff --git a/administrator/components/com_templates/forms/source.xml b/administrator/components/com_templates/forms/source.xml index 823841544041f..8aceade76c3d6 100644 --- a/administrator/components/com_templates/forms/source.xml +++ b/administrator/components/com_templates/forms/source.xml @@ -3,7 +3,7 @@
+ +
diff --git a/administrator/components/com_templates/tmpl/template/default.php b/administrator/components/com_templates/tmpl/template/default.php index 6867a431da032..26f41ec8f6c4d 100644 --- a/administrator/components/com_templates/tmpl/template/default.php +++ b/administrator/components/com_templates/tmpl/template/default.php @@ -48,22 +48,6 @@ ?> 'editor')); ?> -
-
- type == 'file') : ?> -

source->filename, $this->template->element); ?>

- - - type == 'image') : ?> -

image['path'], $this->template->element); ?>

- - - type == 'font') : ?> -

font['rel_path'], $this->template->element); ?>

- - -
-
loadTemplate('tree'); ?> @@ -83,6 +67,8 @@ type == 'file') : ?> +

source->filename, $this->template->element); ?>

+
form->getInput('source'); ?> @@ -92,6 +78,12 @@ form->getInput('extension_id'); ?> form->getInput('filename'); ?> +
+ source->coreFile)) : ?> +

source->coreFile); ?>

+ form->getInput('core'); ?> + +
type == 'archive') : ?> @@ -113,6 +105,8 @@ type == 'image') : ?> +

image['path'], $this->template->element); ?>

+
@@ -128,6 +122,8 @@ type == 'font') : ?> +

font['rel_path'], $this->template->element); ?>

+
@@ -352,4 +348,4 @@ - \ No newline at end of file + diff --git a/administrator/language/en-GB/en-GB.com_templates.ini b/administrator/language/en-GB/en-GB.com_templates.ini index b28de3618608b..910987c91d590 100644 --- a/administrator/language/en-GB/en-GB.com_templates.ini +++ b/administrator/language/en-GB/en-GB.com_templates.ini @@ -43,7 +43,7 @@ COM_TEMPLATES_DIRECTORY_NOT_WRITABLE="The template folder is not writable. Some COM_TEMPLATES_ERR_XML="Template XML data not available" COM_TEMPLATES_ERROR_CANNOT_DELETE_LAST_STYLE="Can't delete the last style of a template. To uninstall/delete a template go to: Extensions-> Manage-> Manage-> Select template to be deleted-> Select 'Uninstall'." COM_TEMPLATES_ERROR_CANNOT_UNSET_DEFAULT_STYLE="Can't unset default style." -COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND="Core file not found." +COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND="Core file not found. Some of the features may not available." COM_TEMPLATES_ERROR_COULD_NOT_COPY="Unable to copy template files to temporary folder." COM_TEMPLATES_ERROR_COULD_NOT_INSTALL="Unable to install new template from temporary folder." COM_TEMPLATES_ERROR_COULD_NOT_WRITE="Unable to delete temporary folder." @@ -64,7 +64,7 @@ COM_TEMPLATES_ERROR_IMAGE_FILE_NOT_FOUND="Image file not found." COM_TEMPLATES_ERROR_INDEX_DELETE="The file index.php can't be deleted. Make changes in the editor if you want to change the file." COM_TEMPLATES_ERROR_INVALID_FROM_NAME="Template to copy from can't be found." COM_TEMPLATES_ERROR_INVALID_TEMPLATE_NAME="Invalid template name. Please use only letters, numbers, dashes and underscores." -COM_TEMPLATES_ERROR_ONLY_HTML_FOLDER_ALLOWED="Only html/ folder allowed." +COM_TEMPLATES_ERROR_ONLY_HTML_FOLDER_ALLOWED="Diff view feature is only available for html folder." COM_TEMPLATES_ERROR_RENAME_INDEX="The file index.php can't be renamed." COM_TEMPLATES_ERROR_ROOT_DELETE="The root folder can't be deleted." COM_TEMPLATES_ERROR_SAVE_DISABLED_TEMPLATE="Unable to save a style associated to a disabled template." @@ -198,6 +198,7 @@ COM_TEMPLATES_TAB_EDITOR="Editor" COM_TEMPLATES_TAB_OVERRIDES="Create Overrides" COM_TEMPLATES_TEMPLATE_CLOSE="Close" COM_TEMPLATES_TEMPLATE_COPY="Copy Template" +COM_TEMPLATES_TEMPLATE_CORE_FILENAME="Core file "%s"." COM_TEMPLATES_TEMPLATE_DESCRIPTION="Template description." COM_TEMPLATES_TEMPLATE_DETAILS="%s Details and Files" COM_TEMPLATES_TEMPLATE_FILENAME="Editing file "%s" in template "%s"." From bcbf86e70998feee0051dfeee2ed54719e0ffc12 Mon Sep 17 00:00:00 2001 From: Anurag <30978328+Anu1601CS@users.noreply.github.com> Date: Sun, 3 Jun 2018 15:46:29 +0530 Subject: [PATCH 06/79] Remove Notice: Only available for html-folder --- administrator/components/com_templates/Model/TemplateModel.php | 2 -- administrator/language/en-GB/en-GB.com_templates.ini | 1 - 2 files changed, 3 deletions(-) diff --git a/administrator/components/com_templates/Model/TemplateModel.php b/administrator/components/com_templates/Model/TemplateModel.php index fc4e3d9ce6007..8c39e9ce24c49 100644 --- a/administrator/components/com_templates/Model/TemplateModel.php +++ b/administrator/components/com_templates/Model/TemplateModel.php @@ -172,8 +172,6 @@ public function getCoreFile($file, $client_id) // Only allow html/ folder if ($explodeArray['1'] !== 'html') { - $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_ONLY_HTML_FOLDER_ALLOWED'), 'notice'); - return false; } diff --git a/administrator/language/en-GB/en-GB.com_templates.ini b/administrator/language/en-GB/en-GB.com_templates.ini index 910987c91d590..cbc19872af569 100644 --- a/administrator/language/en-GB/en-GB.com_templates.ini +++ b/administrator/language/en-GB/en-GB.com_templates.ini @@ -64,7 +64,6 @@ COM_TEMPLATES_ERROR_IMAGE_FILE_NOT_FOUND="Image file not found." COM_TEMPLATES_ERROR_INDEX_DELETE="The file index.php can't be deleted. Make changes in the editor if you want to change the file." COM_TEMPLATES_ERROR_INVALID_FROM_NAME="Template to copy from can't be found." COM_TEMPLATES_ERROR_INVALID_TEMPLATE_NAME="Invalid template name. Please use only letters, numbers, dashes and underscores." -COM_TEMPLATES_ERROR_ONLY_HTML_FOLDER_ALLOWED="Diff view feature is only available for html folder." COM_TEMPLATES_ERROR_RENAME_INDEX="The file index.php can't be renamed." COM_TEMPLATES_ERROR_ROOT_DELETE="The root folder can't be deleted." COM_TEMPLATES_ERROR_SAVE_DISABLED_TEMPLATE="Unable to save a style associated to a disabled template." From f386da8302983b3cc930c9af64cfd6c79cb4a617 Mon Sep 17 00:00:00 2001 From: Anurag <30978328+Anu1601CS@users.noreply.github.com> Date: Mon, 4 Jun 2018 23:40:17 +0530 Subject: [PATCH 07/79] Remove Warning if core file not found (#11) Thanks. So one part of the issue https://github.com/joomla-projects/gsoc18_override_management/issues/12 is done. --- .../com_templates/Model/TemplateModel.php | 32 +++---------------- .../language/en-GB/en-GB.com_templates.ini | 1 - 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/administrator/components/com_templates/Model/TemplateModel.php b/administrator/components/com_templates/Model/TemplateModel.php index 8c39e9ce24c49..a47b4513bce33 100644 --- a/administrator/components/com_templates/Model/TemplateModel.php +++ b/administrator/components/com_templates/Model/TemplateModel.php @@ -189,7 +189,7 @@ public function getCoreFile($file, $client_id) $folder = $explodeArray['2']; $htmlPath = Path::clean($modulePath . $folder . '/tmpl/'); $fileName = $this->getSafeName($fileName); - $coreFile = $this->findPath($htmlPath, $fileName); + $coreFile = Path::find($htmlPath, $fileName); return $coreFile; } @@ -207,7 +207,7 @@ public function getCoreFile($file, $client_id) { // The new scheme, the views are directly in the component/tmpl folder $newHtmlPath = Path::clean($componentPath . $folder . '/tmpl/' . $subFolder . '/'); - $coreFile = $this->findPath($newHtmlPath, $fileName); + $coreFile = Path::find($newHtmlPath, $fileName); return $coreFile; } @@ -226,7 +226,7 @@ public function getCoreFile($file, $client_id) $subFolder = implode(DIRECTORY_SEPARATOR, $subFolder); $htmlPath = Path::clean($componentPath . $folder . '/layouts/' . $subFolder); $fileName = $this->getSafeName($fileName); - $coreFile = $this->findPath($htmlPath, $fileName); + $coreFile = Path::find($htmlPath, $fileName); return $coreFile; } @@ -236,14 +236,12 @@ public function getCoreFile($file, $client_id) $subFolder = implode(DIRECTORY_SEPARATOR, $subFolder); $htmlPath = Path::clean($layoutPath . $subFolder); $fileName = $this->getSafeName($fileName); - $coreFile = $this->findPath($htmlPath, $fileName); + $coreFile = Path::find($htmlPath, $fileName); return $coreFile; } } - $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND'), 'warning'); - return false; } @@ -297,28 +295,6 @@ private function validateDate($date) return $valid && $valid->format($format) == $date; } - /** - * Find file in given folder. - * - * @param string $paths An path or array of path to search. - * @param string $file The file name to look for. - * - * @return mixed $path The full path and file name for the target file, or boolean false if the file is not found in any of the paths. - * - * @since __DEPLOY_VERSION__ - */ - private function findPath($paths, $file) - { - $app = Factory::getApplication(); - - if (!$path = Path::find($paths, $file)) - { - $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND'), 'warning'); - } - - return $path; - } - /** * Method to auto-populate the model state. * diff --git a/administrator/language/en-GB/en-GB.com_templates.ini b/administrator/language/en-GB/en-GB.com_templates.ini index cbc19872af569..54470e802161f 100644 --- a/administrator/language/en-GB/en-GB.com_templates.ini +++ b/administrator/language/en-GB/en-GB.com_templates.ini @@ -43,7 +43,6 @@ COM_TEMPLATES_DIRECTORY_NOT_WRITABLE="The template folder is not writable. Some COM_TEMPLATES_ERR_XML="Template XML data not available" COM_TEMPLATES_ERROR_CANNOT_DELETE_LAST_STYLE="Can't delete the last style of a template. To uninstall/delete a template go to: Extensions-> Manage-> Manage-> Select template to be deleted-> Select 'Uninstall'." COM_TEMPLATES_ERROR_CANNOT_UNSET_DEFAULT_STYLE="Can't unset default style." -COM_TEMPLATES_ERROR_CORE_FILE_NOT_FOUND="Core file not found. Some of the features may not available." COM_TEMPLATES_ERROR_COULD_NOT_COPY="Unable to copy template files to temporary folder." COM_TEMPLATES_ERROR_COULD_NOT_INSTALL="Unable to install new template from temporary folder." COM_TEMPLATES_ERROR_COULD_NOT_WRITE="Unable to delete temporary folder." From 33ea597ba1b61ba7f5174e239e9a773166eb2bed Mon Sep 17 00:00:00 2001 From: Anurag <30978328+Anu1601CS@users.noreply.github.com> Date: Thu, 7 Jun 2018 16:27:44 +0530 Subject: [PATCH 08/79] Implement the diff view in template manager Implement the diff view in template manager --- .../com_templates/layouts/diffview/core.php | 14 ++ .../com_templates/layouts/diffview/diff.php | 14 ++ .../com_templates/tmpl/template/default.php | 79 +++++++-- .../language/en-GB/en-GB.com_templates.ini | 9 +- .../css/admin-templates-default.css | 21 +++ .../css/admin-templates-default.min.css | 2 +- .../js/admin-template-compare.es6.js | 150 +++++++++++++++++ .../js/admin-template-compare.es6.min.js | 1 + .../js/admin-template-compare.js | 159 ++++++++++++++++++ .../js/admin-template-compare.min.js | 1 + 10 files changed, 431 insertions(+), 19 deletions(-) create mode 100644 administrator/components/com_templates/layouts/diffview/core.php create mode 100644 administrator/components/com_templates/layouts/diffview/diff.php create mode 100644 media/com_templates/js/admin-template-compare.es6.js create mode 100644 media/com_templates/js/admin-template-compare.es6.min.js create mode 100644 media/com_templates/js/admin-template-compare.js create mode 100644 media/com_templates/js/admin-template-compare.min.js diff --git a/administrator/components/com_templates/layouts/diffview/core.php b/administrator/components/com_templates/layouts/diffview/core.php new file mode 100644 index 0000000000000..630f501fe31b5 --- /dev/null +++ b/administrator/components/com_templates/layouts/diffview/core.php @@ -0,0 +1,14 @@ + + diff --git a/administrator/components/com_templates/layouts/diffview/diff.php b/administrator/components/com_templates/layouts/diffview/diff.php new file mode 100644 index 0000000000000..b250ba3959a6a --- /dev/null +++ b/administrator/components/com_templates/layouts/diffview/diff.php @@ -0,0 +1,14 @@ + + diff --git a/administrator/components/com_templates/tmpl/template/default.php b/administrator/components/com_templates/tmpl/template/default.php index 26f41ec8f6c4d..b3d96acebc143 100644 --- a/administrator/components/com_templates/tmpl/template/default.php +++ b/administrator/components/com_templates/tmpl/template/default.php @@ -9,9 +9,19 @@ defined('_JEXEC') or die; +use Joomla\CMS\Layout\FileLayout; + // Include the component HTML helpers. JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html'); +JText::script('COM_TEMPLATES_LAYOUTS_DIFFVIEW_SHOW_CORE'); +JText::script('COM_TEMPLATES_LAYOUTS_DIFFVIEW_HIDE_CORE'); +JText::script('COM_TEMPLATES_LAYOUTS_DIFFVIEW_SHOW_DIFF'); +JText::script('COM_TEMPLATES_LAYOUTS_DIFFVIEW_HIDE_DIFF'); + +JHtml::_('script', 'vendor/diff/diff.min.js', array('version' => 'auto', 'relative' => true)); +JHtml::_('script', 'com_templates/admin-template-compare.min.js', array('version' => 'auto', 'relative' => true)); + JHtml::_('behavior.formvalidator'); JHtml::_('behavior.keepalive'); JHtml::_('behavior.tabstate'); @@ -48,6 +58,30 @@ ?> 'editor')); ?> +
+
+ type == 'file') : ?> +

source->filename, $this->template->element); ?>

+ + + type == 'image') : ?> +

image['path'], $this->template->element); ?>

+ + + type == 'font') : ?> +

font['rel_path'], $this->template->element); ?>

+ + +
+ type == 'file' && !empty($this->source->coreFile)) : ?> +
+ + render(array()); ?> + + render(array()); ?> +
+ +
loadTemplate('tree'); ?> @@ -67,21 +101,36 @@ type == 'file') : ?> -

source->filename, $this->template->element); ?>

- -
-
- form->getInput('source'); ?> +
+
+

+ +
+ form->getInput('source'); ?> +
+ + + form->getInput('extension_id'); ?> + form->getInput('filename'); ?> +
- - - form->getInput('extension_id'); ?> - form->getInput('filename'); ?> - -
source->coreFile)) : ?> -

source->coreFile); ?>

- form->getInput('core'); ?> + source->coreFile); ?> + template->element . $this->source->filename); ?> + +
@@ -105,8 +154,6 @@ type == 'image') : ?> -

image['path'], $this->template->element); ?>

-
@@ -122,8 +169,6 @@ type == 'font') : ?> -

font['rel_path'], $this->template->element); ?>

-
diff --git a/administrator/language/en-GB/en-GB.com_templates.ini b/administrator/language/en-GB/en-GB.com_templates.ini index 54470e802161f..13903a7cac1a3 100644 --- a/administrator/language/en-GB/en-GB.com_templates.ini +++ b/administrator/language/en-GB/en-GB.com_templates.ini @@ -90,7 +90,9 @@ COM_TEMPLATES_FILE_ARCHIVE_EXTRACT_SUCCESS="Successfully extracted the archive f COM_TEMPLATES_FILE_ARCHIVE_EXTRACT_FAIL="Failed to extract the archive file." COM_TEMPLATES_FILE_CREATE_ERROR="An error occurred creating the file." COM_TEMPLATES_FILE_CREATE_SUCCESS="File created." -COM_TEMPLATES_FILE_CONTENT_PREVIEW="File Content Preview" +COM_TEMPLATES_FILE_COMPARE_PANE="Compare or diff view between Core and Override file." +COM_TEMPLATES_FILE_CONTENT_PREVIEW="File Content Preview." +COM_TEMPLATES_FILE_CORE_PANE="Core file readonly." COM_TEMPLATES_FILE_COPY_FAIL="Failed to copy the file." COM_TEMPLATES_FILE_COPY_SUCCESS="The current file was copied as %s." COM_TEMPLATES_FILE_CROP_ERROR="Failed to crop image." @@ -103,6 +105,7 @@ COM_TEMPLATES_FILE_NEW_NAME_LABEL="Copied File Name" COM_TEMPLATES_FILE_EXISTS="File with the same name already exists." COM_TEMPLATES_FILE_INFO="File Information" COM_TEMPLATES_FILE_NAME="File Name" +COM_TEMPLATES_FILE_OVERRIDE_PANE="Override file editable." COM_TEMPLATES_FILE_PERMISSIONS="The File Permissions are %s" COM_TEMPLATES_FILE_RENAME_ERROR="An error occurred renaming the file." COM_TEMPLATES_FILE_RENAME_SUCCESS="File renamed." @@ -144,6 +147,10 @@ COM_TEMPLATES_IMAGE_WIDTH="Width" COM_TEMPLATES_INVALID_FILE_NAME="Invalid file name. Please choose a file name containing a-z, A-Z, 0-9, - and _." COM_TEMPLATES_INVALID_FILE_TYPE="File type not selected." COM_TEMPLATES_INVALID_FOLDER_NAME="Invalid folder name. Please choose a folder name containing a-z, A-Z, 0-9, - and _." +COM_TEMPLATES_LAYOUTS_DIFFVIEW_HIDE_CORE="Hide Core" +COM_TEMPLATES_LAYOUTS_DIFFVIEW_HIDE_DIFF="Hide Diff" +COM_TEMPLATES_LAYOUTS_DIFFVIEW_SHOW_CORE="Show Core" +COM_TEMPLATES_LAYOUTS_DIFFVIEW_SHOW_DIFF="Show Diff" COM_TEMPLATES_MANAGER_ADD_STYLE="Templates: Add Style" COM_TEMPLATES_MANAGER_EDIT_STYLE="Templates: Edit Style" COM_TEMPLATES_MANAGE_FOLDERS="Manage Folders" diff --git a/media/com_templates/css/admin-templates-default.css b/media/com_templates/css/admin-templates-default.css index 89f889c3df52d..0b6205f1c8921 100644 --- a/media/com_templates/css/admin-templates-default.css +++ b/media/com_templates/css/admin-templates-default.css @@ -7,11 +7,13 @@ background: #08c; color: #fff; } + .selected:hover, .selected:focus { background: #08c !important; color: #fff; } + #deleteFolder { margin: 0; } @@ -29,3 +31,22 @@ .treeselect a { display: block; } + +.diffview { + white-space: pre-wrap; + word-wrap: break-word; + display: inline; + padding: 4px; + border-radius: .2em; +} + +.diff-pane { + height: 350px; + border: 0.5px solid grey; + overflow: auto; + padding: 10px; +} + +#core-pane .CodeMirror-code { + background-color: #F0F0EE; +} diff --git a/media/com_templates/css/admin-templates-default.min.css b/media/com_templates/css/admin-templates-default.min.css index 9e43a01afbb83..36cbbdbdd9759 100644 --- a/media/com_templates/css/admin-templates-default.min.css +++ b/media/com_templates/css/admin-templates-default.min.css @@ -1 +1 @@ -.selected{background:#08c;color:#fff}.selected:hover,.selected:focus{background:#08c !important;color:#fff}#deleteFolder{margin:0}#image-crop{max-width:100% !important;width:auto;height:auto}.tree-holder{overflow-x:auto}.treeselect a{display:block} \ No newline at end of file +.selected{background:#08c;color:#fff}.selected:hover,.selected:focus{background:#08c !important;color:#fff}#deleteFolder{margin:0}#image-crop{max-width:100% !important;width:auto;height:auto}.tree-holder{overflow-x:auto}.treeselect a{display:block}.diffview{white-space:pre-wrap;word-wrap:break-word;display:inline;padding:4px;border-radius:.2em}.diff-pane{height:350px;border:.5px solid grey;overflow:auto;padding:10px}#core-pane .CodeMirror-code{background-color:#f0f0ee} \ No newline at end of file diff --git a/media/com_templates/js/admin-template-compare.es6.js b/media/com_templates/js/admin-template-compare.es6.js new file mode 100644 index 0000000000000..233e348641aa1 --- /dev/null +++ b/media/com_templates/js/admin-template-compare.es6.js @@ -0,0 +1,150 @@ +/** + * @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ +(() => { + document.addEventListener('DOMContentLoaded', () => { + const decodeHtmlspecialChars = (text) => { + const map = { + '&': '&', + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'", + '’': '’', + '‘': '‘', + '–': '–', + '—': '—', + '…': '…', + '”': '”', + }; + + return text.replace(/\&[\w\d\#]{2,5}\;/g, (m) => { const n = map[m]; return n; }); + }; + + const compare = (original, changed) => { + const display = changed.nextElementSibling; + let color = ''; + let pre = null; + const diff = JsDiff.diffLines(original.innerHTML, changed.innerHTML); + const fragment = document.createDocumentFragment(); + + diff.forEach((part) => { + if (part.added) { + color = '#a6f3a6'; + } else if (part.removed) { + color = '#f8cbcb'; + } else { + color = ''; + } + pre = document.createElement('pre'); + pre.style.backgroundColor = color; + pre.className = 'diffview'; + pre.appendChild(document.createTextNode(decodeHtmlspecialChars(part.value))); + fragment.appendChild(pre); + }); + + display.appendChild(fragment); + }; + + const buttonDataSelector = 'onclick-task'; + const override = document.getElementById('override-pane'); + const corePane = document.getElementById('core-pane'); + const diffMain = document.getElementById('diff-main'); + + const toggle = (e) => { + const task = e.target.getAttribute(buttonDataSelector); + if (task === 'template.show.core') { + if (corePane) { + const { display } = corePane.style; + if (display === 'none') { + e.target.className = 'btn btn-success'; + e.target.innerHTML = Joomla.JText._('COM_TEMPLATES_LAYOUTS_DIFFVIEW_HIDE_CORE'); + corePane.style.display = 'block'; + override.className = 'col-md-6'; + Joomla.editors.instances.jform_core.refresh(); + } else { + e.target.className = 'btn btn-danger'; + e.target.innerHTML = Joomla.JText._('COM_TEMPLATES_LAYOUTS_DIFFVIEW_SHOW_CORE'); + corePane.style.display = 'none'; + override.className = 'col-md-12'; + } + const coreState = { + class: e.target.className, + title: e.target.innerHTML, + display: corePane.style.display, + overrideClass: override.className, + }; + + if (typeof (Storage) !== 'undefined') { + localStorage.setItem('coreButtonState', JSON.stringify(coreState)); + } + } + } else if (task === 'template.show.diff') { + if (diffMain) { + const { display } = diffMain.style; + if (display === 'none') { + e.target.className = 'btn btn-success'; + e.target.innerHTML = Joomla.JText._('COM_TEMPLATES_LAYOUTS_DIFFVIEW_HIDE_DIFF'); + diffMain.style.display = 'block'; + } else { + e.target.className = 'btn btn-danger'; + e.target.innerHTML = Joomla.JText._('COM_TEMPLATES_LAYOUTS_DIFFVIEW_SHOW_DIFF'); + diffMain.style.display = 'none'; + } + const diffState = { + class: e.target.className, + title: e.target.innerHTML, + display: diffMain.style.display, + }; + + if (typeof (Storage) !== 'undefined') { + localStorage.setItem('diffButtonState', JSON.stringify(diffState)); + } + } + } + }; + + const buttons = [].slice.call(document.querySelectorAll(`[${buttonDataSelector}]`)); + const conditionalSection = document.getElementById('conditional-section'); + + const setPrestate = () => { + if (typeof (Storage) !== 'undefined') { + const cState = JSON.parse(localStorage.getItem('coreButtonState')); + const dState = JSON.parse(localStorage.getItem('diffButtonState')); + + if (cState !== null) { + buttons[0].className = cState.class; + buttons[0].innerHTML = cState.title; + corePane.style.display = cState.display; + override.className = cState.overrideClass; + } + + if (dState !== null) { + buttons[1].className = dState.class; + buttons[1].innerHTML = dState.title; + diffMain.style.display = dState.display; + } + } + }; + + if (buttons.length !== 0) { + buttons.forEach((button) => { + button.addEventListener('click', (e) => { + e.preventDefault(); + toggle(e); + }); + }); + setPrestate(); + } else if (override && conditionalSection) { + conditionalSection.className = 'col-md-12'; + override.className = 'col-md-12'; + } + + const diffs = [].slice.call(document.querySelectorAll('#original')); + for (let i = 0, l = diffs.length; i < l; i += 1) { + compare(diffs[i], diffs[i].nextElementSibling); + } + }); +})(); diff --git a/media/com_templates/js/admin-template-compare.es6.min.js b/media/com_templates/js/admin-template-compare.es6.min.js new file mode 100644 index 0000000000000..db882c31ca462 --- /dev/null +++ b/media/com_templates/js/admin-template-compare.es6.min.js @@ -0,0 +1 @@ +document.addEventListener("DOMContentLoaded",()=>{const e=(e,t)=>{const a=t.nextElementSibling;let l="",n=null;const s=JsDiff.diffLines(e.innerHTML,t.innerHTML),o=document.createDocumentFragment();s.forEach(e=>{l=e.added?"#a6f3a6":e.removed?"#f8cbcb":"",(n=document.createElement("pre")).style.backgroundColor=l,n.className="diffview",n.appendChild(document.createTextNode((e=>{const t={"&":"&","&":"&","<":"<",">":">",""":'"',"'":"'","’":"’","‘":"‘","–":"–","—":"—","…":"…","”":"”"};return e.replace(/\&[\w\d\#]{2,5}\;/g,e=>t[e])})(e.value))),o.appendChild(n)}),a.appendChild(o)},t=document.getElementById("override-pane"),a=document.getElementById("core-pane"),l=document.getElementById("diff-main"),n=[].slice.call(document.querySelectorAll("[onclick-task]")),s=document.getElementById("conditional-section");0!==n.length?(n.forEach(e=>{e.addEventListener("click",e=>{e.preventDefault(),(e=>{const n=e.target.getAttribute("onclick-task");if("template.show.core"===n){if(a){const{display:l}=a.style;"none"===l?(e.target.className="btn btn-success",e.target.innerHTML=Joomla.JText._("COM_TEMPLATES_LAYOUTS_DIFFVIEW_HIDE_CORE"),a.style.display="block",t.className="col-md-6",Joomla.editors.instances.jform_core.refresh()):(e.target.className="btn btn-danger",e.target.innerHTML=Joomla.JText._("COM_TEMPLATES_LAYOUTS_DIFFVIEW_SHOW_CORE"),a.style.display="none",t.className="col-md-12");const n={class:e.target.className,title:e.target.innerHTML,display:a.style.display,overrideClass:t.className};"undefined"!=typeof Storage&&localStorage.setItem("coreButtonState",JSON.stringify(n))}}else if("template.show.diff"===n&&l){const{display:t}=l.style;"none"===t?(e.target.className="btn btn-success",e.target.innerHTML=Joomla.JText._("COM_TEMPLATES_LAYOUTS_DIFFVIEW_HIDE_DIFF"),l.style.display="block"):(e.target.className="btn btn-danger",e.target.innerHTML=Joomla.JText._("COM_TEMPLATES_LAYOUTS_DIFFVIEW_SHOW_DIFF"),l.style.display="none");const a={class:e.target.className,title:e.target.innerHTML,display:l.style.display};"undefined"!=typeof Storage&&localStorage.setItem("diffButtonState",JSON.stringify(a))}})(e)})}),(()=>{if("undefined"!=typeof Storage){const e=JSON.parse(localStorage.getItem("coreButtonState")),s=JSON.parse(localStorage.getItem("diffButtonState"));null!==e&&(n[0].className=e.class,n[0].innerHTML=e.title,a.style.display=e.display,t.className=e.overrideClass),null!==s&&(n[1].className=s.class,n[1].innerHTML=s.title,l.style.display=s.display)}})()):t&&s&&(s.className="col-md-12",t.className="col-md-12");const o=[].slice.call(document.querySelectorAll("#original"));for(let t=0,a=o.length;t', + '"': '"', + ''': "'", + '’': '’', + '‘': '‘', + '–': '–', + '—': '—', + '…': '…', + '”': '”' + }; + + return text.replace(/\&[\w\d\#]{2,5}\;/g, function (m) { + var n = map[m];return n; + }); + }; + + var compare = function compare(original, changed) { + var display = changed.nextElementSibling; + var color = ''; + var pre = null; + var diff = JsDiff.diffLines(original.innerHTML, changed.innerHTML); + var fragment = document.createDocumentFragment(); + + diff.forEach(function (part) { + if (part.added) { + color = '#a6f3a6'; + } else if (part.removed) { + color = '#f8cbcb'; + } else { + color = ''; + } + pre = document.createElement('pre'); + pre.style.backgroundColor = color; + pre.className = 'diffview'; + pre.appendChild(document.createTextNode(decodeHtmlspecialChars(part.value))); + fragment.appendChild(pre); + }); + + display.appendChild(fragment); + }; + + var buttonDataSelector = 'onclick-task'; + var override = document.getElementById('override-pane'); + var corePane = document.getElementById('core-pane'); + var diffMain = document.getElementById('diff-main'); + + var toggle = function toggle(e) { + var task = e.target.getAttribute(buttonDataSelector); + if (task === 'template.show.core') { + if (corePane) { + var display = corePane.style.display; + + if (display === 'none') { + e.target.className = 'btn btn-success'; + e.target.innerHTML = Joomla.JText._('COM_TEMPLATES_LAYOUTS_DIFFVIEW_HIDE_CORE'); + corePane.style.display = 'block'; + override.className = 'col-md-6'; + Joomla.editors.instances.jform_core.refresh(); + } else { + e.target.className = 'btn btn-danger'; + e.target.innerHTML = Joomla.JText._('COM_TEMPLATES_LAYOUTS_DIFFVIEW_SHOW_CORE'); + corePane.style.display = 'none'; + override.className = 'col-md-12'; + } + var coreState = { + class: e.target.className, + title: e.target.innerHTML, + display: corePane.style.display, + overrideClass: override.className + }; + + if (typeof Storage !== 'undefined') { + localStorage.setItem('coreButtonState', JSON.stringify(coreState)); + } + } + } else if (task === 'template.show.diff') { + if (diffMain) { + var _display = diffMain.style.display; + + if (_display === 'none') { + e.target.className = 'btn btn-success'; + e.target.innerHTML = Joomla.JText._('COM_TEMPLATES_LAYOUTS_DIFFVIEW_HIDE_DIFF'); + diffMain.style.display = 'block'; + } else { + e.target.className = 'btn btn-danger'; + e.target.innerHTML = Joomla.JText._('COM_TEMPLATES_LAYOUTS_DIFFVIEW_SHOW_DIFF'); + diffMain.style.display = 'none'; + } + var diffState = { + class: e.target.className, + title: e.target.innerHTML, + display: diffMain.style.display + }; + + if (typeof Storage !== 'undefined') { + localStorage.setItem('diffButtonState', JSON.stringify(diffState)); + } + } + } + }; + + var buttons = [].slice.call(document.querySelectorAll('[' + buttonDataSelector + ']')); + var conditionalSection = document.getElementById('conditional-section'); + + var setPrestate = function setPrestate() { + if (typeof Storage !== 'undefined') { + var cState = JSON.parse(localStorage.getItem('coreButtonState')); + var dState = JSON.parse(localStorage.getItem('diffButtonState')); + + if (cState !== null) { + buttons[0].className = cState.class; + buttons[0].innerHTML = cState.title; + corePane.style.display = cState.display; + override.className = cState.overrideClass; + } + + if (dState !== null) { + buttons[1].className = dState.class; + buttons[1].innerHTML = dState.title; + diffMain.style.display = dState.display; + } + } + }; + + if (buttons.length !== 0) { + buttons.forEach(function (button) { + button.addEventListener('click', function (e) { + e.preventDefault(); + toggle(e); + }); + }); + setPrestate(); + } else if (override && conditionalSection) { + conditionalSection.className = 'col-md-12'; + override.className = 'col-md-12'; + } + + var diffs = [].slice.call(document.querySelectorAll('#original')); + for (var i = 0, l = diffs.length; i < l; i += 1) { + compare(diffs[i], diffs[i].nextElementSibling); + } + }); +})(); diff --git a/media/com_templates/js/admin-template-compare.min.js b/media/com_templates/js/admin-template-compare.min.js new file mode 100644 index 0000000000000..d00cde76e1945 --- /dev/null +++ b/media/com_templates/js/admin-template-compare.min.js @@ -0,0 +1 @@ +document.addEventListener("DOMContentLoaded",function(){var e=function(e,t){var a=t.nextElementSibling,n="",l=null,s=JsDiff.diffLines(e.innerHTML,t.innerHTML),o=document.createDocumentFragment();s.forEach(function(e){var t,a;n=e.added?"#a6f3a6":e.removed?"#f8cbcb":"",(l=document.createElement("pre")).style.backgroundColor=n,l.className="diffview",l.appendChild(document.createTextNode((t=e.value,a={"&":"&","&":"&","<":"<",">":">",""":'"',"'":"'","’":"’","‘":"‘","–":"–","—":"—","…":"…","”":"”"},t.replace(/\&[\w\d\#]{2,5}\;/g,function(e){return a[e]})))),o.appendChild(l)}),a.appendChild(o)},t=document.getElementById("override-pane"),a=document.getElementById("core-pane"),n=document.getElementById("diff-main"),l=[].slice.call(document.querySelectorAll("[onclick-task]")),s=document.getElementById("conditional-section");0!==l.length?(l.forEach(function(e){e.addEventListener("click",function(e){e.preventDefault(),function(e){var l=e.target.getAttribute("onclick-task");if("template.show.core"===l){if(a){"none"===a.style.display?(e.target.className="btn btn-success",e.target.innerHTML=Joomla.JText._("COM_TEMPLATES_LAYOUTS_DIFFVIEW_HIDE_CORE"),a.style.display="block",t.className="col-md-6",Joomla.editors.instances.jform_core.refresh()):(e.target.className="btn btn-danger",e.target.innerHTML=Joomla.JText._("COM_TEMPLATES_LAYOUTS_DIFFVIEW_SHOW_CORE"),a.style.display="none",t.className="col-md-12");var s={class:e.target.className,title:e.target.innerHTML,display:a.style.display,overrideClass:t.className};"undefined"!=typeof Storage&&localStorage.setItem("coreButtonState",JSON.stringify(s))}}else if("template.show.diff"===l&&n){"none"===n.style.display?(e.target.className="btn btn-success",e.target.innerHTML=Joomla.JText._("COM_TEMPLATES_LAYOUTS_DIFFVIEW_HIDE_DIFF"),n.style.display="block"):(e.target.className="btn btn-danger",e.target.innerHTML=Joomla.JText._("COM_TEMPLATES_LAYOUTS_DIFFVIEW_SHOW_DIFF"),n.style.display="none");var o={class:e.target.className,title:e.target.innerHTML,display:n.style.display};"undefined"!=typeof Storage&&localStorage.setItem("diffButtonState",JSON.stringify(o))}}(e)})}),function(){if("undefined"!=typeof Storage){var e=JSON.parse(localStorage.getItem("coreButtonState")),s=JSON.parse(localStorage.getItem("diffButtonState"));null!==e&&(l[0].className=e.class,l[0].innerHTML=e.title,a.style.display=e.display,t.className=e.overrideClass),null!==s&&(l[1].className=s.class,l[1].innerHTML=s.title,n.style.display=s.display)}}()):t&&s&&(s.className="col-md-12",t.className="col-md-12");for(var o=[].slice.call(document.querySelectorAll("#original")),i=0,r=o.length;i Date: Mon, 18 Jun 2018 13:18:01 +0200 Subject: [PATCH 09/79] coding standard (#17) --- administrator/components/com_templates/forms/source.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_templates/forms/source.xml b/administrator/components/com_templates/forms/source.xml index 8aceade76c3d6..a61fdf9e711f4 100644 --- a/administrator/components/com_templates/forms/source.xml +++ b/administrator/components/com_templates/forms/source.xml @@ -35,7 +35,7 @@ cols="80" syntax="php" filter="raw" - readonly="true" + readonly="true" />
From d370e946fb1666bf0d2d42f19370ea80f55f6986 Mon Sep 17 00:00:00 2001 From: Anurag <30978328+Anu1601CS@users.noreply.github.com> Date: Tue, 19 Jun 2018 02:26:06 +0530 Subject: [PATCH 10/79] fix diff (#18) Fix bug in path in case of administrator template override. Fix bug in path in case of administrator template override. --- administrator/components/com_templates/Model/TemplateModel.php | 1 + .../components/com_templates/tmpl/template/default.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/administrator/components/com_templates/Model/TemplateModel.php b/administrator/components/com_templates/Model/TemplateModel.php index a47b4513bce33..8fadc4f6523a8 100644 --- a/administrator/components/com_templates/Model/TemplateModel.php +++ b/administrator/components/com_templates/Model/TemplateModel.php @@ -604,6 +604,7 @@ public function &getSource() $item->extension_id = $this->getState('extension.id'); $item->filename = $fileName; $item->source = file_get_contents($filePath); + $item->filePath = $filePath; if ($coreFile = $this->getCoreFile($fileName, $this->template->client_id)) { diff --git a/administrator/components/com_templates/tmpl/template/default.php b/administrator/components/com_templates/tmpl/template/default.php index b3d96acebc143..ed53d037152ef 100644 --- a/administrator/components/com_templates/tmpl/template/default.php +++ b/administrator/components/com_templates/tmpl/template/default.php @@ -116,7 +116,7 @@
source->coreFile)) : ?> source->coreFile); ?> - template->element . $this->source->filename); ?> + source->filePath); ?>
diff --git a/administrator/components/com_templates/layouts/diffview/core.php b/administrator/components/com_templates/layouts/diffview/core.php deleted file mode 100644 index 630f501fe31b5..0000000000000 --- a/administrator/components/com_templates/layouts/diffview/core.php +++ /dev/null @@ -1,14 +0,0 @@ - - diff --git a/administrator/components/com_templates/layouts/diffview/diff.php b/administrator/components/com_templates/layouts/diffview/diff.php deleted file mode 100644 index b250ba3959a6a..0000000000000 --- a/administrator/components/com_templates/layouts/diffview/diff.php +++ /dev/null @@ -1,14 +0,0 @@ - - diff --git a/administrator/components/com_templates/tmpl/template/default.php b/administrator/components/com_templates/tmpl/template/default.php index 11e24039cff75..8d152403c4332 100644 --- a/administrator/components/com_templates/tmpl/template/default.php +++ b/administrator/components/com_templates/tmpl/template/default.php @@ -28,6 +28,7 @@ HTMLHelper::_('script', 'vendor/diff/diff.min.js', array('version' => 'auto', 'relative' => true)); HTMLHelper::_('script', 'com_templates/admin-template-compare.min.js', array('version' => 'auto', 'relative' => true)); +HTMLHelper::_('script', 'com_templates/admin-template-toggle-switch.min.js', array('version' => 'auto', 'relative' => true)); HTMLHelper::_('behavior.formvalidator'); HTMLHelper::_('behavior.keepalive'); @@ -84,10 +85,8 @@
type == 'file' && !empty($this->source->coreFile)) : ?>
- - render(array()); ?> - - render(array()); ?> + form->getInput('show_core'); ?> + form->getInput('show_diff'); ?>
@@ -126,13 +125,13 @@ source->coreFile)) : ?> source->coreFile); ?> source->filePath); ?> -