Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.1 com_templates, child templates 2/2 #35879

Closed
Closed
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
ed0a641
New mode for cassiopeia and atum
dgrammatiko Oct 22, 2021
ed0fa0a
DB Changes
dgrammatiko Oct 22, 2021
d29cd20
Fix wrong import paths
dgrammatiko Oct 22, 2021
108250f
SQL for updates
dgrammatiko Oct 22, 2021
843a3b4
Deleted files and folder for changing core templates to inheritable
richard67 Oct 22, 2021
60476dd
Better version comments
richard67 Oct 22, 2021
4b3c5f0
Merge pull request #4 from richard67/4.1-dev-dgrammatiko-child-templa…
dgrammatiko Oct 22, 2021
cac4933
Move custom files in core templates to media folder on update
richard67 Oct 22, 2021
6de4fc4
Better English in the comment
richard67 Oct 22, 2021
06edcdc
Merge pull request #5 from richard67/4.1-dev-dgrammatiko-child-templa…
dgrammatiko Oct 22, 2021
dca3ac9
Fix some paths
dgrammatiko Oct 22, 2021
00e431b
System templates
dgrammatiko Oct 22, 2021
8680438
Deleted files and folders for system templates
richard67 Oct 23, 2021
09b4d89
Move template preview files, too
richard67 Oct 23, 2021
9faa291
Create parent folders if necessary at target path
richard67 Oct 23, 2021
1562dff
Don't delete template previews
richard67 Oct 23, 2021
aa87408
Merge pull request #6 from richard67/4.1-dev-dgrammatiko-child-templa…
dgrammatiko Oct 23, 2021
d8a1d8b
Revert special handling for core template preview images
richard67 Oct 23, 2021
d59f121
Merge pull request #7 from richard67/4.1-dev-dgrammatiko-child-templa…
dgrammatiko Oct 23, 2021
40f24d9
move images to the correct folder
dgrammatiko Oct 23, 2021
d08883b
Fix the thumb/preview paths
dgrammatiko Oct 23, 2021
8502440
xmldata not always in the template object
dgrammatiko Oct 23, 2021
cef1870
CS
dgrammatiko Oct 23, 2021
4ded3d7
Child Creation logic
dgrammatiko Oct 23, 2021
2725303
Create a media folder
dgrammatiko Oct 23, 2021
0d3af89
more
dgrammatiko Oct 28, 2021
e7e0304
tree-view
dgrammatiko Nov 1, 2021
5a8cb83
more
dgrammatiko Nov 1, 2021
9169c32
Fix the adapter, fallback image
dgrammatiko Nov 2, 2021
e9ebc5d
Lang, child tmpls name convention: parent_child
dgrammatiko Nov 2, 2021
bbbf42b
Fix the img paths
dgrammatiko Nov 2, 2021
132b236
Fix roboto path
dgrammatiko Nov 2, 2021
5c68f5c
CS
dgrammatiko Nov 2, 2021
bc2914a
CS
dgrammatiko Nov 2, 2021
10ce4d4
Update administrator/components/com_templates/src/Model/TemplateModel…
dgrammatiko Nov 2, 2021
083fee5
Update administrator/components/com_templates/src/Model/TemplateModel…
dgrammatiko Nov 2, 2021
b3c3a56
Update administrator/components/com_templates/src/Model/TemplateModel…
dgrammatiko Nov 2, 2021
3c2b599
Update administrator/components/com_templates/tmpl/template/default_m…
dgrammatiko Nov 2, 2021
d6d1650
Update administrator/components/com_templates/tmpl/template/default_m…
dgrammatiko Nov 2, 2021
d330cf8
Update administrator/components/com_templates/src/Service/HTML/Templa…
dgrammatiko Nov 2, 2021
1e33423
Update administrator/components/com_templates/src/Service/HTML/Templa…
dgrammatiko Nov 2, 2021
ba76d9c
CS
dgrammatiko Nov 2, 2021
0f61e00
beatify the tree (still not a11y compliant)
dgrammatiko Nov 2, 2021
36a2d55
meh
dgrammatiko Nov 2, 2021
071e0a2
prevent default
dgrammatiko Nov 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Child Creation logic
dgrammatiko committed Oct 23, 2021
commit 4ded3d7a548794607781d38b69be4557845b9876
Original file line number Diff line number Diff line change
@@ -980,4 +980,103 @@ public function ajax()

