diff --git a/administrator/components/com_admin/sql/updates/mysql/4.0.0-2017-06-03.sql b/administrator/components/com_admin/sql/updates/mysql/4.0.0-2017-06-03.sql new file mode 100644 index 0000000000000..2166de7eb35be --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/4.0.0-2017-06-03.sql @@ -0,0 +1,2 @@ +ALTER TABLE `#__extensions` ADD COLUMN `changelogurl` text AFTER `element`; +ALTER TABLE `#__updates` ADD COLUMN `changelogurl` text AFTER `infourl`; diff --git a/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2017-06-03.sql b/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2017-06-03.sql new file mode 100644 index 0000000000000..018cb0b5b749a --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2017-06-03.sql @@ -0,0 +1,2 @@ +ALTER TABLE "#__extensions" ADD COLUMN "changelogurl" text; +ALTER TABLE "#__updates" ADD COLUMN "changelogurl" text; diff --git a/administrator/components/com_installer/Controller/ManageController.php b/administrator/components/com_installer/Controller/ManageController.php index 3bdd126053cd0..2fdb1e74241a9 100644 --- a/administrator/components/com_installer/Controller/ManageController.php +++ b/administrator/components/com_installer/Controller/ManageController.php @@ -11,11 +11,14 @@ defined('_JEXEC') or die; +use Joomla\CMS\Application\CMSApplication; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\BaseController; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; +use Joomla\CMS\Response\JsonResponse; use Joomla\CMS\Router\Route; use Joomla\CMS\Session\Session; +use Joomla\Component\Installer\Administrator\Model\ManageModel; use Joomla\Utilities\ArrayHelper; /** @@ -49,6 +52,8 @@ public function __construct($config = array(), MVCFactoryInterface $factory = nu * * @return void * + * @throws \Exception + * * @since 1.6 */ public function publish() @@ -67,7 +72,7 @@ public function publish() } else { - /* @var \Joomla\Component\Installer\Administrator\Model\ManageModel $model */ + /** @var ManageModel $model */ $model = $this->getModel('manage'); // Change the state of the records. @@ -98,6 +103,8 @@ public function publish() * * @return void * + * @throws \Exception + * * @since 1.5 */ public function remove() @@ -105,7 +112,7 @@ public function remove() // Check for request forgeries. Session::checkToken() or jexit(Text::_('JINVALID_TOKEN')); - /* @var \Joomla\Component\Installer\Administrator\Model\ManageModel $model */ + /** @var ManageModel $model */ $model = $this->getModel('manage'); $eid = $this->input->get('cid', array(), 'array'); @@ -128,7 +135,7 @@ public function refresh() // Check for request forgeries. Session::checkToken() or jexit(Text::_('JINVALID_TOKEN')); - /* @var \Joomla\Component\Installer\Administrator\Model\ManageModel $model */ + /** @var ManageModel $model */ $model = $this->getModel('manage'); $uid = $this->input->get('cid', array(), 'array'); @@ -136,4 +143,29 @@ public function refresh() $model->refresh($uid); $this->setRedirect(Route::_('index.php?option=com_installer&view=manage', false)); } + + /** + * Load the changelog for a given extension. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function loadChangelog() + { + /** @var ManageModel $model */ + $model = $this->getModel('manage'); + + $eid = $this->input->get('eid', 0, 'int'); + $source = $this->input->get('source', 'manage', 'string'); + + if (!$eid) + { + return; + } + + $output = $model->loadChangelog($eid, $source); + + echo (new JsonResponse($output)); + } } diff --git a/administrator/components/com_installer/Model/ManageModel.php b/administrator/components/com_installer/Model/ManageModel.php index 411e9fe215601..25e32ddce3f09 100644 --- a/administrator/components/com_installer/Model/ManageModel.php +++ b/administrator/components/com_installer/Model/ManageModel.php @@ -11,11 +11,14 @@ defined('_JEXEC') or die; +use Joomla\CMS\Changelog\Changelog; use Joomla\CMS\Extension\ExtensionHelper; use Joomla\CMS\Factory; use Joomla\CMS\Installer\Installer; use Joomla\CMS\Language\Text; +use Joomla\CMS\Layout\FileLayout; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; +use Joomla\CMS\Table\Extension; use Joomla\Component\Templates\Administrator\Table\StyleTable; use Joomla\Database\DatabaseQuery; @@ -64,6 +67,8 @@ public function __construct($config = array(), MVCFactoryInterface $factory = nu * * @return void * + * @throws \Exception + * * @since 1.6 */ protected function populateState($ordering = 'name', $direction = 'asc') @@ -94,6 +99,8 @@ protected function populateState($ordering = 'name', $direction = 'asc') * * @return boolean True on success * + * @throws \Exception + * * @since 1.5 */ public function publish(&$eid = array(), $value = 1) @@ -117,7 +124,7 @@ public function publish(&$eid = array(), $value = 1) } // Get a table object for the extension type - $table = new \Joomla\CMS\Table\Extension($this->getDbo()); + $table = new Extension($this->getDbo()); // Enable the extension in the table and store it in the database foreach ($eid as $i => $id) @@ -182,7 +189,7 @@ public function refresh($eid) // Get an installer object for the extension type $installer = Installer::getInstance(); - $result = 0; + $result = 0; // Uninstall the chosen extensions foreach ($eid as $id) @@ -200,6 +207,8 @@ public function refresh($eid) * * @return boolean True on success * + * @throws \Exception + * * @since 1.5 */ public function remove($eid = array()) @@ -222,10 +231,10 @@ public function remove($eid = array()) // Get an installer object for the extension type $installer = Installer::getInstance(); - $row = new \Joomla\CMS\Table\Extension($this->getDbo()); + $row = new \Joomla\CMS\Table\Extension($this->getDbo()); // Uninstall the chosen extensions - $msgs = array(); + $msgs = array(); $result = false; foreach ($eid as $id) @@ -235,7 +244,7 @@ public function remove($eid = array()) $result = false; $langstring = 'COM_INSTALLER_TYPE_TYPE_' . strtoupper($row->type); - $rowtype = Text::_($langstring); + $rowtype = Text::_($langstring); if (strpos($rowtype, $langstring) !== false) { @@ -376,4 +385,79 @@ protected function getListQuery() return $query; } + + /** + * Load the changelog details for a given extension. + * + * @param integer $eid The extension ID + * @param string $source The view the changelog is for, this is used to determine which version number to show + * + * @return string The output to show in the modal. + * + * @since __DEPLOY_VERSION__ + */ + public function loadChangelog($eid, $source) + { + // Get the changelog URL + $db = $this->getDbo(); + $query = $db->getQuery(true) + ->select( + $db->quoteName( + array( + 'extensions.element', + 'extensions.type', + 'extensions.changelogurl', + 'extensions.manifest_cache', + 'extensions.client_id' + ) + ) + ) + ->select($db->quoteName('updates.version', 'updateVersion')) + ->from($db->quoteName('#__extensions', 'extensions')) + ->leftJoin( + $db->quoteName('#__updates', 'updates') + . ' ON ' . $db->quoteName('updates.extension_id') . ' = ' . $db->quoteName('extensions.extension_id') + ) + ->where($db->quoteName('extensions.extension_id') . ' = ' . (int) $eid); + $db->setQuery($query); + + $extensions = $db->loadObjectList(); + $this->translate($extensions); + $extension = array_shift($extensions); + + if (!$extension->changelogurl) + { + return ''; + } + + $changelog = new Changelog; + $changelog->setVersion($source === 'manage' ? $extension->version : $extension->updateVersion); + $changelog->loadFromXml($extension->changelogurl); + + // Read all the entries + $entries = array( + 'security' => array(), + 'fix' => array(), + 'addition' => array(), + 'change' => array(), + 'remove' => array(), + 'language' => array(), + 'note' => array() + ); + + array_walk( + $entries, + function (&$value, $name) use ($changelog) { + if ($field = $changelog->get($name)) + { + $value = $changelog->get($name)->data; + } + } + ); + + $layout = new FileLayout('joomla.installer.changelog'); + $output = $layout->render($entries); + + return $output; + } } diff --git a/administrator/components/com_installer/tmpl/manage/default.php b/administrator/components/com_installer/tmpl/manage/default.php index b31e99688a9db..a510f977ae020 100644 --- a/administrator/components/com_installer/tmpl/manage/default.php +++ b/administrator/components/com_installer/tmpl/manage/default.php @@ -104,14 +104,34 @@ type_translated; ?> - version != '' ? $item->version : ' '; ?> + version !== '') : ?> + changelogurl !== null) : ?> + + version?> + + Text::sprintf('COM_INSTALLER_CHANGELOG_TITLE', $item->name, $item->version), + ), + '' + ); + ?> + + version; ?> + + - creationDate != '' ? $item->creationDate : ' '; ?> + creationDate) && $item->creationDate !== '' ? $item->creationDate : ' '; ?> - author != '' ? $item->author : ' '; ?> + author) && $item->author !== '' ? $item->author : ' '; ?> diff --git a/administrator/components/com_installer/tmpl/update/default.php b/administrator/components/com_installer/tmpl/update/default.php index 80ca2014605d3..cd4ca6ddf9966 100644 --- a/administrator/components/com_installer/tmpl/update/default.php +++ b/administrator/components/com_installer/tmpl/update/default.php @@ -27,14 +27,13 @@ showMessage) : ?> loadTemplate('message'); ?> - ftp) : ?> loadTemplate('ftp'); ?> $this)); ?> items)) : ?>
- +
@@ -43,9 +42,9 @@ - @@ -61,8 +60,11 @@ - + + diff --git a/administrator/language/en-GB/en-GB.com_installer.ini b/administrator/language/en-GB/en-GB.com_installer.ini index 985575ca48742..acc8a7d45e494 100644 --- a/administrator/language/en-GB/en-GB.com_installer.ini +++ b/administrator/language/en-GB/en-GB.com_installer.ini @@ -6,6 +6,15 @@ COM_INSTALLER="Installer" COM_INSTALLER_AUTHOR_INFORMATION="Author Information" COM_INSTALLER_CACHETIMEOUT_LABEL="Updates Caching (in hours)" +COM_INSTALLER_CHANGELOG="Changelog" +COM_INSTALLER_CHANGELOG_ADDITION="New Features" +COM_INSTALLER_CHANGELOG_CHANGE="Changes" +COM_INSTALLER_CHANGELOG_FIX="Bug Fixes" +COM_INSTALLER_CHANGELOG_LANGUAGE="Language" +COM_INSTALLER_CHANGELOG_NOTE="Notes" +COM_INSTALLER_CHANGELOG_REMOVE="Removed Features" +COM_INSTALLER_CHANGELOG_SECURITY="Security Fixes" +COM_INSTALLER_CHANGELOG_TITLE="Changelog - %s - %s" COM_INSTALLER_CONFIGURATION="Installer: Options" COM_INSTALLER_CONFIRM_UNINSTALL="Are you sure you want to uninstall? Confirming will permanently delete the selected item(s)!" COM_INSTALLER_CURRENT_VERSION="Installed" diff --git a/administrator/templates/atum/scss/blocks/_modals.scss b/administrator/templates/atum/scss/blocks/_modals.scss index c3328431fc862..9477f1fb382b3 100644 --- a/administrator/templates/atum/scss/blocks/_modals.scss +++ b/administrator/templates/atum/scss/blocks/_modals.scss @@ -43,3 +43,59 @@ .contentpane { padding: 15px; } + +// Changelog +.changelog { + text-align: left !important; + + &__item { + display: flex; + border-bottom: 1px solid $table-border-color; + + @include media-breakpoint-down(sm) { + flex-direction: column; + } + } + + &__tag { + flex: 1 0 180px; + max-width: 180px; + padding: 10px 15px; + background: darken($gray-100, 2.5%); + border-right: 1px solid $table-border-color; + text-align: right; + + .badge { + border-radius: .2rem; + + &.badge-jlanguage { + background-color: $white; + } + } + + @include media-breakpoint-down(sm) { + flex: 1 0 auto; + max-width: 100%; + text-align: left; + border-right: 0; + border-bottom: 1px solid $table-border-color; + } + } + + &__list { + padding: 10px 15px; + + ul { + padding-left: 15px; + margin-bottom: 0; + } + + li { + margin-bottom: .15rem; + + &:last-of-type{ + margin-bottom: 0; + } + } + } +} \ No newline at end of file diff --git a/build/media_source/system/js/core.es6.js b/build/media_source/system/js/core.es6.js index d9c41c72d0093..0c344a80745f6 100644 --- a/build/media_source/system/js/core.es6.js +++ b/build/media_source/system/js/core.es6.js @@ -914,6 +914,25 @@ window.Joomla.Modal = window.Joomla.Modal || { return xhr; }; + /** + * Load the changelog data + * + * @param extensionId The extension ID to load the changelog for + * @param view The view the changelog is for, + * this is used to determine which version number to show + * + * @since 4.0.0 + */ + Joomla.loadChangelog = (extensionId, view) => { + Joomla.request({ + url: `index.php?option=com_installer&task=manage.loadChangelog&eid=${extensionId}&source=${view}&format=json`, + onSuccess: (response) => { + const result = JSON.parse(response); + document.querySelectorAll('#changelogModal .modal-body')[0].innerHTML = result.data; + }, + }); + }; + /** * Loads any needed polyfill for web components and async load any web components * diff --git a/installation/sql/mysql/joomla.sql b/installation/sql/mysql/joomla.sql index 218a95e99cd6e..85bc46ceba93e 100644 --- a/installation/sql/mysql/joomla.sql +++ b/installation/sql/mysql/joomla.sql @@ -491,6 +491,7 @@ CREATE TABLE IF NOT EXISTS `#__extensions` ( `name` varchar(100) NOT NULL, `type` varchar(20) NOT NULL, `element` varchar(100) NOT NULL, + `changelogurl` text, `folder` varchar(100) NOT NULL, `client_id` tinyint(3) NOT NULL, `enabled` tinyint(3) NOT NULL DEFAULT 0, @@ -1833,6 +1834,7 @@ CREATE TABLE IF NOT EXISTS `#__updates` ( `data` text NOT NULL, `detailsurl` text NOT NULL, `infourl` text NOT NULL, + `changelogurl` text, `extra_query` varchar(1000) DEFAULT '', PRIMARY KEY (`update_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci COMMENT='Available Updates'; diff --git a/installation/sql/postgresql/joomla.sql b/installation/sql/postgresql/joomla.sql index dada3344af91e..d0ab155e77ce4 100644 --- a/installation/sql/postgresql/joomla.sql +++ b/installation/sql/postgresql/joomla.sql @@ -503,6 +503,7 @@ CREATE TABLE IF NOT EXISTS "#__extensions" ( "name" varchar(100) NOT NULL, "type" varchar(20) NOT NULL, "element" varchar(100) NOT NULL, + "changelogurl" text, "folder" varchar(100) NOT NULL, "client_id" smallint NOT NULL, "enabled" smallint DEFAULT 0 NOT NULL, @@ -1830,6 +1831,7 @@ CREATE TABLE IF NOT EXISTS "#__updates" ( "data" text NOT NULL, "detailsurl" text NOT NULL, "infourl" text NOT NULL, + "changelogurl" text, "extra_query" varchar(1000) DEFAULT '', PRIMARY KEY ("update_id") ); diff --git a/layouts/joomla/installer/changelog.php b/layouts/joomla/installer/changelog.php new file mode 100644 index 0000000000000..67de92f2f152a --- /dev/null +++ b/layouts/joomla/installer/changelog.php @@ -0,0 +1,64 @@ + +
+
+
+ +
+
+
    +
  • ', $items); ?>
  • +
+
+
+
+ ` element + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $element; + + /** + * Update manifest `` element + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $type; + + /** + * Update manifest `` element + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $version; + + /** + * Update manifest `` element + * + * @var array + * @since __DEPLOY_VERSION__ + */ + protected $security = array(); + + /** + * Update manifest `` element + * + * @var array + * @since __DEPLOY_VERSION__ + */ + protected $fix = array(); + + /** + * Update manifest `` element + * + * @var array + * @since __DEPLOY_VERSION__ + */ + protected $language = array(); + + /** + * Update manifest `` element + * + * @var array + * @since __DEPLOY_VERSION__ + */ + protected $addition = array(); + + /** + * Update manifest `` elements + * + * @var array + * @since __DEPLOY_VERSION__ + */ + protected $change = array(); + + /** + * Update manifest `` element + * + * @var array + * @since __DEPLOY_VERSION__ + */ + protected $remove = array(); + + /** + * Update manifest `` element + * + * @var array + * @since __DEPLOY_VERSION__ + */ + protected $note = array(); + + /** + * List of node items + * + * @var array + * @since __DEPLOY_VERSION__ + */ + private $items = array(); + + /** + * Resource handle for the XML Parser + * + * @var resource + * @since __DEPLOY_VERSION__ + */ + protected $xmlParser; + + /** + * Element call stack + * + * @var array + * @since __DEPLOY_VERSION__ + */ + protected $stack = array('base'); + + /** + * Object containing the current update data + * + * @var \stdClass + * @since __DEPLOY_VERSION__ + */ + protected $currentChangelog; + + /** + * The version to match the changelog + * + * @var string + * @since __DEPLOY_VERSION__ + */ + private $matchVersion = ''; + + /** + * Object containing the latest changelog data + * + * @var \stdClass + * @since __DEPLOY_VERSION__ + */ + protected $latest; + + /** + * Gets the reference to the current direct parent + * + * @return object + * + * @since __DEPLOY_VERSION__ + */ + protected function getStackLocation() + { + return implode('->', $this->stack); + } + + /** + * Get the last position in stack count + * + * @return string + * + * @since __DEPLOY_VERSION__ + */ + protected function getLastTag() + { + return $this->stack[count($this->stack) - 1]; + } + + /** + * Set the version to match. + * + * @param string $version The version to match + * + * @return void + * + * @since __DEPLOY_VERSION_ + */ + public function setVersion(string $version) + { + $this->matchVersion = $version; + } + + /** + * XML Start Element callback + * + * @param object $parser Parser object + * @param string $name Name of the tag found + * @param array $attrs Attributes of the tag + * + * @return void + * + * @note This is public because it is called externally + * @since 1.7.0 + */ + public function startElement($parser, $name, $attrs = array()) + { + $this->stack[] = $name; + $tag = $this->getStackLocation(); + + // Reset the data + if (isset($this->$tag)) + { + $this->$tag->data = ''; + } + + switch ($name) + { + default: + $name = strtolower($name); + + if (!isset($this->currentChangelog->$name)) + { + $this->currentChangelog->$name = new \stdClass; + } + + $this->currentChangelog->$name->data = ''; + + foreach ($attrs as $key => $data) + { + $key = strtolower($key); + $this->currentChangelog->$name->$key = $data; + } + break; + } + } + + /** + * Callback for closing the element + * + * @param object $parser Parser object + * @param string $name Name of element that was closed + * + * @return void + * + * @note This is public because it is called externally + * @since 1.7.0 + */ + public function endElement($parser, $name) + { + array_pop($this->stack); + + switch ($name) + { + case 'SECURITY': + case 'FIX': + case 'LANGUAGE': + case 'ADDITION': + case 'CHANGE': + case 'REMOVE': + case 'NOTE': + $name = strtolower($name); + $this->currentChangelog->$name->data = $this->items; + $this->items = array(); + break; + case 'CHANGELOG': + if (version_compare($this->currentChangelog->version->data, $this->matchVersion, '==') === true) + { + $this->latest = $this->currentChangelog; + } + + // No version match, empty it + $this->currentChangelog = new \stdClass; + break; + case 'CHANGELOGS': + // If the latest item is set then we transfer it to where we want to + if (isset($this->latest)) + { + foreach (get_object_vars($this->latest) as $key => $val) + { + $this->$key = $val; + } + + unset($this->latest); + unset($this->currentChangelog); + } + elseif (isset($this->currentChangelog)) + { + // The update might be for an older version of j! + unset($this->currentChangelog); + } + break; + } + } + + /** + * Character Parser Function + * + * @param object $parser Parser object. + * @param object $data The data. + * + * @return void + * + * @note This is public because its called externally. + * @since 1.7.0 + */ + public function characterData($parser, $data) + { + $tag = $this->getLastTag(); + + switch ($tag) + { + case 'ITEM': + $this->items[] = $data; + break; + case 'SECURITY': + case 'FIX': + case 'LANGUAGE': + case 'ADDITION': + case 'CHANGE': + case 'REMOVE': + case 'NOTE': + break; + default: + // Throw the data for this item together + $tag = strtolower($tag); + + if (isset($this->currentChangelog->$tag)) + { + $this->currentChangelog->$tag->data .= $data; + } + break; + } + } + + /** + * Loads an XML file from a URL. + * + * @param string $url The URL. + * + * @return boolean True on success + * + * @since __DEPLOY_VERSION__ + */ + public function loadFromXml($url) + { + $version = new Version; + $httpOption = new Registry; + $httpOption->set('userAgent', $version->getUserAgent('Joomla', true, false)); + + try + { + $http = HttpFactory::getHttp($httpOption); + $response = $http->get($url); + } + catch (RuntimeException $e) + { + $response = null; + } + + if ($response === null || $response->code !== 200) + { + // TODO: Add a 'mark bad' setting here somehow + Log::add(Text::sprintf('JLIB_UPDATER_ERROR_EXTENSION_OPEN_URL', $url), Log::WARNING, 'jerror'); + + return false; + } + + $this->currentChangelog = new \stdClass; + + $this->xmlParser = xml_parser_create(''); + xml_set_object($this->xmlParser, $this); + xml_set_element_handler($this->xmlParser, 'startElement', 'endElement'); + xml_set_character_data_handler($this->xmlParser, 'characterData'); + + if (!xml_parse($this->xmlParser, $response->body)) + { + Log::add( + sprintf( + 'XML error: %s at line %d', xml_error_string(xml_get_error_code($this->xmlParser)), + xml_get_current_line_number($this->xmlParser) + ), + Log::WARNING, 'updater' + ); + + return false; + } + + xml_parser_free($this->xmlParser); + + return true; + } +} diff --git a/libraries/src/Installer/Adapter/ComponentAdapter.php b/libraries/src/Installer/Adapter/ComponentAdapter.php index c5dbdd4c52600..bcdb25ffe4d9b 100644 --- a/libraries/src/Installer/Adapter/ComponentAdapter.php +++ b/libraries/src/Installer/Adapter/ComponentAdapter.php @@ -903,9 +903,10 @@ protected function storeExtension($deleteExisting = false) } // Add or update an entry to the extension table - $this->extension->name = $this->name; - $this->extension->type = 'component'; - $this->extension->element = $this->element; + $this->extension->name = $this->name; + $this->extension->type = 'component'; + $this->extension->element = $this->element; + $this->extension->changelogurl = $this->changelogurl; // If we are told to delete existing extension entries then do so. if ($deleteExisting) @@ -1037,10 +1038,10 @@ protected function _buildAdminMenus($component_id = null) { // Lets find the extension id $query->clear() - ->select('e.extension_id') - ->from('#__extensions AS e') - ->where('e.type = ' . $db->quote('component')) - ->where('e.element = ' . $db->quote($option)); + ->select($db->quoteName('e.extension_id')) + ->from($db->quoteName('#__extensions', 'e')) + ->where($db->quoteName('e.type') . ' = ' . $db->quote('component')) + ->where($db->quoteName('e.element') . ' = ' . $db->quote($option)); $db->setQuery($query); $component_id = $db->loadResult(); @@ -1067,37 +1068,37 @@ protected function _buildAdminMenus($component_id = null) if ($menuElement) { // I have a menu element, use this information - $data['menutype'] = 'main'; - $data['client_id'] = 1; - $data['title'] = (string) trim($menuElement); - $data['alias'] = (string) $menuElement; - $data['link'] = 'index.php?option=' . $option; - $data['type'] = 'component'; - $data['published'] = 1; - $data['parent_id'] = 1; + $data['menutype'] = 'main'; + $data['client_id'] = 1; + $data['title'] = (string) trim($menuElement); + $data['alias'] = (string) $menuElement; + $data['link'] = 'index.php?option=' . $option; + $data['type'] = 'component'; + $data['published'] = 1; + $data['parent_id'] = 1; $data['component_id'] = $component_id; - $data['img'] = ((string) $menuElement->attributes()->img) ?: 'class:component'; - $data['home'] = 0; - $data['path'] = ''; - $data['params'] = ''; + $data['img'] = ((string) $menuElement->attributes()->img) ?: 'class:component'; + $data['home'] = 0; + $data['path'] = ''; + $data['params'] = ''; } else { // No menu element was specified, Let's make a generic menu item - $data = array(); - $data['menutype'] = 'main'; - $data['client_id'] = 1; - $data['title'] = $option; - $data['alias'] = $option; - $data['link'] = 'index.php?option=' . $option; - $data['type'] = 'component'; - $data['published'] = 1; - $data['parent_id'] = 1; + $data = array(); + $data['menutype'] = 'main'; + $data['client_id'] = 1; + $data['title'] = $option; + $data['alias'] = $option; + $data['link'] = 'index.php?option=' . $option; + $data['type'] = 'component'; + $data['published'] = 1; + $data['parent_id'] = 1; $data['component_id'] = $component_id; - $data['img'] = 'class:component'; - $data['home'] = 0; - $data['path'] = ''; - $data['params'] = ''; + $data['img'] = 'class:component'; + $data['home'] = 0; + $data['path'] = ''; + $data['params'] = ''; } // Try to create the menu item in the database @@ -1120,17 +1121,17 @@ protected function _buildAdminMenus($component_id = null) foreach ($this->getManifest()->administration->submenu->menu as $child) { - $data = array(); - $data['menutype'] = 'main'; - $data['client_id'] = 1; - $data['title'] = (string) trim($child); - $data['alias'] = (string) $child; - $data['type'] = 'component'; - $data['published'] = 1; - $data['parent_id'] = $parent_id; + $data = array(); + $data['menutype'] = 'main'; + $data['client_id'] = 1; + $data['title'] = (string) trim($child); + $data['alias'] = (string) $child; + $data['type'] = 'component'; + $data['published'] = 1; + $data['parent_id'] = $parent_id; $data['component_id'] = $component_id; - $data['img'] = ((string) $child->attributes()->img) ?: 'class:component'; - $data['home'] = 0; + $data['img'] = ((string) $child->attributes()->img) ?: 'class:component'; + $data['home'] = 0; // Set the sub menu link if ((string) $child->attributes()->link) @@ -1171,7 +1172,7 @@ protected function _buildAdminMenus($component_id = null) $request[] = 'sub=' . $child->attributes()->sub; } - $qstring = count($request) ? '&' . implode('&', $request) : ''; + $qstring = count($request) ? '&' . implode('&', $request) : ''; $data['link'] = 'index.php?option=' . $option . $qstring; } @@ -1199,6 +1200,8 @@ protected function _buildAdminMenus($component_id = null) * * @return boolean True if successful. * + * @throws \Exception + * * @since 3.1 */ protected function _removeAdminMenus($id) @@ -1210,8 +1213,8 @@ protected function _removeAdminMenus($id) // Get the ids of the menu items $query = $db->getQuery(true) - ->select('id') - ->from('#__menu') + ->select($db->quoteName('id')) + ->from($db->quoteName('#__menu')) ->where($db->quoteName('client_id') . ' = 1') ->where($db->quoteName('menutype') . ' = ' . $db->quote('main')) ->where($db->quoteName('component_id') . ' = :id') @@ -1219,8 +1222,7 @@ protected function _removeAdminMenus($id) $db->setQuery($query); - $ids = $db->loadColumn(); - + $ids = $db->loadColumn(); $result = true; // Check for error @@ -1277,12 +1279,12 @@ protected function _updateMenus($component_id, $clientId = null) // Update all menu items which contain 'index.php?option=com_extension' or 'index.php?option=com_extension&...' // to use the new component id. $query = $db->getQuery(true) - ->update('#__menu') - ->set('component_id = ' . $db->quote($component_id)) - ->where('type = ' . $db->quote('component')) + ->update($db->quoteName('#__menu')) + ->set($db->quoteName('component_id') . ' = ' . $db->quote($component_id)) + ->where($db->quoteName('type') . ' = ' . $db->quote('component')) ->where('(' - . 'link LIKE ' . $db->quote('index.php?option=' . $option) . ' OR ' - . 'link LIKE ' . $db->quote($db->escape('index.php?option=' . $option . '&') . '%', false) + . $db->quoteName('link') . ' LIKE ' . $db->quote('index.php?option=' . $option) . ' OR ' + . $db->quoteName('link') . ' LIKE ' . $db->quote($db->escape('index.php?option=' . $option . '&') . '%', false) . ')'); if (isset($clientId)) @@ -1312,6 +1314,8 @@ protected function _updateMenus($component_id, $clientId = null) * * @return boolean True on success * + * @throws \Exception + * * @since 3.1 */ protected function _rollback_menu($step) @@ -1328,8 +1332,8 @@ protected function _rollback_menu($step) */ public function discover() { - $results = array(); - $site_components = Folder::folders(JPATH_SITE . '/components'); + $results = array(); + $site_components = Folder::folders(JPATH_SITE . '/components'); $admin_components = Folder::folders(JPATH_ADMINISTRATOR . '/components'); $api_components = Folder::folders(JPATH_API . '/components'); @@ -1407,15 +1411,16 @@ public function discover() public function refreshManifestCache() { // Need to find to find where the XML file is since we don't store this normally - $client = ApplicationHelper::getClientInfo($this->parent->extension->client_id); - $short_element = str_replace('com_', '', $this->parent->extension->element); - $manifestPath = $client->path . '/components/' . $this->parent->extension->element . '/' . $short_element . '.xml'; + $client = ApplicationHelper::getClientInfo($this->parent->extension->client_id); + $short_element = str_replace('com_', '', $this->parent->extension->element); + $manifestPath = $client->path . '/components/' . $this->parent->extension->element . '/' . $short_element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); - $manifest_details = Installer::parseXMLInstallFile($this->parent->getPath('manifest')); + $manifest_details = Installer::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); - $this->parent->extension->name = $manifest_details['name']; + $this->parent->extension->name = $manifest_details['name']; + $this->parent->extension->namespace = $manifest_details['namespace']; try { @@ -1436,6 +1441,10 @@ public function refreshManifestCache() * @param integer $parentId The parent menu item ID * * @return boolean|integer Menu item ID on success, false on failure + * + * @throws \Exception + * + * @since 3.1 */ protected function _createAdminMenuItem(array &$data, $parentId) { diff --git a/libraries/src/Installer/Adapter/FileAdapter.php b/libraries/src/Installer/Adapter/FileAdapter.php index e44e2f6c3b302..d079ef300667e 100644 --- a/libraries/src/Installer/Adapter/FileAdapter.php +++ b/libraries/src/Installer/Adapter/FileAdapter.php @@ -410,9 +410,10 @@ protected function storeExtension() else { // Add an entry to the extension table with a whole heap of defaults - $this->extension->name = $this->name; - $this->extension->type = 'file'; - $this->extension->element = $this->element; + $this->extension->name = $this->name; + $this->extension->type = 'file'; + $this->extension->element = $this->element; + $this->extension->changelogurl = $this->changelogurl; // There is no folder for files so leave it blank $this->extension->folder = ''; diff --git a/libraries/src/Installer/Adapter/LanguageAdapter.php b/libraries/src/Installer/Adapter/LanguageAdapter.php index 54de5d32dc7f9..11a19dd2db60c 100644 --- a/libraries/src/Installer/Adapter/LanguageAdapter.php +++ b/libraries/src/Installer/Adapter/LanguageAdapter.php @@ -486,6 +486,7 @@ protected function _install($cname, $basePath, $clientId, &$element) $row->set('name', $this->name); $row->set('type', 'language'); $row->set('element', $this->tag); + $row->set('changelogurl', (string) $this->getManifest()->changelogurl); // There is no folder for languages $row->set('folder', ''); @@ -765,6 +766,7 @@ public function update() $row->set('type', 'language'); $row->set('element', $this->tag); $row->set('manifest_cache', $this->parent->generateManifestCache()); + $row->set('changelogurl', (string) $this->getManifest()->changelogurl); // Clean installed languages cache. Factory::getCache()->clean('com_languages'); @@ -790,8 +792,8 @@ public function update() */ public function discover() { - $results = array(); - $site_languages = Folder::folders(JPATH_SITE . '/language'); + $results = array(); + $site_languages = Folder::folders(JPATH_SITE . '/language'); $admin_languages = Folder::folders(JPATH_ADMINISTRATOR . '/language'); foreach ($site_languages as $language) @@ -844,18 +846,18 @@ public function discover() public function discover_install() { // Need to find to find where the XML file is since we don't store this normally - $client = ApplicationHelper::getClientInfo($this->parent->extension->client_id); - $short_element = $this->parent->extension->element; - $manifestPath = $client->path . '/language/' . $short_element . '/' . $short_element . '.xml'; + $client = ApplicationHelper::getClientInfo($this->parent->extension->client_id); + $short_element = $this->parent->extension->element; + $manifestPath = $client->path . '/language/' . $short_element . '/' . $short_element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $this->parent->setPath('source', $client->path . '/language/' . $short_element); $this->parent->setPath('extension_root', $this->parent->getPath('source')); - $manifest_details = Installer::parseXMLInstallFile($this->parent->getPath('manifest')); + $manifest_details = Installer::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); - $this->parent->extension->state = 0; - $this->parent->extension->name = $manifest_details['name']; - $this->parent->extension->enabled = 1; + $this->parent->extension->state = 0; + $this->parent->extension->name = $manifest_details['name']; + $this->parent->extension->enabled = 1; // @todo remove code: $this->parent->extension->params = $this->parent->getParams(); try @@ -885,23 +887,21 @@ public function discover_install() */ public function refreshManifestCache() { - $client = ApplicationHelper::getClientInfo($this->parent->extension->client_id); - $manifestPath = $client->path . '/language/' . $this->parent->extension->element . '/' . $this->parent->extension->element . '.xml'; + $client = ApplicationHelper::getClientInfo($this->parent->extension->client_id); + $manifestPath = $client->path . '/language/' . $this->parent->extension->element . '/' . $this->parent->extension->element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); - $manifest_details = Installer::parseXMLInstallFile($this->parent->getPath('manifest')); + $manifest_details = Installer::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); - $this->parent->extension->name = $manifest_details['name']; + $this->parent->extension->name = $manifest_details['name']; if ($this->parent->extension->store()) { return true; } - else - { - Log::add(Text::_('JLIB_INSTALLER_ERROR_MOD_REFRESH_MANIFEST_CACHE'), Log::WARNING, 'jerror'); - return false; - } + Log::add(Text::_('JLIB_INSTALLER_ERROR_MOD_REFRESH_MANIFEST_CACHE'), Log::WARNING, 'jerror'); + + return false; } } diff --git a/libraries/src/Installer/Adapter/LibraryAdapter.php b/libraries/src/Installer/Adapter/LibraryAdapter.php index d3a8a062bfa9d..c07240644e705 100644 --- a/libraries/src/Installer/Adapter/LibraryAdapter.php +++ b/libraries/src/Installer/Adapter/LibraryAdapter.php @@ -94,10 +94,10 @@ protected function finaliseInstall() // Clobber any possible pending updates /** @var Update $update */ $update = Table::getInstance('update'); - $uid = $update->find( + $uid = $update->find( array( 'element' => $this->element, - 'type' => $this->type, + 'type' => $this->type, ) ); @@ -109,8 +109,8 @@ protected function finaliseInstall() // Lastly, we will copy the manifest file to its appropriate place. if ($this->route !== 'discover_install') { - $manifest = array(); - $manifest['src'] = $this->parent->getPath('manifest'); + $manifest = array(); + $manifest['src'] = $this->parent->getPath('manifest'); $manifest['dest'] = JPATH_MANIFESTS . '/libraries/' . $this->element . '.xml'; $destFolder = dirname($manifest['dest']); @@ -130,7 +130,7 @@ protected function finaliseInstall() // If there is a manifest script, let's copy it. if ($this->manifest_script) { - $path['src'] = $this->parent->getPath('source') . '/' . $this->manifest_script; + $path['src'] = $this->parent->getPath('source') . '/' . $this->manifest_script; $path['dest'] = $this->parent->getPath('extension_root') . '/' . $this->manifest_script; if ($this->parent->isOverwrite() || !file_exists($path['dest'])) @@ -228,9 +228,9 @@ public function loadLanguage($path = null) $this->parent->setPath('source', JPATH_PLATFORM . '/' . $this->getElement()); } - $extension = 'lib_' . str_replace('/', '_', $this->getElement()); + $extension = 'lib_' . str_replace('/', '_', $this->getElement()); $librarypath = (string) $this->getManifest()->libraryname; - $source = $path ?: JPATH_PLATFORM . '/' . $librarypath; + $source = $path ?: JPATH_PLATFORM . '/' . $librarypath; $this->doLoadLanguage($extension, $source, JPATH_SITE); } @@ -257,7 +257,7 @@ protected function parseOptionalTags() */ public function prepareDiscoverInstall() { - $manifestPath = JPATH_MANIFESTS . '/libraries/' . $this->extension->element . '.xml'; + $manifestPath = JPATH_MANIFESTS . '/libraries/' . $this->extension->element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $this->setManifest($this->parent->getManifest()); @@ -388,10 +388,10 @@ protected function storeExtension() $manifest_details = Installer::parseXMLInstallFile($this->parent->getPath('manifest')); $this->extension->manifest_cache = json_encode($manifest_details); - $this->extension->state = 0; - $this->extension->name = $manifest_details['name']; - $this->extension->enabled = 1; - $this->extension->params = $this->parent->getParams(); + $this->extension->state = 0; + $this->extension->name = $manifest_details['name']; + $this->extension->enabled = 1; + $this->extension->params = $this->parent->getParams(); if (!$this->extension->store()) { @@ -402,9 +402,10 @@ protected function storeExtension() return; } - $this->extension->name = $this->name; - $this->extension->type = 'library'; - $this->extension->element = $this->element; + $this->extension->name = $this->name; + $this->extension->type = 'library'; + $this->extension->element = $this->element; + $this->extension->changelogurl = $this->changelogurl; // There is no folder for libraries $this->extension->folder = ''; @@ -460,8 +461,8 @@ public function update() */ // Set the extensions name - $name = (string) $this->getManifest()->name; - $name = InputFilter::getInstance()->clean($name, 'string'); + $name = (string) $this->getManifest()->name; + $name = InputFilter::getInstance()->clean($name, 'string'); $element = str_replace('.xml', '', basename($this->parent->getPath('manifest'))); $this->name = $name; @@ -469,8 +470,8 @@ public function update() // We don't want to compromise this instance! $installer = new Installer; - $db = $this->parent->getDbo(); - $query = $db->getQuery(true) + $db = $this->parent->getDbo(); + $query = $db->getQuery(true) ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('library')) @@ -487,7 +488,7 @@ public function update() // Clear the cached data $this->currentExtensionId = null; - $this->extension = Table::getInstance('Extension', 'JTable', array('dbo' => $this->db)); + $this->extension = Table::getInstance('Extension', 'JTable', array('dbo' => $this->db)); } // Now create the new files @@ -515,7 +516,7 @@ public function discover() foreach ($iterator as $file => $pattern) { - $element = str_replace(array($mainFolder . DIRECTORY_SEPARATOR, '.xml'), '', $file); + $element = str_replace(array($mainFolder . DIRECTORY_SEPARATOR, '.xml'), '', $file); $manifestCache = Installer::parseXMLInstallFile($file); $extension = Table::getInstance('extension'); @@ -543,13 +544,13 @@ public function discover() public function refreshManifestCache() { // Need to find to find where the XML file is since we don't store this normally - $manifestPath = JPATH_MANIFESTS . '/libraries/' . $this->parent->extension->element . '.xml'; + $manifestPath = JPATH_MANIFESTS . '/libraries/' . $this->parent->extension->element . '.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); - $manifest_details = Installer::parseXMLInstallFile($this->parent->getPath('manifest')); + $manifest_details = Installer::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); - $this->parent->extension->name = $manifest_details['name']; + $this->parent->extension->name = $manifest_details['name']; try { diff --git a/libraries/src/Installer/Adapter/ModuleAdapter.php b/libraries/src/Installer/Adapter/ModuleAdapter.php index eb38d4a123224..925522b534abc 100644 --- a/libraries/src/Installer/Adapter/ModuleAdapter.php +++ b/libraries/src/Installer/Adapter/ModuleAdapter.php @@ -619,10 +619,11 @@ protected function storeExtension() } else { - $this->extension->name = $this->name; - $this->extension->type = 'module'; - $this->extension->element = $this->element; - $this->extension->namespace = (string) $this->manifest->namespace; + $this->extension->name = $this->name; + $this->extension->type = 'module'; + $this->extension->element = $this->element; + $this->extension->namespace = (string) $this->manifest->namespace; + $this->extension->changelogurl = $this->changelogurl; // There is no folder for modules $this->extension->folder = ''; diff --git a/libraries/src/Installer/Adapter/PackageAdapter.php b/libraries/src/Installer/Adapter/PackageAdapter.php index 54efab19324fb..f10fadf7f5b7a 100644 --- a/libraries/src/Installer/Adapter/PackageAdapter.php +++ b/libraries/src/Installer/Adapter/PackageAdapter.php @@ -556,9 +556,10 @@ protected function storeExtension() } else { - $this->extension->name = $this->name; - $this->extension->type = 'package'; - $this->extension->element = $this->element; + $this->extension->name = $this->name; + $this->extension->type = 'package'; + $this->extension->element = $this->element; + $this->extension->changelogurl = $this->changelogurl; // There is no folder for packages $this->extension->folder = ''; diff --git a/libraries/src/Installer/Adapter/PluginAdapter.php b/libraries/src/Installer/Adapter/PluginAdapter.php index a21d0b11400f9..91f11f21a0768 100644 --- a/libraries/src/Installer/Adapter/PluginAdapter.php +++ b/libraries/src/Installer/Adapter/PluginAdapter.php @@ -443,10 +443,10 @@ protected function storeExtension() $manifest_details = Installer::parseXMLInstallFile($this->parent->getPath('manifest')); $this->extension->manifest_cache = json_encode($manifest_details); - $this->extension->state = 0; - $this->extension->name = $manifest_details['name']; - $this->extension->enabled = 'editors' === $this->extension->folder ? 1 : 0; - $this->extension->params = $this->parent->getParams(); + $this->extension->state = 0; + $this->extension->name = $manifest_details['name']; + $this->extension->enabled = 'editors' === $this->extension->folder ? 1 : 0; + $this->extension->params = $this->parent->getParams(); if (!$this->extension->store()) { @@ -482,16 +482,17 @@ protected function storeExtension() else { // Store in the extensions table (1.6) - $this->extension->name = $this->name; - $this->extension->type = 'plugin'; - $this->extension->ordering = 0; - $this->extension->element = $this->element; - $this->extension->folder = $this->group; - $this->extension->enabled = 0; - $this->extension->protected = 0; - $this->extension->access = 1; - $this->extension->client_id = 0; - $this->extension->params = $this->parent->getParams(); + $this->extension->name = $this->name; + $this->extension->type = 'plugin'; + $this->extension->ordering = 0; + $this->extension->element = $this->element; + $this->extension->folder = $this->group; + $this->extension->enabled = 0; + $this->extension->protected = 0; + $this->extension->access = 1; + $this->extension->client_id = 0; + $this->extension->params = $this->parent->getParams(); + $this->extension->changelogurl = $this->changelogurl; // Update the manifest cache for the entry $this->extension->manifest_cache = $this->parent->generateManifestCache(); diff --git a/libraries/src/Installer/Adapter/TemplateAdapter.php b/libraries/src/Installer/Adapter/TemplateAdapter.php index f08d09377f9f4..ae7cf74c2a00c 100644 --- a/libraries/src/Installer/Adapter/TemplateAdapter.php +++ b/libraries/src/Installer/Adapter/TemplateAdapter.php @@ -343,8 +343,8 @@ protected function parseQueries() */ public function prepareDiscoverInstall() { - $client = ApplicationHelper::getClientInfo($this->extension->client_id); - $manifestPath = $client->path . '/templates/' . $this->extension->element . '/templateDetails.xml'; + $client = ApplicationHelper::getClientInfo($this->extension->client_id); + $manifestPath = $client->path . '/templates/' . $this->extension->element . '/templateDetails.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); $this->setManifest($this->parent->getManifest()); @@ -398,13 +398,13 @@ protected function setupInstallPaths() throw new \RuntimeException(Text::sprintf('JLIB_INSTALLER_ABORT_TPL_INSTALL_UNKNOWN_CLIENT', $cname)); } - $basePath = $client->path; + $basePath = $client->path; $this->clientId = $client->id; } else { // No client attribute was found so we assume the site as the client - $basePath = JPATH_SITE; + $basePath = JPATH_SITE; $this->clientId = 0; } @@ -537,12 +537,13 @@ protected function storeExtension() $this->extension->element = $this->element; // There is no folder for templates - $this->extension->folder = ''; - $this->extension->enabled = 1; - $this->extension->protected = 0; - $this->extension->access = 1; - $this->extension->client_id = $this->clientId; - $this->extension->params = $this->parent->getParams(); + $this->extension->folder = ''; + $this->extension->enabled = 1; + $this->extension->protected = 0; + $this->extension->access = 1; + $this->extension->client_id = $this->clientId; + $this->extension->params = $this->parent->getParams(); + $this->extension->changelogurl = $this->changelogurl; } // Name might change in an update @@ -551,6 +552,8 @@ protected function storeExtension() // Update the manifest cache for the entry $this->extension->manifest_cache = $this->parent->generateManifestCache(); + $this->extension->changelogurl = $this->changelogurl; + if (!$this->extension->store()) { // Install failed, roll back changes @@ -571,10 +574,10 @@ protected function storeExtension() */ public function discover() { - $results = array(); - $site_list = Folder::folders(JPATH_SITE . '/templates'); + $results = array(); + $site_list = Folder::folders(JPATH_SITE . '/templates'); $admin_list = Folder::folders(JPATH_ADMINISTRATOR . '/templates'); - $site_info = ApplicationHelper::getClientInfo('site', true); + $site_info = ApplicationHelper::getClientInfo('site', true); $admin_info = ApplicationHelper::getClientInfo('administrator', true); foreach ($site_list as $template) @@ -588,7 +591,7 @@ public function discover() } $manifest_details = Installer::parseXMLInstallFile(JPATH_SITE . "/templates/$template/templateDetails.xml"); - $extension = Table::getInstance('extension'); + $extension = Table::getInstance('extension'); $extension->set('type', 'template'); $extension->set('client_id', $site_info->id); $extension->set('element', $template); @@ -612,7 +615,7 @@ public function discover() } $manifest_details = Installer::parseXMLInstallFile(JPATH_ADMINISTRATOR . "/templates/$template/templateDetails.xml"); - $extension = Table::getInstance('extension'); + $extension = Table::getInstance('extension'); $extension->set('type', 'template'); $extension->set('client_id', $admin_info->id); $extension->set('element', $template); @@ -638,14 +641,14 @@ public function discover() public function refreshManifestCache() { // Need to find to find where the XML file is since we don't store this normally. - $client = ApplicationHelper::getClientInfo($this->parent->extension->client_id); - $manifestPath = $client->path . '/templates/' . $this->parent->extension->element . '/templateDetails.xml'; + $client = ApplicationHelper::getClientInfo($this->parent->extension->client_id); + $manifestPath = $client->path . '/templates/' . $this->parent->extension->element . '/templateDetails.xml'; $this->parent->manifest = $this->parent->isManifest($manifestPath); $this->parent->setPath('manifest', $manifestPath); - $manifest_details = Installer::parseXMLInstallFile($this->parent->getPath('manifest')); + $manifest_details = Installer::parseXMLInstallFile($this->parent->getPath('manifest')); $this->parent->extension->manifest_cache = json_encode($manifest_details); - $this->parent->extension->name = $manifest_details['name']; + $this->parent->extension->name = $manifest_details['name']; try { diff --git a/libraries/src/Installer/InstallerAdapter.php b/libraries/src/Installer/InstallerAdapter.php index f71bb19a57dbb..ecd6725677254 100644 --- a/libraries/src/Installer/InstallerAdapter.php +++ b/libraries/src/Installer/InstallerAdapter.php @@ -28,6 +28,14 @@ */ abstract class InstallerAdapter { + /** + * Changelog URL of extensions + * + * @var string + * @since __DEPLOY_VERSION__ + * */ + protected $changelogurl = null; + /** * ID for the currently installed extension if present * @@ -666,20 +674,18 @@ protected function getScriptClassName() public function install() { // Get the extension's description - $description = (string) $this->getManifest()->description; + $description = (string) $this->getManifest()->description; + $this->parent->message = ''; if ($description) { $this->parent->message = Text::_($description); } - else - { - $this->parent->message = ''; - } // Set the extension's name and element - $this->name = $this->getName(); - $this->element = $this->getElement(); + $this->name = $this->getName(); + $this->element = $this->getElement(); + $this->changelogurl = (string) $this->getManifest()->changelogurl; /* * --------------------------------------------------------------------------------------------- diff --git a/libraries/src/Updater/UpdateAdapter.php b/libraries/src/Updater/UpdateAdapter.php index eabb0c1ec6f23..bd88338d7714c 100644 --- a/libraries/src/Updater/UpdateAdapter.php +++ b/libraries/src/Updater/UpdateAdapter.php @@ -56,7 +56,7 @@ abstract class UpdateAdapter extends \JAdapterInstance * @var array * @since 3.0.0 */ - protected $updatecols = array('NAME', 'ELEMENT', 'TYPE', 'FOLDER', 'CLIENT', 'VERSION', 'DESCRIPTION', 'INFOURL', 'EXTRA_QUERY'); + protected $updatecols = array('NAME', 'ELEMENT', 'TYPE', 'FOLDER', 'CLIENT', 'VERSION', 'DESCRIPTION', 'INFOURL', 'CHANGELOGURL', 'EXTRA_QUERY'); /** * Should we try appending a .xml extension to the update site's URL?
+ - + - + + + + @@ -102,6 +104,28 @@ version; ?> + changelogurl !== null) : ?> + + + + Text::sprintf('COM_INSTALLER_CHANGELOG_TITLE', $item->name, $item->version), + ), + '' + ); + ?> + + + + + + + folder_translated; ?>