diff --git a/administrator/components/com_installer/Controller/Downloadkey.php b/administrator/components/com_installer/Controller/Downloadkey.php new file mode 100644 index 0000000000000..77145d5778537 --- /dev/null +++ b/administrator/components/com_installer/Controller/Downloadkey.php @@ -0,0 +1,23 @@ +client_id) + { + $path = JPATH_ADMINISTRATOR; + } + + switch ($extension->type) + { + case 'component': + $path .= '/components/' . $extension->element . '/' . substr($extension->element, 4) . '.xml'; + break; + case 'plugin': + $path .= '/plugins/' . $extension->folder . '/' . $extension->element . '/' . $extension->element . '.xml'; + break; + case 'module': + $path .= '/modules/' . $extension->element . '/' . $extension->element . '.xml'; + break; + case 'template': + $path .= '/templates/' . $extension->element . '/templateDetails.xml'; + break; + case 'library': + $path = JPATH_ADMINISTRATOR . '/manifests/libraries/' . $extension->element . '.xml'; + break; + case 'file': + $path = JPATH_ADMINISTRATOR . '/manifests/files/' . $extension->element . '.xml'; + break; + case 'package': + $path = JPATH_ADMINISTRATOR . '/manifests/packages/' . $extension->element . '.xml'; + } + + return simplexml_load_file($path); + } + + /** + * Get the download key of an extension going through their installation xml + * + * @param object $extension element of an extension + * + * @return array An array with the prefix, suffix and value of the download key + * + * @since __DEPLOY_VERSION__ + */ + public static function getDownloadKey($extension) + { + $installXmlFile = self::getInstallationXML($extension); + + if (!isset($installXmlFile->dlid)) + { + return null; + } + + $prefix = (string) $installXmlFile->dlid['prefix']; + $suffix = (string) $installXmlFile->dlid['suffix']; + $value = substr($extension->extra_query, strlen($prefix)); + + if ($suffix != null) + { + $value = substr($value, 0, -strlen($suffix)); + } + + $downloadKey = array( + 'prefix' => $prefix, + 'suffix' => $suffix, + 'value' => $value + ); + + return $downloadKey; + } } diff --git a/administrator/components/com_installer/Model/Downloadkey.php b/administrator/components/com_installer/Model/Downloadkey.php new file mode 100644 index 0000000000000..38b620a748c56 --- /dev/null +++ b/administrator/components/com_installer/Model/Downloadkey.php @@ -0,0 +1,137 @@ +loadForm('com_installer.downloadkey', 'downloadkey', array('control' => 'jform', 'load_data' => $loadData)); + + if (empty($form)) + { + return false; + } + + return $form; + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since __DEPLOY_VERSION__ + */ + protected function loadFormData() + { + $data = $this->getItem(); + + $this->preprocessData('com_installer.downloadkey', $data); + + return $data; + } + + /** + * Method to get a single record. + * + * @param integer $pk The id of the primary key. + * + * @return \JObject|boolean Object on success, false on failure. + * + * @since __DEPLOY_VERSION__ + */ + public function getItem($pk = null) + { + $item = parent::getItem($pk); + + $db = $this->getDbo(); + $query = $db->getQuery(true) + ->select( + $db->quoteName( + array( + 'e.type', + 's.extra_query', + 'e.element', + 'e.folder', + 'e.client_id' + ) + ) + ) + ->from($db->quoteName('#__update_sites', 's')) + ->innerJoin( + $db->quoteName('#__update_sites_extensions', 'se') . + ' ON ' . $db->quoteName('se.update_site_id') . + ' = ' . $db->quoteName('s.update_site_id') + ) + ->innerJoin( + $db->quoteName('#__extensions', 'e') . + ' ON ' . $db->quoteName('e.extension_id') . + ' = ' . $db->quoteName('se.extension_id') + ) + ->where($db->quoteName('s.update_site_id') . ' = ' . $db->quote($item->update_site_id)); + $db->setQuery($query); + $extension = $db->loadObject(); + + $downloadKey = InstallerHelper::getDownloadKey($extension); + + $item->extra_query = $downloadKey['value']; + $item->dlidprefix = $downloadKey['prefix']; + $item->dlidsuffix = $downloadKey['suffix']; + + return $item; + } + + /** + * Method to save the form data. + * + * @param array $data The form data. + * + * @return boolean True on success, False on error. + * + * @since __DEPLOY_VERSION__ + */ + public function save($data) + { + $data['extra_query'] = $data['dlidprefix'] . $data['extra_query'] . $data['dlidsuffix']; + + return parent::save($data); + } +} diff --git a/administrator/components/com_installer/Model/Downloadkeys.php b/administrator/components/com_installer/Model/Downloadkeys.php new file mode 100644 index 0000000000000..78576b055532c --- /dev/null +++ b/administrator/components/com_installer/Model/Downloadkeys.php @@ -0,0 +1,174 @@ +setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string')); + $this->setState('filter.client_id', $this->getUserStateFromRequest($this->context . '.filter.client_id', 'filter_client_id', null, 'int')); + $this->setState('filter.enabled', $this->getUserStateFromRequest($this->context . '.filter.enabled', 'filter_enabled', '', 'string')); + $this->setState('filter.type', $this->getUserStateFromRequest($this->context . '.filter.type', 'filter_type', '', 'string')); + $this->setState('filter.folder', $this->getUserStateFromRequest($this->context . '.filter.folder', 'filter_folder', '', 'string')); + + parent::populateState($ordering, $direction); + } + + /** + * Method to get an array of data items. + * + * @return mixed An array of data items on success, false on failure. + * + * @since __DEPLOY_VERSION__ + */ + public function getItems() + { + $items = parent::getItems(); + + foreach ($items as $item) + { + $item->extra_query = InstallerHelper::getDownloadKey($item); + } + + return $items; + } + + /** + * Method to get the database query + * + * @return \JDatabaseQuery The database query + * + * @since __DEPLOY_VERSION__ + */ + protected function getListQuery() + { + $db = $this->getDbo(); + + $query = $db->getQuery(true) + ->select( + array( + 's.update_site_id', + 's.name AS update_site_name', + 's.type AS update_site_type', + 's.extra_query AS extra_query', + 's.location', + 'e.extension_id', + 'e.name', + 'e.type', + 'e.element', + 'e.folder', + 'e.client_id', + 'e.manifest_cache', + ) + ) + ->from($db->quoteName('#__update_sites', 's')) + ->innerJoin( + $db->quoteName('#__update_sites_extensions', 'se') . + ' ON ' . $db->quoteName('se.update_site_id') . + ' = ' . $db->quoteName('s.update_site_id') + ) + ->innerJoin( + $db->quoteName('#__extensions', 'e') . + ' ON ' . $db->quoteName('e.extension_id') . + ' = ' . $db->quoteName('se.extension_id') + ) + ->where('location not like \'%.joomla.org/%\''); + + // Process select filters. + $enabled = $this->getState('filter.enabled'); + $type = $this->getState('filter.type'); + $clientId = $this->getState('filter.client_id'); + $folder = $this->getState('filter.folder'); + + if ($enabled != '') + { + $query->where($db->quoteName('s.enabled') . ' = ' . $db->quote((int) $enabled)); + } + + if ($type) + { + $query->where($db->quoteName('e.type') . ' = ' . $db->quote($type)); + } + + if ($clientId != '') + { + $query->where($db->quoteName('e.client_id') . ' = ' . $db->quote((int) $clientId)); + } + + if ($folder != '' && in_array($type, array('plugin', 'library', ''))) + { + $query->where($db->quoteName('e.folder') . ' = ' . $db->quote($folder == '*' ? '' : $folder)); + } + + // Process search filter (update site id). + $search = $this->getState('filter.search'); + + if (!empty($search) && stripos($search, 'id:') === 0) + { + $query->where($db->quoteName('s.update_site_id') . ' = ' . $db->quote((int) substr($search, 3))); + } + + // Note: The search for name, ordering and pagination are processed by the parent InstallerModel class (in extension.php). + + return $query; + } +} diff --git a/administrator/components/com_installer/Table/Downloadkey.php b/administrator/components/com_installer/Table/Downloadkey.php new file mode 100644 index 0000000000000..1db57e303f40c --- /dev/null +++ b/administrator/components/com_installer/Table/Downloadkey.php @@ -0,0 +1,67 @@ +typeAlias = 'com_installer.downloadkey'; + + parent::__construct('#__update_sites', 'update_site_id', $db); + } + + /** + * Overloaded check function + * + * @return boolean True on success, false on failure + * + * @see \JTable::check + * @since __DEPLOY_VERSION__ + */ + public function check() + { + try + { + parent::check(); + } + catch (\Exception $e) + { + $this->setError($e->getMessage()); + + return false; + } + + // Check for valid name + if (trim($this->location) == '') + { + $this->setError(\JText::_('COM_INSTALLER_UPDATESITE_EDIT_VALID_NAME')); + + return false; + } + + return true; + } +} diff --git a/administrator/components/com_installer/View/Downloadkey/Html.php b/administrator/components/com_installer/View/Downloadkey/Html.php new file mode 100644 index 0000000000000..538a19ab8e975 --- /dev/null +++ b/administrator/components/com_installer/View/Downloadkey/Html.php @@ -0,0 +1,119 @@ +form = $this->get('Form'); + $this->item = $this->get('Item'); + + $jinput = \JFactory::getApplication()->input; + $this->modal = $jinput->getString('tmpl', ''); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new \JViewGenericdataexception(implode("\n", $errors), 500); + } + + $this->addToolbar(); + + return parent::display($tpl); + } + + /** + * Add the page title and toolbar. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + protected function addToolbar() + { + \JFactory::getApplication()->input->set('hidemainmenu', true); + + $user = \JFactory::getUser(); + $userId = $user->id; + $checkedOut = !($this->item->checked_out == 0 || $this->item->checked_out == $userId); + + $canDo = \JHelperContent::getActions('com_installer', 'downloadkey'); + + \JToolbarHelper::title(\JText::_('COM_INSTALLER_DOWNLOADKEY_EDIT_TITLE'), 'bookmark downloadkeys'); + + $toolbarButtons = []; + + // If not checked out, can save the item. + if (!$checkedOut && ($canDo->get('core.edit'))) + { + $toolbarButtons[] = ['apply', 'downloadkey.apply']; + $toolbarButtons[] = ['save', 'downloadkey.save']; + } + + \JToolbarHelper::saveGroup( + $toolbarButtons, + 'btn-success' + ); + + if (empty($this->item->id)) + { + \JToolbarHelper::cancel('downloadkey.cancel'); + } + else + { + if (\JComponentHelper::isEnabled('com_contenthistory') && $this->state->params->get('save_history', 0) && $canDo->get('core.edit')) + { + \JToolbarHelper::versions('com_installers.downloadkey', $this->item->id); + } + + \JToolbarHelper::cancel('banner.cancel', 'JTOOLBAR_CLOSE'); + } + + \JToolbarHelper::divider(); + \JToolbarHelper::help('JHELP_COMPONENTS_BANNERS_BANNERS_EDIT'); + } +} diff --git a/administrator/components/com_installer/View/Downloadkeys/Html.php b/administrator/components/com_installer/View/Downloadkeys/Html.php new file mode 100644 index 0000000000000..1d69ec35d7495 --- /dev/null +++ b/administrator/components/com_installer/View/Downloadkeys/Html.php @@ -0,0 +1,92 @@ +items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->filterForm = $this->get('FilterForm'); + $this->activeFilters = $this->get('ActiveFilters'); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new \JViewGenericdataexception(implode("\n", $errors), 500); + } + + // Include the component HTML helpers. + \JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html'); + + // Display the view + parent::display($tpl); + } + /** + * Add the page title and toolbar. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + protected function addToolbar() + { + $canDo = ContentHelper::getActions('com_installer'); + + if ($canDo->get('core.admin')) + { + ToolbarHelper::editList('downloadkey.edit'); + ToolbarHelper::divider(); + } + + \JHtmlSidebar::setAction('index.php?option=com_installer&view=downloadkey'); + parent::addToolbar(); + ToolbarHelper::help('JHELP_EXTENSIONS_EXTENSION_MANAGER_UPDATESITES'); + } +} diff --git a/administrator/components/com_installer/access.xml b/administrator/components/com_installer/access.xml index 1c90bfc488ca8..3065cd0a159c7 100644 --- a/administrator/components/com_installer/access.xml +++ b/administrator/components/com_installer/access.xml @@ -1,6 +1,7 @@
+ diff --git a/administrator/components/com_installer/forms/downloadkey.xml b/administrator/components/com_installer/forms/downloadkey.xml new file mode 100644 index 0000000000000..2490b4f280ded --- /dev/null +++ b/administrator/components/com_installer/forms/downloadkey.xml @@ -0,0 +1,38 @@ + +
+
+ + + + + + +
+
\ No newline at end of file diff --git a/administrator/components/com_installer/forms/filter_downloadkeys.xml b/administrator/components/com_installer/forms/filter_downloadkeys.xml new file mode 100644 index 0000000000000..9eab855660e99 --- /dev/null +++ b/administrator/components/com_installer/forms/filter_downloadkeys.xml @@ -0,0 +1,78 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/administrator/components/com_installer/tmpl/downloadkey/default.xml b/administrator/components/com_installer/tmpl/downloadkey/default.xml new file mode 100644 index 0000000000000..6dd7fb6ab203d --- /dev/null +++ b/administrator/components/com_installer/tmpl/downloadkey/default.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/administrator/components/com_installer/tmpl/downloadkey/edit.php b/administrator/components/com_installer/tmpl/downloadkey/edit.php new file mode 100644 index 0000000000000..c131f68831b5e --- /dev/null +++ b/administrator/components/com_installer/tmpl/downloadkey/edit.php @@ -0,0 +1,42 @@ +modal != null) +{ + $tmp = "&tmpl=" . $this->modal; +} + +?> +
+
+
+ +
+
+ form->getFieldset() as $field) : ?> +
+
label; ?>
+
input; ?>
+
+ +
+
+
+
+ + +
diff --git a/administrator/components/com_installer/tmpl/downloadkeys/default.php b/administrator/components/com_installer/tmpl/downloadkeys/default.php new file mode 100644 index 0000000000000..9c379bf04fad0 --- /dev/null +++ b/administrator/components/com_installer/tmpl/downloadkeys/default.php @@ -0,0 +1,122 @@ +escape($this->state->get('list.ordering')); +$listDirn = $this->escape($this->state->get('list.direction')); +?> +
+
+
+
+ sidebar; ?> +
+
+
+ $this)); ?> + items)) : ?> +
+ +
+ + + + + + + + + + + + + + + + + + + + + + items as $i => $item) : ?> + extra_query == null) : ?> + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ pagination->getListFooter(); ?> +
+ update_site_id); ?> + + + + + name; ?> + + + client_translated; ?> + + type_translated; ?> + + folder_translated; ?> + + update_site_id; ?> + + extra_query['value'] ? $item->extra_query['value'] : \JText::_('COM_INSTALLER_TYPE_NONAPPLICABLE'); ?> +
+ + + + +
+
+
+
+
diff --git a/administrator/components/com_installer/tmpl/downloadkeys/default.xml b/administrator/components/com_installer/tmpl/downloadkeys/default.xml new file mode 100644 index 0000000000000..6dd7fb6ab203d --- /dev/null +++ b/administrator/components/com_installer/tmpl/downloadkeys/default.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/administrator/components/com_modules/View/Module/Html.php b/administrator/components/com_modules/View/Module/Html.php index 5950fcf0e1b1a..d759c93836274 100644 --- a/administrator/components/com_modules/View/Module/Html.php +++ b/administrator/components/com_modules/View/Module/Html.php @@ -157,5 +157,10 @@ protected function addToolbar() } \JToolbarHelper::help($help->key, false, $url); + + if (isset($this->item->xml->dlid)) + { + \JToolbarHelper::downloadkey('JGLOBAL_DOWNLOAD_KEY_MODAL_BUTTON', null, $this->item->module); + } } } diff --git a/administrator/components/com_plugins/View/Plugin/Html.php b/administrator/components/com_plugins/View/Plugin/Html.php index 74ba3a7eb9fbb..fd45a4e13e358 100644 --- a/administrator/components/com_plugins/View/Plugin/Html.php +++ b/administrator/components/com_plugins/View/Plugin/Html.php @@ -111,5 +111,10 @@ protected function addToolbar() } \JToolbarHelper::help($help->key, false, $url); + + if (isset($this->item->xml->dlid)) + { + \JToolbarHelper::downloadkey('JGLOBAL_DOWNLOAD_KEY_MODAL_BUTTON', $this->item->extension_id); + } } } diff --git a/administrator/language/en-GB/en-GB.com_installer.ini b/administrator/language/en-GB/en-GB.com_installer.ini index 707bb2cc6ff0e..d1b1a89e0cf84 100644 --- a/administrator/language/en-GB/en-GB.com_installer.ini +++ b/administrator/language/en-GB/en-GB.com_installer.ini @@ -11,6 +11,13 @@ COM_INSTALLER_CONFIRM_UNINSTALL="Are you sure you want to uninstall? Confirming COM_INSTALLER_CURRENT_VERSION="Installed" COM_INSTALLER_DISCOVER_FILTER_SEARCH_DESC="Search in discovered extension name. Prefix with ID: to search for an extension ID." COM_INSTALLER_DISCOVER_FILTER_SEARCH_LABEL="Search Discovered Extensions" +COM_INSTALLER_DOWNLOADKEY_EDIT_DETAILS="Edit Download Key" +COM_INSTALLER_DOWNLOADKEY_EDIT_EXTRA_QUERY="Download ID" +COM_INSTALLER_DOWNLOADKEY_EDIT_TITLE="Download Key" +COM_INSTALLER_DOWNLOADKEY_EXTRA_QUERY_LABEL="Download Key" +COM_INSTALLER_DOWNLOADKEY_EXTRA_QUERY_DESCRIPTION="Add your Download key." +COM_INSTALLER_DOWNLOADKEY_NAME_LABEL="Name" +COM_INSTALLER_DOWNLOADKEY_TYPE_LABEL="Type" COM_INSTALLER_ENABLED_UPDATES_1=", 1 disabled site was enabled." COM_INSTALLER_ENABLED_UPDATES_MORE=", %s disabled sites were enabled." COM_INSTALLER_ERROR_DISABLE_DEFAULT_TEMPLATE_NOT_PERMITTED="Disable default template is not permitted." @@ -34,10 +41,12 @@ COM_INSTALLER_HEADER_LANGUAGES="Extensions: Install Languages" COM_INSTALLER_HEADER_MANAGE="Extensions: Manage" COM_INSTALLER_HEADER_UPDATE="Extensions: Update" COM_INSTALLER_HEADER_UPDATESITES="Extensions: Update Sites" +COM_INSTALLER_HEADER_DOWNLOADKEYS="Extensions: Download Keys" COM_INSTALLER_HEADER_WARNINGS="Extensions: Warnings" COM_INSTALLER_HEADING_CLIENT="Client" COM_INSTALLER_HEADING_DETAILS_URL="Details URL" COM_INSTALLER_HEADING_DETAILSURL="URL Details" +COM_INSTALLER_HEADING_DOWNLOADKEY="Download Key" COM_INSTALLER_HEADING_FOLDER="Folder" COM_INSTALLER_HEADING_FOLDER_ASC="Folder ascending" COM_INSTALLER_HEADING_FOLDER_DESC="Folder descending" @@ -204,6 +213,7 @@ COM_INSTALLER_SUBMENU_LANGUAGES="Install Languages" COM_INSTALLER_SUBMENU_MANAGE="Manage" COM_INSTALLER_SUBMENU_UPDATE="Update" COM_INSTALLER_SUBMENU_UPDATESITES="Update Sites" +COM_INSTALLER_SUBMENU_DOWNLOADKEYS="Download Keys" COM_INSTALLER_SUBMENU_WARNINGS="Warnings" COM_INSTALLER_TITLE_DATABASE="Extensions: Database" COM_INSTALLER_TITLE_DISCOVER="Extensions: Discover" diff --git a/administrator/language/en-GB/en-GB.ini b/administrator/language/en-GB/en-GB.ini index b58992f69f389..28064108da86b 100644 --- a/administrator/language/en-GB/en-GB.ini +++ b/administrator/language/en-GB/en-GB.ini @@ -337,6 +337,8 @@ JGLOBAL_DISPLAY_NUM="Display #" JGLOBAL_DISPLAY_SELECT_DESC="Show or hide the Display Select dropdown listbox." JGLOBAL_DISPLAY_SELECT_LABEL="Display Select" JGLOBAL_DOWN="Down" +JGLOBAL_DOWNLOAD_KEY_MODAL_BUTTON="Download Key" +JGLOBAL_DOWNLOAD_KEY_MODAL_TITLE="Download Key Modal" JGLOBAL_EDIT_ITEM="Edit item" JGLOBAL_EDIT_PREFERENCES="Edit Preferences" JGLOBAL_EMAIL="Email" diff --git a/administrator/language/en-GB/en-GB.mod_menu.ini b/administrator/language/en-GB/en-GB.mod_menu.ini index 96eb035d9e303..2911135a3ea66 100644 --- a/administrator/language/en-GB/en-GB.mod_menu.ini +++ b/administrator/language/en-GB/en-GB.mod_menu.ini @@ -78,6 +78,7 @@ MOD_MENU_INSTALLER_SUBMENU_LANGUAGES="Install Languages" MOD_MENU_INSTALLER_SUBMENU_MANAGE="Manage" MOD_MENU_INSTALLER_SUBMENU_UPDATE="Update" MOD_MENU_INSTALLER_SUBMENU_UPDATESITES="Update Sites" +MOD_MENU_INSTALLER_SUBMENU_DOWNLOADKEYS="Download Keys Manager" MOD_MENU_INSTALLER_SUBMENU_WARNINGS="Warnings" MOD_MENU_LOGOUT="Logout" MOD_MENU_MASS_MAIL_USERS="Mass Mail Users" diff --git a/libraries/src/Toolbar/ToolbarHelper.php b/libraries/src/Toolbar/ToolbarHelper.php index f4fa5c4160894..dfed0d23edf4e 100644 --- a/libraries/src/Toolbar/ToolbarHelper.php +++ b/libraries/src/Toolbar/ToolbarHelper.php @@ -716,4 +716,75 @@ public static function modal($targetModalId, $icon, $alt) $bar = Toolbar::getInstance('toolbar'); $bar->appendButton('Custom', $dhtml, $alt); } + + /** + * Displays a modal button for the extensions that have a download key + * + * @param string $alt Title for the modal button. + * @param string $extensionId Id of the extension. + * @param string $module Id of the module. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public static function downloadkey($alt, $extensionId, $module = null) + { + $db = \JFactory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName('s.update_site_id')) + ->from($db->quoteName('#__update_sites', 's')) + ->innerJoin( + $db->quoteName('#__update_sites_extensions', 'se') . + ' ON ' . $db->quoteName('se.update_site_id') . + ' = ' . $db->quoteName('s.update_site_id') + ) + ->innerJoin( + $db->quoteName('#__extensions', 'e') . + ' ON ' . $db->quoteName('e.extension_id') . + ' = ' . $db->quoteName('se.extension_id') + ); + + if ($module == null) + { + $query->where($db->quoteName('e.extension_id') . ' = ' . $db->quote($extensionId)); + } + else + { + $query->where($db->quoteName('e.element') . ' = ' . $db->quote($module)); + } + + $db->setQuery($query); + + $updateSiteId = $db->loadResult(); + + $title = \JText::_($alt); + + \JHtml::_('script', 'system/fields/modal-fields.min.js', array('version' => 'auto', 'relative' => true)); + + $dhtml = ''; + + $dhtml .= \JHtml::_( + 'bootstrap.renderModal', + 'download_key_modal', + array( + 'title' => \JText::_('JGLOBAL_DOWNLOAD_KEY_MODAL_TITLE'), + 'bodyHeight' => '45', + 'modalWidth' => '80', + 'footer' => '' + . '', + ), + '' + ); + + $bar = Toolbar::getInstance('toolbar'); + $bar->appendButton('Custom', $dhtml, $alt); + } }