$app->close();
}

/**
* Method for copying the template.
*
* @return boolean true on success, false otherwise
*
* @since __DEPLOY_VERSION__
*/
public function child()
{
// Check for request forgeries
$this->checkToken();

$app = $this->app;
$this->input->set('installtype', 'folder');
$newNameRaw = $this->input->get('new_name', null, 'string');
// Only accept letters, numbers and underscore for template name
$newName = preg_replace('/[^a-zA-Z0-9_]/', '', $newNameRaw);
$templateID = (int) $this->input->getInt('id', 0);
$file = (string) $this->input->get('file', '', 'cmd');

// Access check.
if (!$this->allowEdit()) {
$app->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error');

return false;
}

$this->setRedirect('index.php?option=com_templates&view=template&id=' . $templateID . '&file=' . $file);

/* @var \Joomla\Component\Templates\Administrator\Model\TemplateModel $model */
$model = $this->getModel('Template', 'Administrator');
$model->setState('new_name', $newName);
$model->setState('tmp_prefix', uniqid('template_child_'));
$model->setState('to_path', $app->get('tmp_path') . '/' . $model->getState('tmp_prefix'));

// Process only if we have a new name entered
if (strlen($newName) > 0) {
if (!$this->app->getIdentity()->authorise('core.create', 'com_templates')) {
// User is not authorised to delete
$this->setMessage(Text::_('COM_TEMPLATES_ERROR_CREATE_NOT_PERMITTED'), 'error');

return false;
}

// Check that new name is valid
if (($newNameRaw !== null) && ($newName !== $newNameRaw)) {
$this->setMessage(Text::_('COM_TEMPLATES_ERROR_INVALID_TEMPLATE_NAME'), 'error');

return false;
}

// Check that new name doesn't already exist
if (!$model->checkNewName()) {
$this->setMessage(Text::_('COM_TEMPLATES_ERROR_DUPLICATE_TEMPLATE_NAME'), 'error');

return false;
}

// Check that from name does exist and get the folder name
$fromName = $model->getFromName();

if (!$fromName) {
$this->setMessage(Text::_('COM_TEMPLATES_ERROR_INVALID_FROM_NAME'), 'error');

return false;
}

// Call model's copy method
if (!$model->child()) {
$this->setMessage(Text::_('COM_TEMPLATES_ERROR_COULD_NOT_COPY'), 'error');

return false;
}

// Call installation model
$this->input->set('install_directory', $app->get('tmp_path') . '/' . $model->getState('tmp_prefix'));

/** @var \Joomla\Component\Installer\Administrator\Model\InstallModel $installModel */
$installModel = $this->app->bootComponent('com_installer')
->getMVCFactory()->createModel('Install', 'Administrator');
$this->app->getLanguage()->load('com_installer');

if (!$installModel->install()) {
$this->setMessage(Text::_('COM_TEMPLATES_ERROR_COULD_NOT_INSTALL'), 'error');

return false;
}

$this->setMessage(Text::sprintf('COM_TEMPLATES_CHILD_SUCCESS', $newName));
$model->cleanup();

return true;
}

$this->setMessage(Text::sprintf('COM_TEMPLATES_ERROR_INVALID_TEMPLATE_NAME'), 'error');

return false;
}
}
Original file line number Diff line number Diff line change
@@ -419,6 +419,8 @@ protected function preprocessForm(Form $form, $data, $group = 'content')

// Load the core and/or local language file(s).
$lang->load('tpl_' . $template, $client->path)
|| $lang->load('tpl_' . $data->parent, $client->path)
|| $lang->load('tpl_' . $data->parent, $client->path . '/templates/' . $data->parent)
|| $lang->load('tpl_' . $template, $client->path . '/templates/' . $template);

if (file_exists($formFile))
85 changes: 85 additions & 0 deletions administrator/components/com_templates/src/Model/TemplateModel.php
Original file line number Diff line number Diff line change
@@ -25,7 +25,9 @@
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\Uri\Uri;
use Joomla\Component\Templates\Administrator\Helper\TemplateHelper;
use Joomla\Component\Templates\Administrator\Helper\TemplatesHelper;
use Joomla\Database\ParameterType;
use JsonSchema\Uri\Retrievers\FileGetContents;

/**
* Template model class.
@@ -665,6 +667,9 @@ public function &getTemplate()
else
{
$this->template = $result;
if (!isset($this->template->xmldata)) {
$this->template->xmldata = TemplatesHelper::parseXMLTemplateFile($this->template->client_id === 0 ? JPATH_ROOT : JPATH_ROOT . '/administrator', $this->template->name);
}
}
}

@@ -1985,4 +1990,84 @@ protected function checkFormat($ext)

return in_array(strtolower($ext), $this->allowedFormats);
}

/**
* Method to check if new template name already exists
*
* @return boolean true if name is not used, false otherwise
*
* @since __DEPLOY_VERSION__
*/
public function child()
{
$app = Factory::getApplication();

if ($template = $this->getTemplate()) {
$client = ApplicationHelper::getClientInfo($template->client_id);
$fromPath = Path::clean($client->path . '/templates/' . $template->element . '/templateDetails.xml');

// Delete new folder if it exists
$toPath = $this->getState('to_path');

if (Folder::exists($toPath)) {
if (!Folder::delete($toPath)) {
$app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_COULD_NOT_WRITE'), 'error');

return false;
}
}
else
{
if (!Folder::create($toPath)) {
$app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_COULD_NOT_WRITE'), 'error');

return false;
}
}

// Copy all files from $fromName template to $newName folder
if (!File::copy($fromPath, $toPath . '/templateDetails.xml')) {
return false;
}

// Check manifest for additional files
$newName = strtolower($this->getState('new_name'));
$template = $this->getTemplate();

// Edit XML file
$xmlFile = $this->getState('to_path') . '/templateDetails.xml';

if (File::exists($xmlFile)) {
$xml = simplexml_load_string(file_get_contents($xmlFile));
unset($xml->languages);
unset($xml->media);
unset($xml->files);
unset($xml->parent);
$files = $xml->addChild('files');
$files->addChild('filename', 'templateDetails.xml');
$xml->name = $newName;
$xml->inheritable = 0;
$files = $xml->addChild('parent', $template->element);

$dom = new \DOMDocument;
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($xml->asXML());

$result = File::write($xmlFile, $dom->saveXML());

if (!$result) {
$app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_COULD_NOT_WRITE'), 'error');

return false;
}
}

return true;
} else {
$app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_INVALID_FROM_NAME'), 'error');

return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -263,10 +263,17 @@ protected function addToolbar()
{
ToolbarHelper::custom('template.extractArchive', 'chevron-down', '', 'COM_TEMPLATES_BUTTON_EXTRACT_ARCHIVE', false);
}
// Add a copy template button
// Add a copy/child template button
elseif ($this->type === 'home')
{
ToolbarHelper::modal('copyModal', 'icon-copy', 'COM_TEMPLATES_BUTTON_COPY_TEMPLATE');
if ($this->template->xmldata->inheritable)
{
ToolbarHelper::modal('childModal', 'icon-copy', 'COM_TEMPLATES_BUTTON_CHILD_TEMPLATE', false);
}
elseif (!isset($this->template->xmldata->parent) || $this->template->xmldata->parent == '')
{
ToolbarHelper::modal('copyModal', 'icon-copy', 'COM_TEMPLATES_BUTTON_COPY_TEMPLATE', false);
}
}
}

11 changes: 6 additions & 5 deletions administrator/components/com_templates/tmpl/template/default.php
Original file line number Diff line number Diff line change
@@ -356,16 +356,17 @@
<?php echo HTMLHelper::_('uitab.endTabSet'); ?>

<?php // Collapse Modal
$taskName = $this->template->xmldata->inheritable ? 'child' : 'copy';
$copyModalData = array(
'selector' => 'copyModal',
'selector' => $taskName . 'Modal',
'params' => array(
'title' => Text::_('COM_TEMPLATES_TEMPLATE_COPY'),
'footer' => $this->loadTemplate('modal_copy_footer')
'title' => Text::_('COM_TEMPLATES_TEMPLATE_' . strtoupper($taskName)),
'footer' => $this->loadTemplate('modal_' . $taskName . '_footer')
),
'body' => $this->loadTemplate('modal_copy_body')
'body' => $this->loadTemplate('modal_' . $taskName . '_body')
);
?>
<form action="<?php echo Route::_('index.php?option=com_templates&task=template.copy&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" method="post" name="adminForm" id="adminForm">
<form action="<?php echo Route::_('index.php?option=com_templates&task=template.' . $taskName . '&id=' . $input->getInt('id') . '&file=' . $this->file); ?>" method="post" name="adminForm" id="adminForm">
<?php echo LayoutHelper::render('libraries.html.bootstrap.modal.main', $copyModalData); ?>
<?php echo HTMLHelper::_('form.token'); ?>
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
/**
* @package Joomla.Administrator
* @subpackage com_templates
*
* @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/

defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<div id="template-manager-copy" class="container-fluid">
<div class="mt-2">
<div class="col-md-12">
<div class="control-group">
<div class="control-label">
<label for="new_name">
<?php echo Text::_('COM_TEMPLATES_TEMPLATE_CHILD_NAME_LABEL'); ?>
</label>
</div>
<div class="controls">
<input class="form-control" type="text" id="new_name" name="new_name" required>
<small class="form-text">
<?php echo Text::_('COM_TEMPLATES_TEMPLATE_CHILD_NAME_DESC'); ?>
</small>
</div>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php
/**
* @package Joomla.Administrator
* @subpackage com_templates
*
* @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/

defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;

?>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><?php echo Text::_('COM_TEMPLATES_TEMPLATE_CLOSE'); ?></button>
<button type="submit" class="btn btn-primary"><?php echo Text::_('COM_TEMPLATES_TEMPLATE_CHILD'); ?></button>
6 changes: 6 additions & 0 deletions administrator/language/en-GB/com_templates.ini
Original file line number Diff line number Diff line change
@@ -7,6 +7,12 @@ COM_TEMPLATES="Templates"
COM_TEMPLATES_ARE_YOU_SURE="Are you sure?"
COM_TEMPLATES_ASSIGNED_1="Assigned to one menu item."
COM_TEMPLATES_ASSIGNED_MORE="Assigned to %d menu items."

COM_TEMPLATES_BUTTON_CHILD_TEMPLATE="Child Template"
COM_TEMPLATES_TEMPLATE_CHILD="Child Template"
COM_TEMPLATES_TEMPLATE_CHILD_NAME_LABEL="Name of the child template"
COM_TEMPLATES_TEMPLATE_CHILD_NAME_DESC="Name of the child template"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets not add a description that is identical to the label please

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That isn't my intention, I'm just adding the keys here and then sort them and probably ping you for the correct text


COM_TEMPLATES_BUTTON_CLOSE_FILE="Close File"
COM_TEMPLATES_BUTTON_COPY_FILE="Copy File"
COM_TEMPLATES_BUTTON_COPY_TEMPLATE="Copy Template"
4 changes: 2 additions & 2 deletions libraries/src/Installer/Installer.php
Original file line number Diff line number Diff line change
@@ -2303,9 +2303,9 @@ public static function parseXMLInstallFile($path)
$data['group'] = (string) $xml->group;

// Child templates specific fields.
if (isset($xml->inheritable) && (string) $xml->inheritable !== '')
if (isset($xml->inheritable))
{
$data['inheritable'] = (boolean) $xml->inheritable;
$data['inheritable'] = (string) $xml->inheritable === '0' ? false : true;
}

if (isset($xml->parent) && (string) $xml->parent !== '')