primo commit
This commit is contained in:
11
administrator/components/com_installer/access.xml
Normal file
11
administrator/components/com_installer/access.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<access component="com_installer">
|
||||
<section name="component">
|
||||
<action name="core.admin" title="JACTION_ADMIN" />
|
||||
<action name="core.options" title="JACTION_OPTIONS" />
|
||||
<action name="core.manage" title="JACTION_MANAGE" />
|
||||
<action name="core.delete" title="JACTION_DELETE" />
|
||||
<action name="core.edit" title="JACTION_EDIT" />
|
||||
<action name="core.edit.state" title="JACTION_EDITSTATE" />
|
||||
</section>
|
||||
</access>
|
||||
54
administrator/components/com_installer/config.xml
Normal file
54
administrator/components/com_installer/config.xml
Normal file
@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<config>
|
||||
<help key="Installer:_Options"/>
|
||||
<inlinehelp button="show"/>
|
||||
<fieldset
|
||||
name="preferences"
|
||||
label="COM_INSTALLER_PREFERENCES_LABEL"
|
||||
description="COM_INSTALLER_PREFERENCES_DESCRIPTION"
|
||||
>
|
||||
|
||||
<field
|
||||
name="cachetimeout"
|
||||
type="integer"
|
||||
label="COM_INSTALLER_CACHETIMEOUT_LABEL"
|
||||
first="0"
|
||||
last="24"
|
||||
step="1"
|
||||
default="6"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="minimum_stability"
|
||||
type="list"
|
||||
label="COM_INSTALLER_MINIMUM_STABILITY_LABEL"
|
||||
description="COM_INSTALLER_MINIMUM_STABILITY_DESC"
|
||||
default="4"
|
||||
validate="options"
|
||||
>
|
||||
<option value="0">COM_INSTALLER_MINIMUM_STABILITY_DEV</option>
|
||||
<option value="1">COM_INSTALLER_MINIMUM_STABILITY_ALPHA</option>
|
||||
<option value="2">COM_INSTALLER_MINIMUM_STABILITY_BETA</option>
|
||||
<option value="3">COM_INSTALLER_MINIMUM_STABILITY_RC</option>
|
||||
<option value="4">COM_INSTALLER_MINIMUM_STABILITY_STABLE</option>
|
||||
</field>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<fieldset
|
||||
name="permissions"
|
||||
label="JCONFIG_PERMISSIONS_LABEL"
|
||||
>
|
||||
|
||||
<field
|
||||
name="rules"
|
||||
type="rules"
|
||||
label="JCONFIG_PERMISSIONS_LABEL"
|
||||
filter="rules"
|
||||
validate="rules"
|
||||
component="com_installer"
|
||||
section="component"
|
||||
/>
|
||||
|
||||
</fieldset>
|
||||
</config>
|
||||
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form addfieldprefix="Joomla\Component\Installer\Administrator\Field">
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_INSTALLER_MANAGE_FILTER_SEARCH_LABEL"
|
||||
description="COM_INSTALLER_MANAGE_FILTER_SEARCH_DESC"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="client_id"
|
||||
type="location"
|
||||
label="COM_INSTALLER_TYPE_CLIENT"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_CLIENT_SELECT</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="type"
|
||||
type="type"
|
||||
label="COM_INSTALLER_HEADING_TYPE"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_TYPE_SELECT</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="folder"
|
||||
type="folder"
|
||||
label="COM_INSTALLER_HEADING_FOLDER"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_FOLDER_SELECT</option>
|
||||
</field>
|
||||
</fields>
|
||||
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
class="js-select-submit-on-change"
|
||||
default="name ASC"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="name ASC">JGLOBAL_NAME_ASC</option>
|
||||
<option value="name DESC">JGLOBAL_NAME_DESC</option>
|
||||
<option value="client_translated ASC">COM_INSTALLER_HEADING_LOCATION_ASC</option>
|
||||
<option value="client_translated DESC">COM_INSTALLER_HEADING_LOCATION_DESC</option>
|
||||
<option value="type_translated ASC">COM_INSTALLER_HEADING_TYPE_ASC</option>
|
||||
<option value="type_translated DESC">COM_INSTALLER_HEADING_TYPE_DESC</option>
|
||||
<option value="folder_translated ASC">COM_INSTALLER_HEADING_FOLDER_ASC</option>
|
||||
<option value="folder_translated DESC">COM_INSTALLER_HEADING_FOLDER_DESC</option>
|
||||
<option value="extension_id ASC">JGRID_HEADING_ID_ASC</option>
|
||||
<option value="extension_id DESC">JGRID_HEADING_ID_DESC</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="2"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form addfieldprefix="Joomla\Component\Installer\Administrator\Field">
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_INSTALLER_DISCOVER_FILTER_SEARCH_LABEL"
|
||||
description="COM_INSTALLER_DISCOVER_FILTER_SEARCH_DESC"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="client_id"
|
||||
type="location"
|
||||
label="COM_INSTALLER_TYPE_CLIENT"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_CLIENT_SELECT</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="type"
|
||||
type="type"
|
||||
label="COM_INSTALLER_HEADING_TYPE"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_TYPE_SELECT</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="folder"
|
||||
type="folder"
|
||||
label="COM_INSTALLER_HEADING_FOLDER"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_FOLDER_SELECT</option>
|
||||
</field>
|
||||
</fields>
|
||||
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
class="js-select-submit-on-change"
|
||||
default="name ASC"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="name ASC">JGLOBAL_NAME_ASC</option>
|
||||
<option value="name DESC">JGLOBAL_NAME_DESC</option>
|
||||
<option value="client_translated ASC">COM_INSTALLER_HEADING_LOCATION_ASC</option>
|
||||
<option value="client_translated DESC">COM_INSTALLER_HEADING_LOCATION_DESC</option>
|
||||
<option value="type_translated ASC">COM_INSTALLER_HEADING_TYPE_ASC</option>
|
||||
<option value="type_translated DESC">COM_INSTALLER_HEADING_TYPE_DESC</option>
|
||||
<option value="folder_translated ASC">COM_INSTALLER_HEADING_FOLDER_ASC</option>
|
||||
<option value="folder_translated DESC">COM_INSTALLER_HEADING_FOLDER_DESC</option>
|
||||
<option value="extension_id ASC">JGRID_HEADING_ID_ASC</option>
|
||||
<option value="extension_id DESC">JGRID_HEADING_ID_DESC</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_INSTALLER_LANGUAGES_FILTER_SEARCH_LABEL"
|
||||
description="COM_INSTALLER_LANGUAGES_FILTER_SEARCH_DESC"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
</fields>
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
class="js-select-submit-on-change"
|
||||
default="name ASC"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="name ASC">JGRID_HEADING_LANGUAGE_ASC</option>
|
||||
<option value="name DESC">JGRID_HEADING_LANGUAGE_DESC</option>
|
||||
<option value="element ASC">COM_INSTALLER_HEADING_LANGUAGE_TAG_ASC</option>
|
||||
<option value="element DESC">COM_INSTALLER_HEADING_LANGUAGE_TAG_DESC</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
108
administrator/components/com_installer/forms/filter_manage.xml
Normal file
108
administrator/components/com_installer/forms/filter_manage.xml
Normal file
@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form addfieldprefix="Joomla\Component\Installer\Administrator\Field">
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_INSTALLER_MANAGE_FILTER_SEARCH_LABEL"
|
||||
description="COM_INSTALLER_MANAGE_FILTER_SEARCH_DESC"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="status"
|
||||
type="extensionstatus"
|
||||
label="JSTATUS"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_PUBLISHED</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="client_id"
|
||||
type="location"
|
||||
label="COM_INSTALLER_TYPE_CLIENT"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_CLIENT_SELECT</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="type"
|
||||
type="type"
|
||||
label="COM_INSTALLER_HEADING_TYPE"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_TYPE_SELECT</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="folder"
|
||||
type="folder"
|
||||
label="COM_INSTALLER_HEADING_FOLDER"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_FOLDER_SELECT</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="package_id"
|
||||
type="package"
|
||||
label="COM_INSTALLER_MANAGE_FILTER_PACKAGE_ID_LABEL"
|
||||
description="COM_INSTALLER_MANAGE_FILTER_PACKAGE_ID_DESC"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_PACKAGE_ID_SELECT</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="core"
|
||||
type="list"
|
||||
label="COM_INSTALLER_HEADING_TYPE"
|
||||
class="js-select-submit-on-change"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_CORE_SELECT</option>
|
||||
<option value="1">COM_INSTALLER_VALUE_CORE_YES</option>
|
||||
<option value="0">COM_INSTALLER_VALUE_CORE_NO</option>
|
||||
</field>
|
||||
</fields>
|
||||
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
class="js-select-submit-on-change"
|
||||
default="name ASC"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="status ASC">JSTATUS_ASC</option>
|
||||
<option value="status DESC">JSTATUS_DESC</option>
|
||||
<option value="name ASC">JGLOBAL_NAME_ASC</option>
|
||||
<option value="name DESC">JGLOBAL_NAME_DESC</option>
|
||||
<option value="client_translated ASC">COM_INSTALLER_HEADING_LOCATION_ASC</option>
|
||||
<option value="client_translated DESC">COM_INSTALLER_HEADING_LOCATION_DESC</option>
|
||||
<option value="type_translated ASC">COM_INSTALLER_HEADING_TYPE_ASC</option>
|
||||
<option value="type_translated DESC">COM_INSTALLER_HEADING_TYPE_DESC</option>
|
||||
<option value="creationDate ASC">JDATE_ASC</option>
|
||||
<option value="creationDate DESC">JDATE_DESC</option>
|
||||
<option value="folder_translated ASC">COM_INSTALLER_HEADING_FOLDER_ASC</option>
|
||||
<option value="folder_translated DESC">COM_INSTALLER_HEADING_FOLDER_DESC</option>
|
||||
<option value="package_id ASC">COM_INSTALLER_HEADING_PACKAGE_ID_ASC</option>
|
||||
<option value="package_id DESC">COM_INSTALLER_HEADING_PACKAGE_ID_DESC</option>
|
||||
<option value="extension_id ASC">JGRID_HEADING_ID_ASC</option>
|
||||
<option value="extension_id DESC">JGRID_HEADING_ID_DESC</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form addfieldprefix="Joomla\Component\Installer\Administrator\Field">
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_INSTALLER_UPDATE_FILTER_SEARCH_LABEL"
|
||||
description="COM_INSTALLER_UPDATE_FILTER_SEARCH_DESC"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
<field
|
||||
name="client_id"
|
||||
type="location"
|
||||
label="COM_INSTALLER_TYPE_CLIENT"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_CLIENT_SELECT</option>
|
||||
</field>
|
||||
<field
|
||||
name="type"
|
||||
type="type"
|
||||
label="COM_INSTALLER_TYPE_CLIENT"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_TYPE_SELECT</option>
|
||||
</field>
|
||||
<field
|
||||
name="folder"
|
||||
type="folder"
|
||||
label="COM_INSTALLER_HEADING_FOLDER"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_FOLDER_SELECT</option>
|
||||
</field>
|
||||
</fields>
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
class="js-select-submit-on-change"
|
||||
default="u.name ASC"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="u.name ASC">JGLOBAL_NAME_ASC</option>
|
||||
<option value="u.name DESC">JGLOBAL_NAME_DESC</option>
|
||||
<option value="client_translated ASC">COM_INSTALLER_HEADING_LOCATION_ASC</option>
|
||||
<option value="client_translated DESC">COM_INSTALLER_HEADING_LOCATION_DESC</option>
|
||||
<option value="type_translated ASC">COM_INSTALLER_HEADING_TYPE_ASC</option>
|
||||
<option value="type_translated DESC">COM_INSTALLER_HEADING_TYPE_DESC</option>
|
||||
<option value="folder_translated ASC">COM_INSTALLER_HEADING_FOLDER_ASC</option>
|
||||
<option value="folder_translated DESC">COM_INSTALLER_HEADING_FOLDER_DESC</option>
|
||||
</field>
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form addfieldprefix="Joomla\Component\Installer\Administrator\Field">
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_INSTALLER_UPDATESITES_FILTER_SEARCH_LABEL"
|
||||
description="COM_INSTALLER_UPDATESITES_FILTER_SEARCH_DESC"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
<field
|
||||
name="enabled"
|
||||
type="list"
|
||||
label="JSTATUS"
|
||||
class="js-select-submit-on-change"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_PUBLISHED</option>
|
||||
<option value="0">JDISABLED</option>
|
||||
<option value="1">JENABLED</option>
|
||||
</field>
|
||||
<field
|
||||
name="client_id"
|
||||
type="location"
|
||||
label="COM_INSTALLER_TYPE_CLIENT"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_CLIENT_SELECT</option>
|
||||
</field>
|
||||
<field
|
||||
name="type"
|
||||
type="type"
|
||||
label="COM_INSTALLER_HEADING_TYPE"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_TYPE_SELECT</option>
|
||||
</field>
|
||||
<field
|
||||
name="folder"
|
||||
type="folder"
|
||||
label="COM_INSTALLER_HEADING_FOLDER"
|
||||
class="js-select-submit-on-change"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_FOLDER_SELECT</option>
|
||||
</field>
|
||||
<field
|
||||
name="supported"
|
||||
type="list"
|
||||
label="COM_INSTALLER_HEADING_SUPPORTED"
|
||||
class="js-select-submit-on-change"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">COM_INSTALLER_VALUE_SUPPORTED_SELECT</option>
|
||||
<option value="1">COM_INSTALLER_VALUE_SUPPORTED_SUPPORTED</option>
|
||||
<option value="-1">COM_INSTALLER_VALUE_SUPPORTED_MISSING</option>
|
||||
<option value="2">COM_INSTALLER_VALUE_SUPPORTED_EXISTS</option>
|
||||
</field>
|
||||
|
||||
</fields>
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
class="js-select-submit-on-change"
|
||||
default="name ASC"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="enabled ASC">JSTATUS_ASC</option>
|
||||
<option value="enabled DESC">JSTATUS_DESC</option>
|
||||
<option value="update_site_name ASC">COM_INSTALLER_HEADING_UPDATESITE_NAME_ASC</option>
|
||||
<option value="update_site_name DESC">COM_INSTALLER_HEADING_UPDATESITE_NAME_DESC</option>
|
||||
<option value="name ASC">JGLOBAL_NAME_ASC</option>
|
||||
<option value="name DESC">JGLOBAL_NAME_DESC</option>
|
||||
<option value="client_translated ASC">COM_INSTALLER_HEADING_LOCATION_ASC</option>
|
||||
<option value="client_translated DESC">COM_INSTALLER_HEADING_LOCATION_DESC</option>
|
||||
<option value="type_translated ASC">COM_INSTALLER_HEADING_TYPE_ASC</option>
|
||||
<option value="type_translated DESC">COM_INSTALLER_HEADING_TYPE_DESC</option>
|
||||
<option value="folder_translated ASC">COM_INSTALLER_HEADING_FOLDER_ASC</option>
|
||||
<option value="folder_translated DESC">COM_INSTALLER_HEADING_FOLDER_DESC</option>
|
||||
<option value="update_site_id ASC">JGRID_HEADING_ID_ASC</option>
|
||||
<option value="update_site_id DESC">JGRID_HEADING_ID_DESC</option>
|
||||
</field>
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
42
administrator/components/com_installer/forms/updatesite.xml
Normal file
42
administrator/components/com_installer/forms/updatesite.xml
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
<fieldset name="updateSite">
|
||||
<field
|
||||
name="update_site_id"
|
||||
type="hidden"
|
||||
/>
|
||||
<field
|
||||
name="name"
|
||||
type="text"
|
||||
label="COM_INSTALLER_FIELD_NAME_LABEL"
|
||||
disabled="true"
|
||||
/>
|
||||
<field
|
||||
name="type"
|
||||
type="text"
|
||||
label="COM_INSTALLER_FIELD_TYPE_LABEL"
|
||||
disabled="true"
|
||||
/>
|
||||
<field
|
||||
name="location"
|
||||
type="text"
|
||||
label="COM_INSTALLER_FIELD_TYPE_LOCATION"
|
||||
disabled="true"
|
||||
/>
|
||||
<field
|
||||
name="extra_query"
|
||||
type="text"
|
||||
label="COM_INSTALLER_FIELD_EXTRA_QUERY_LABEL"
|
||||
description="COM_INSTALLER_FIELD_EXTRA_QUERY_DESC"
|
||||
default=""
|
||||
/>
|
||||
<field
|
||||
name="downloadIdPrefix"
|
||||
type="hidden"
|
||||
/>
|
||||
<field
|
||||
name="downloadIdSuffix"
|
||||
type="hidden"
|
||||
/>
|
||||
</fieldset>
|
||||
</form>
|
||||
27
administrator/components/com_installer/helpers/installer.php
Normal file
27
administrator/components/com_installer/helpers/installer.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*
|
||||
* @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
|
||||
*/
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer helper.
|
||||
*
|
||||
* @since 1.6
|
||||
*
|
||||
* @deprecated 4.3 will be removed in 6.0
|
||||
* Use \Joomla\Component\Installer\Administrator\Helper\InstallerHelper instead
|
||||
*/
|
||||
class InstallerHelper extends \Joomla\Component\Installer\Administrator\Helper\InstallerHelper
|
||||
{
|
||||
}
|
||||
34
administrator/components/com_installer/installer.xml
Normal file
34
administrator/components/com_installer/installer.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="component" method="upgrade">
|
||||
<name>com_installer</name>
|
||||
<author>Joomla! Project</author>
|
||||
<creationDate>2006-04</creationDate>
|
||||
<copyright>(C) 2006 Open Source Matters, Inc.</copyright>
|
||||
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
|
||||
<authorEmail>admin@joomla.org</authorEmail>
|
||||
<authorUrl>www.joomla.org</authorUrl>
|
||||
<version>4.0.0</version>
|
||||
<description>COM_INSTALLER_XML_DESCRIPTION</description>
|
||||
<namespace path="src">Joomla\Component\Installer</namespace>
|
||||
<media destination="com_installer" folder="media">
|
||||
<folder>css</folder>
|
||||
<folder>js</folder>
|
||||
</media>
|
||||
<administration>
|
||||
<files folder="admin">
|
||||
<filename>access.xml</filename>
|
||||
<filename>config.xml</filename>
|
||||
<filename>installer.xml</filename>
|
||||
<folder>forms</folder>
|
||||
<folder>helpers</folder>
|
||||
<folder>services</folder>
|
||||
<folder>src</folder>
|
||||
<folder>tmpl</folder>
|
||||
</files>
|
||||
<languages folder="admin">
|
||||
<language tag="en-GB">language/en-GB/com_installer.ini</language>
|
||||
<language tag="en-GB">language/en-GB/com_installer.sys.ini</language>
|
||||
</languages>
|
||||
</administration>
|
||||
</extension>
|
||||
|
||||
54
administrator/components/com_installer/services/provider.php
Normal file
54
administrator/components/com_installer/services/provider.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2018 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\Dispatcher\ComponentDispatcherFactoryInterface;
|
||||
use Joomla\CMS\Extension\ComponentInterface;
|
||||
use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory;
|
||||
use Joomla\CMS\Extension\Service\Provider\MVCFactory;
|
||||
use Joomla\CMS\HTML\Registry;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\Component\Installer\Administrator\Extension\InstallerComponent;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
|
||||
/**
|
||||
* The installer service provider.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
return new class () implements ServiceProviderInterface {
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->registerServiceProvider(new MVCFactory('\\Joomla\\Component\\Installer'));
|
||||
$container->registerServiceProvider(new ComponentDispatcherFactory('\\Joomla\\Component\\Installer'));
|
||||
|
||||
$container->set(
|
||||
ComponentInterface::class,
|
||||
function (Container $container) {
|
||||
$component = new InstallerComponent($container->get(ComponentDispatcherFactoryInterface::class));
|
||||
$component->setMVCFactory($container->get(MVCFactoryInterface::class));
|
||||
$component->setRegistry($container->get(Registry::class));
|
||||
|
||||
return $component;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Response\JsonResponse;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Component\Installer\Administrator\Model\DatabaseModel;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer Database Controller
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class DatabaseController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Tries to fix missing database updates
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 2.5
|
||||
* @todo Purge updates has to be replaced with an events system
|
||||
*/
|
||||
public function fix()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
// Get items to fix the database.
|
||||
$cid = (array) $this->input->get('cid', [], 'int');
|
||||
|
||||
// Remove zero values resulting from input filter
|
||||
$cid = array_filter($cid);
|
||||
|
||||
if (empty($cid)) {
|
||||
$this->app->getLogger()->warning(
|
||||
Text::_(
|
||||
'COM_INSTALLER_ERROR_NO_EXTENSIONS_SELECTED'
|
||||
),
|
||||
['category' => 'jerror']
|
||||
);
|
||||
} else {
|
||||
/** @var DatabaseModel $model */
|
||||
$model = $this->getModel('Database');
|
||||
$model->fix($cid);
|
||||
|
||||
/** @var \Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel $updateModel */
|
||||
$updateModel = $this->app->bootComponent('com_joomlaupdate')
|
||||
->getMVCFactory()->createModel('Update', 'Administrator', ['ignore_request' => true]);
|
||||
$updateModel->purge();
|
||||
|
||||
// Refresh versionable assets cache
|
||||
$this->app->flushAssets();
|
||||
}
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_installer&view=database', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the data for a badge in a menu item via JSON
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getMenuBadgeData()
|
||||
{
|
||||
if (!$this->app->getIdentity()->authorise('core.manage', 'com_installer')) {
|
||||
throw new \Exception(Text::_('JGLOBAL_AUTH_ACCESS_DENIED'));
|
||||
}
|
||||
|
||||
$model = $this->getModel('Database');
|
||||
|
||||
$changeSet = $model->getItems();
|
||||
|
||||
$changeSetCount = 0;
|
||||
|
||||
foreach ($changeSet as $item) {
|
||||
$changeSetCount += $item['errorsCount'];
|
||||
}
|
||||
|
||||
echo new JsonResponse($changeSetCount);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Response\JsonResponse;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Discover Installation Controller
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class DiscoverController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Refreshes the cache of discovered extensions.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function refresh()
|
||||
{
|
||||
$this->checkToken('request');
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\Model\DiscoverModel $model */
|
||||
$model = $this->getModel('discover');
|
||||
$model->discover();
|
||||
|
||||
if (!$model->getTotal()) {
|
||||
$this->setMessage(Text::_('COM_INSTALLER_ERROR_NO_EXTENSIONS_DISCOVERED'), 'info');
|
||||
}
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_installer&view=discover', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a discovered extension.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
$this->checkToken();
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\Model\DiscoverModel $model */
|
||||
$model = $this->getModel('discover');
|
||||
$model->discover_install();
|
||||
$this->setRedirect(Route::_('index.php?option=com_installer&view=discover', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean out the discovered extension cache.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function purge()
|
||||
{
|
||||
$this->checkToken('request');
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\Model\DiscoverModel $model */
|
||||
$model = $this->getModel('discover');
|
||||
$model->purge();
|
||||
$this->setRedirect(Route::_('index.php?option=com_installer&view=discover', false), $model->_message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the data for a badge in a menu item via JSON
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getMenuBadgeData()
|
||||
{
|
||||
if (!$this->app->getIdentity()->authorise('core.manage', 'com_installer')) {
|
||||
throw new \Exception(Text::_('JGLOBAL_AUTH_ACCESS_DENIED'));
|
||||
}
|
||||
|
||||
$model = $this->getModel('Discover');
|
||||
|
||||
echo new JsonResponse($model->getTotal());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Response\JsonResponse;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer Controller
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class DisplayController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Method to display a view.
|
||||
*
|
||||
* @param boolean $cachable If true, the view output will be cached
|
||||
* @param array $urlparams An array of safe URL parameters and their variable types.
|
||||
* @see \Joomla\CMS\Filter\InputFilter::clean() for valid values.
|
||||
*
|
||||
* @return static This object to support chaining.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function display($cachable = false, $urlparams = false)
|
||||
{
|
||||
// Get the document object.
|
||||
$document = $this->app->getDocument();
|
||||
|
||||
// Set the default view name and format from the Request.
|
||||
$vName = $this->input->get('view', 'install');
|
||||
$vFormat = $document->getType();
|
||||
$lName = $this->input->get('layout', 'default', 'string');
|
||||
$id = $this->input->getInt('update_site_id');
|
||||
|
||||
// Check for edit form.
|
||||
if ($vName === 'updatesite' && $lName === 'edit' && !$this->checkEditId('com_installer.edit.updatesite', $id)) {
|
||||
// Somehow the person just went to the form - we don't allow that.
|
||||
if (!\count($this->app->getMessageQueue())) {
|
||||
$this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id), 'error');
|
||||
}
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_installer&view=updatesites', false));
|
||||
|
||||
$this->redirect();
|
||||
}
|
||||
|
||||
// Get and render the view.
|
||||
if ($view = $this->getView($vName, $vFormat)) {
|
||||
// Get the model for the view.
|
||||
$model = $this->getModel($vName);
|
||||
|
||||
// Push the model into the view (as default).
|
||||
$view->setModel($model, true);
|
||||
$view->setLayout($lName);
|
||||
|
||||
// Push document object into the view.
|
||||
$view->document = $document;
|
||||
|
||||
$view->display();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the data for a badge in a menu item via JSON
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getMenuBadgeData()
|
||||
{
|
||||
if (!$this->app->getIdentity()->authorise('core.manage', 'com_installer')) {
|
||||
throw new \Exception(Text::_('JGLOBAL_AUTH_ACCESS_DENIED'));
|
||||
}
|
||||
|
||||
$model = $this->getModel('Warnings');
|
||||
|
||||
echo new JsonResponse(\count($model->getItems()));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Access\Exception\NotAllowed;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Response\JsonResponse;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer controller for Joomla! installer class.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class InstallController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Install an extension.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
if (!$this->app->getIdentity()->authorise('core.admin')) {
|
||||
throw new NotAllowed(Text::_('JERROR_ALERTNOAUTHOR'), 403);
|
||||
}
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\Model\InstallModel $model */
|
||||
$model = $this->getModel('install');
|
||||
|
||||
// @todo: Reset the users acl here as well to kill off any missing bits.
|
||||
$result = $model->install();
|
||||
|
||||
$app = $this->app;
|
||||
$redirect_url = $app->getUserState('com_installer.redirect_url');
|
||||
$return = $this->input->getBase64('return');
|
||||
|
||||
if (!$redirect_url && $return) {
|
||||
$redirect_url = base64_decode($return);
|
||||
}
|
||||
|
||||
// Don't redirect to an external URL.
|
||||
if ($redirect_url && !Uri::isInternal($redirect_url)) {
|
||||
$redirect_url = '';
|
||||
}
|
||||
|
||||
if (empty($redirect_url)) {
|
||||
$redirect_url = Route::_('index.php?option=com_installer&view=install', false);
|
||||
} else {
|
||||
// Wipe out the user state when we're going to redirect.
|
||||
$app->setUserState('com_installer.redirect_url', '');
|
||||
$app->setUserState('com_installer.message', '');
|
||||
$app->setUserState('com_installer.extension_message', '');
|
||||
}
|
||||
|
||||
$this->setRedirect($redirect_url);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install an extension from drag & drop ajax upload.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public function ajax_upload()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
Session::checkToken() or jexit(Text::_('JINVALID_TOKEN'));
|
||||
|
||||
if (!$this->app->getIdentity()->authorise('core.admin')) {
|
||||
throw new NotAllowed(Text::_('JERROR_ALERTNOAUTHOR'), 403);
|
||||
}
|
||||
|
||||
$message = $this->app->getUserState('com_installer.message');
|
||||
|
||||
// Do install
|
||||
$result = $this->install();
|
||||
|
||||
// Get redirect URL
|
||||
$redirect = $this->redirect;
|
||||
|
||||
// Push message queue to session because we will redirect page by \Javascript, not $app->redirect().
|
||||
// The "application.queue" is only set in redirect() method, so we must manually store it.
|
||||
$this->app->getSession()->set('application.queue', $this->app->getMessageQueue());
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
echo new JsonResponse(['redirect' => $redirect], $message, !$result);
|
||||
|
||||
$this->app->close();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,200 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Controller;
|
||||
|
||||
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\Component\Installer\Administrator\Model\ManageModel;
|
||||
use Joomla\Input\Input;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer Manage Controller
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class ManageController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
* @param ?CMSApplication $app The Application for the dispatcher
|
||||
* @param ?Input $input Input
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function __construct($config = [], ?MVCFactoryInterface $factory = null, $app = null, $input = null)
|
||||
{
|
||||
parent::__construct($config, $factory, $app, $input);
|
||||
|
||||
$this->registerTask('unpublish', 'publish');
|
||||
$this->registerTask('publish', 'publish');
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable an extension (if supported).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function publish()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
$ids = (array) $this->input->get('cid', [], 'int');
|
||||
$values = ['publish' => 1, 'unpublish' => 0];
|
||||
$task = $this->getTask();
|
||||
$value = ArrayHelper::getValue($values, $task, 0, 'int');
|
||||
|
||||
// Remove zero values resulting from input filter
|
||||
$ids = array_filter($ids);
|
||||
|
||||
if (empty($ids)) {
|
||||
$this->setMessage(Text::_('COM_INSTALLER_ERROR_NO_EXTENSIONS_SELECTED'), 'warning');
|
||||
} else {
|
||||
/** @var ManageModel $model */
|
||||
$model = $this->getModel('manage');
|
||||
|
||||
// Change the state of the records.
|
||||
if (!$model->publish($ids, $value)) {
|
||||
$this->setMessage(implode('<br>', $model->getErrors()), 'warning');
|
||||
} else {
|
||||
if ($value == 1) {
|
||||
$ntext = 'COM_INSTALLER_N_EXTENSIONS_PUBLISHED';
|
||||
} else {
|
||||
$ntext = 'COM_INSTALLER_N_EXTENSIONS_UNPUBLISHED';
|
||||
}
|
||||
|
||||
$this->setMessage(Text::plural($ntext, \count($ids)));
|
||||
}
|
||||
}
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_installer&view=manage', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an extension (Uninstall).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
$eid = (array) $this->input->get('cid', [], 'int');
|
||||
|
||||
// Remove zero values resulting from input filter
|
||||
$eid = array_filter($eid);
|
||||
|
||||
if (!empty($eid)) {
|
||||
/** @var ManageModel $model */
|
||||
$model = $this->getModel('manage');
|
||||
|
||||
$model->remove($eid);
|
||||
}
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_installer&view=manage', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the cached metadata about an extension.
|
||||
*
|
||||
* Useful for debugging and testing purposes when the XML file might change.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function refresh()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
$uid = (array) $this->input->get('cid', [], 'int');
|
||||
|
||||
// Remove zero values resulting from input filter
|
||||
$uid = array_filter($uid);
|
||||
|
||||
if (!empty($uid)) {
|
||||
/** @var ManageModel $model */
|
||||
$model = $this->getModel('manage');
|
||||
|
||||
$model->refresh($uid);
|
||||
}
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_installer&view=manage', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the changelog for a given extension. Outputs HTML encoded in JSON.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the changelog for a given extension. Outputs HTML.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.1.0
|
||||
*/
|
||||
public function loadChangelogRaw()
|
||||
{
|
||||
/** @var ManageModel $model */
|
||||
$model = $this->getModel('manage');
|
||||
|
||||
$eid = $this->input->get('eid', 0, 'int');
|
||||
$source = $this->input->get('source', 'manage', 'string');
|
||||
|
||||
if (!$eid) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo $model->loadChangelog($eid, $source);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Response\JsonResponse;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\CMS\Updater\Updater;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
use Joomla\Component\Installer\Administrator\Model\UpdateModel;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer Update Controller
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class UpdateController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Update a set of extensions.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
/** @var UpdateModel $model */
|
||||
$model = $this->getModel('update');
|
||||
|
||||
$uid = (array) $this->input->get('cid', [], 'int');
|
||||
|
||||
// Remove zero values resulting from input filter
|
||||
$uid = array_filter($uid);
|
||||
|
||||
// Get the minimum stability.
|
||||
$params = ComponentHelper::getComponent('com_installer')->getParams();
|
||||
$minimum_stability = (int) $params->get('minimum_stability', Updater::STABILITY_STABLE);
|
||||
|
||||
$model->update($uid, $minimum_stability);
|
||||
|
||||
$app = $this->app;
|
||||
$redirect_url = $app->getUserState('com_installer.redirect_url');
|
||||
|
||||
// Don't redirect to an external URL.
|
||||
if ($redirect_url && !Uri::isInternal($redirect_url)) {
|
||||
$redirect_url = '';
|
||||
}
|
||||
|
||||
if (empty($redirect_url)) {
|
||||
$redirect_url = Route::_('index.php?option=com_installer&view=update', false);
|
||||
} else {
|
||||
// Wipe out the user state when we're going to redirect.
|
||||
$app->setUserState('com_installer.redirect_url', '');
|
||||
$app->setUserState('com_installer.message', '');
|
||||
$app->setUserState('com_installer.extension_message', '');
|
||||
}
|
||||
|
||||
$this->setRedirect($redirect_url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find new updates.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function find()
|
||||
{
|
||||
$this->checkToken('request');
|
||||
|
||||
// Get the caching duration.
|
||||
$params = ComponentHelper::getComponent('com_installer')->getParams();
|
||||
$cache_timeout = (int) $params->get('cachetimeout', 6);
|
||||
$cache_timeout = 3600 * $cache_timeout;
|
||||
|
||||
// Get the minimum stability.
|
||||
$minimum_stability = (int) $params->get('minimum_stability', Updater::STABILITY_STABLE);
|
||||
|
||||
// Find updates.
|
||||
/** @var UpdateModel $model */
|
||||
$model = $this->getModel('update');
|
||||
|
||||
// Purge the table before checking again
|
||||
$model->purge();
|
||||
|
||||
$disabledUpdateSites = $model->getDisabledUpdateSites();
|
||||
|
||||
if ($disabledUpdateSites) {
|
||||
$updateSitesUrl = Route::_('index.php?option=com_installer&view=updatesites');
|
||||
$this->app->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_UPDATE_SITES_COUNT_CHECK', $updateSitesUrl), 'warning');
|
||||
}
|
||||
|
||||
$model->findUpdates(0, $cache_timeout, $minimum_stability);
|
||||
|
||||
if (0 === $model->getTotal()) {
|
||||
$this->app->enqueueMessage(Text::_('COM_INSTALLER_MSG_UPDATE_NOUPDATES'), 'info');
|
||||
}
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_installer&view=update', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch and report updates in \JSON format, for AJAX requests
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function ajax()
|
||||
{
|
||||
$app = $this->app;
|
||||
|
||||
if (!Session::checkToken('get')) {
|
||||
$app->setHeader('status', 403, true);
|
||||
$app->sendHeaders();
|
||||
echo Text::_('JINVALID_TOKEN_NOTICE');
|
||||
$app->close();
|
||||
}
|
||||
|
||||
// Close the session before we make a long running request
|
||||
$app->getSession()->abort();
|
||||
|
||||
$eid = $this->input->getInt('eid', 0);
|
||||
$skip = $this->input->get('skip', [], 'array');
|
||||
$cache_timeout = $this->input->getInt('cache_timeout', 0);
|
||||
$minimum_stability = $this->input->getInt('minimum_stability', -1);
|
||||
|
||||
$params = ComponentHelper::getComponent('com_installer')->getParams();
|
||||
|
||||
if ($cache_timeout == 0) {
|
||||
$cache_timeout = (int) $params->get('cachetimeout', 6);
|
||||
$cache_timeout = 3600 * $cache_timeout;
|
||||
}
|
||||
|
||||
if ($minimum_stability < 0) {
|
||||
$minimum_stability = (int) $params->get('minimum_stability', Updater::STABILITY_STABLE);
|
||||
}
|
||||
|
||||
/** @var UpdateModel $model */
|
||||
$model = $this->getModel('update');
|
||||
$model->findUpdates($eid, $cache_timeout, $minimum_stability);
|
||||
|
||||
$model->setState('list.start', 0);
|
||||
$model->setState('list.limit', 0);
|
||||
|
||||
if ($eid != 0) {
|
||||
$model->setState('filter.extension_id', $eid);
|
||||
}
|
||||
|
||||
$updates = $model->getItems();
|
||||
|
||||
if (!empty($skip)) {
|
||||
$unfiltered_updates = $updates;
|
||||
$updates = [];
|
||||
|
||||
foreach ($unfiltered_updates as $update) {
|
||||
if (!\in_array($update->extension_id, $skip)) {
|
||||
$updates[] = $update;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode($updates);
|
||||
|
||||
$app->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the data for a badge in a menu item via JSON
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getMenuBadgeData()
|
||||
{
|
||||
if (!$this->app->getIdentity()->authorise('core.manage', 'com_installer')) {
|
||||
throw new \Exception(Text::_('JGLOBAL_AUTH_ACCESS_DENIED'));
|
||||
}
|
||||
|
||||
$model = $this->getModel('Update');
|
||||
|
||||
echo new JsonResponse($model->getTotal());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\MVC\Controller\FormController;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Controller for a single update site
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class UpdatesiteController extends FormController
|
||||
{
|
||||
}
|
||||
@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\AdminController;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Input\Input;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer Update Sites Controller
|
||||
*
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
* @since 3.4
|
||||
*/
|
||||
class UpdatesitesController extends AdminController
|
||||
{
|
||||
/**
|
||||
* The prefix to use with controller messages.
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $text_prefix = 'COM_INSTALLER_UPDATESITES';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
* @param ?CMSApplication $app The Application for the dispatcher
|
||||
* @param ?Input $input Input
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function __construct($config = [], ?MVCFactoryInterface $factory = null, $app = null, $input = null)
|
||||
{
|
||||
parent::__construct($config, $factory, $app, $input);
|
||||
|
||||
$this->registerTask('unpublish', 'publish');
|
||||
$this->registerTask('publish', 'publish');
|
||||
$this->registerTask('delete', 'delete');
|
||||
$this->registerTask('rebuild', 'rebuild');
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy for getModel.
|
||||
*
|
||||
* @param string $name The model name. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config The array of possible config values. Optional.
|
||||
*
|
||||
* @return \Joomla\CMS\MVC\Model\BaseDatabaseModel
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getModel($name = 'Updatesite', $prefix = 'Administrator', $config = ['ignore_request' => true])
|
||||
{
|
||||
return parent::getModel($name, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable an extension (if supported).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @throws \Exception on error
|
||||
*/
|
||||
public function publish()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
$ids = (array) $this->input->get('cid', [], 'int');
|
||||
$values = ['publish' => 1, 'unpublish' => 0];
|
||||
$task = $this->getTask();
|
||||
$value = ArrayHelper::getValue($values, $task, 0, 'int');
|
||||
|
||||
// Remove zero values resulting from input filter
|
||||
$ids = array_filter($ids);
|
||||
|
||||
if (empty($ids)) {
|
||||
throw new \Exception(Text::_('COM_INSTALLER_ERROR_NO_UPDATESITES_SELECTED'), 500);
|
||||
}
|
||||
|
||||
// Get the model.
|
||||
/** @var \Joomla\Component\Installer\Administrator\Model\UpdatesitesModel $model */
|
||||
$model = $this->getModel('Updatesites');
|
||||
|
||||
// Change the state of the records.
|
||||
if (!$model->publish($ids, $value)) {
|
||||
throw new \Exception(implode('<br>', $model->getErrors()), 500);
|
||||
}
|
||||
|
||||
$ntext = ($value == 0) ? 'COM_INSTALLER_N_UPDATESITES_UNPUBLISHED' : 'COM_INSTALLER_N_UPDATESITES_PUBLISHED';
|
||||
|
||||
$this->setMessage(Text::plural($ntext, \count($ids)));
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_installer&view=updatesites', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an update site (if supported).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.6
|
||||
*
|
||||
* @throws \Exception on error
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
$ids = (array) $this->input->get('cid', [], 'int');
|
||||
|
||||
// Remove zero values resulting from input filter
|
||||
$ids = array_filter($ids);
|
||||
|
||||
if (empty($ids)) {
|
||||
throw new \Exception(Text::_('COM_INSTALLER_ERROR_NO_UPDATESITES_SELECTED'), 500);
|
||||
}
|
||||
|
||||
// Delete the records.
|
||||
$this->getModel('Updatesites')->delete($ids);
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_installer&view=updatesites', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild update sites tables.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
public function rebuild()
|
||||
{
|
||||
// Check for request forgeries.
|
||||
$this->checkToken();
|
||||
|
||||
// Rebuild the update sites.
|
||||
$this->getModel('Updatesites')->rebuild();
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_installer&view=updatesites', false));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Extension;
|
||||
|
||||
use Joomla\CMS\Extension\BootableExtensionInterface;
|
||||
use Joomla\CMS\Extension\MVCComponent;
|
||||
use Joomla\CMS\HTML\HTMLRegistryAwareTrait;
|
||||
use Joomla\Component\Installer\Administrator\Service\HTML\Manage;
|
||||
use Joomla\Component\Installer\Administrator\Service\HTML\Updatesites;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Component class for com_installer
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class InstallerComponent extends MVCComponent implements
|
||||
BootableExtensionInterface
|
||||
{
|
||||
use HTMLRegistryAwareTrait;
|
||||
|
||||
/**
|
||||
* Booting the extension. This is the function to set up the environment of the extension like
|
||||
* registering new class loaders, etc.
|
||||
*
|
||||
* If required, some initial set up can be done from services of the container, eg.
|
||||
* registering HTML services.
|
||||
*
|
||||
* @param ContainerInterface $container The container
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function boot(ContainerInterface $container)
|
||||
{
|
||||
$this->getRegistry()->register('manage', new Manage());
|
||||
$this->getRegistry()->register('updatesites', new Updatesites());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\Component\Installer\Administrator\Helper\InstallerHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Extension Status field.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
class ExtensionstatusField extends ListField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.5
|
||||
*/
|
||||
protected $type = 'ExtensionStatus';
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
$options = InstallerHelper::getStateOptions();
|
||||
|
||||
return array_merge(parent::getOptions(), $options);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\Component\Installer\Administrator\Helper\InstallerHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Folder field.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
class FolderField extends ListField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.5
|
||||
*/
|
||||
protected $type = 'Folder';
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
$options = InstallerHelper::getExtensionGroups();
|
||||
|
||||
return array_merge(parent::getOptions(), $options);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\Component\Installer\Administrator\Helper\InstallerHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Location field.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
class LocationField extends ListField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.5
|
||||
*/
|
||||
protected $type = 'Location';
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
$options = InstallerHelper::getClientOptions();
|
||||
|
||||
return array_merge(parent::getOptions(), $options);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\Component\Installer\Administrator\Helper\InstallerHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Package field.
|
||||
*
|
||||
* Selects the extension ID of an extension of the "package" type.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
class PackageField extends ListField
|
||||
{
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects.
|
||||
* @since 4.2.0
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
$options = InstallerHelper::getPackageOptions();
|
||||
|
||||
return array_merge(parent::getOptions(), $options);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\Component\Installer\Administrator\Helper\InstallerHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Form field for a list of extension types.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
class TypeField extends ListField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.5
|
||||
*/
|
||||
protected $type = 'Type';
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
$options = InstallerHelper::getExtensionTypes();
|
||||
|
||||
return array_merge(parent::getOptions(), $options);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,488 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Helper;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Object\CMSObject;
|
||||
use Joomla\Database\DatabaseInterface;
|
||||
use Joomla\Database\ParameterType;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer helper.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class InstallerHelper
|
||||
{
|
||||
/**
|
||||
* Get a list of filter options for the extension types.
|
||||
*
|
||||
* @return array An array of \stdClass objects.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public static function getExtensionTypes()
|
||||
{
|
||||
$db = Factory::getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->select('DISTINCT ' . $db->quoteName('type'))
|
||||
->from($db->quoteName('#__extensions'));
|
||||
$db->setQuery($query);
|
||||
$types = $db->loadColumn();
|
||||
|
||||
$options = [];
|
||||
|
||||
foreach ($types as $type) {
|
||||
$options[] = HTMLHelper::_('select.option', $type, Text::_('COM_INSTALLER_TYPE_' . strtoupper($type)));
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of filter options for the extension types.
|
||||
*
|
||||
* @return array An array of \stdClass objects.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public static function getExtensionGroups()
|
||||
{
|
||||
$nofolder = '';
|
||||
$db = Factory::getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->select('DISTINCT ' . $db->quoteName('folder'))
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('folder') . ' != :folder')
|
||||
->bind(':folder', $nofolder)
|
||||
->order($db->quoteName('folder'));
|
||||
$db->setQuery($query);
|
||||
$folders = $db->loadColumn();
|
||||
|
||||
$options = [];
|
||||
|
||||
foreach ($folders as $folder) {
|
||||
$options[] = HTMLHelper::_('select.option', $folder, $folder);
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of filter options for the application clients.
|
||||
*
|
||||
* @return array An array of \JHtmlOption elements.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
public static function getClientOptions()
|
||||
{
|
||||
// Build the filter options.
|
||||
$options = [];
|
||||
$options[] = HTMLHelper::_('select.option', '0', Text::_('JSITE'));
|
||||
$options[] = HTMLHelper::_('select.option', '1', Text::_('JADMINISTRATOR'));
|
||||
$options[] = HTMLHelper::_('select.option', '3', Text::_('JAPI'));
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of filter options for the application statuses.
|
||||
*
|
||||
* @return array An array of \JHtmlOption elements.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
public static function getStateOptions()
|
||||
{
|
||||
// Build the filter options.
|
||||
$options = [];
|
||||
$options[] = HTMLHelper::_('select.option', '0', Text::_('JDISABLED'));
|
||||
$options[] = HTMLHelper::_('select.option', '1', Text::_('JENABLED'));
|
||||
$options[] = HTMLHelper::_('select.option', '2', Text::_('JPROTECTED'));
|
||||
$options[] = HTMLHelper::_('select.option', '3', Text::_('JUNPROTECTED'));
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of filter options for extensions of the "package" type.
|
||||
*
|
||||
* @return array
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public static function getPackageOptions(): array
|
||||
{
|
||||
$options = [];
|
||||
|
||||
/** @var DatabaseInterface $db The application's database driver object */
|
||||
$db = Factory::getContainer()->get(DatabaseInterface::class);
|
||||
$query = $db->getQuery(true)
|
||||
->select(
|
||||
$db->quoteName(
|
||||
[
|
||||
'extension_id',
|
||||
'name',
|
||||
'element',
|
||||
]
|
||||
)
|
||||
)
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('package'));
|
||||
$extensions = $db->setQuery($query)->loadObjectList() ?: [];
|
||||
|
||||
if (empty($extensions)) {
|
||||
return $options;
|
||||
}
|
||||
|
||||
$language = Factory::getApplication()->getLanguage();
|
||||
$arrayKeys = array_map(
|
||||
function (object $entry) use ($language): string {
|
||||
$language->load($entry->element, JPATH_ADMINISTRATOR);
|
||||
|
||||
return Text::_($entry->name);
|
||||
},
|
||||
$extensions
|
||||
);
|
||||
$arrayValues = array_map(
|
||||
function (object $entry): int {
|
||||
return $entry->extension_id;
|
||||
},
|
||||
$extensions
|
||||
);
|
||||
|
||||
$extensions = array_combine($arrayKeys, $arrayValues);
|
||||
ksort($extensions);
|
||||
|
||||
foreach ($extensions as $label => $id) {
|
||||
$options[] = HTMLHelper::_('select.option', $id, $label);
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of filter options for the application statuses.
|
||||
*
|
||||
* @param string $element element of an extension
|
||||
* @param string $type type of an extension
|
||||
* @param integer $clientId client_id of an extension
|
||||
* @param ?string $folder folder of an extension
|
||||
*
|
||||
* @return \SimpleXMLElement
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static function getInstallationXML(
|
||||
string $element,
|
||||
string $type,
|
||||
int $clientId = 1,
|
||||
?string $folder = null
|
||||
): ?\SimpleXMLElement {
|
||||
$path = [0 => JPATH_SITE, 1 => JPATH_ADMINISTRATOR, 3 => JPATH_API][$clientId] ?? JPATH_SITE;
|
||||
|
||||
switch ($type) {
|
||||
case 'component':
|
||||
$path .= '/components/' . $element . '/' . substr($element, 4) . '.xml';
|
||||
break;
|
||||
case 'plugin':
|
||||
$path .= '/plugins/' . $folder . '/' . $element . '/' . $element . '.xml';
|
||||
break;
|
||||
case 'module':
|
||||
$path .= '/modules/' . $element . '/' . $element . '.xml';
|
||||
break;
|
||||
case 'template':
|
||||
$path .= '/templates/' . $element . '/templateDetails.xml';
|
||||
break;
|
||||
case 'library':
|
||||
$path = JPATH_ADMINISTRATOR . '/manifests/libraries/' . $element . '.xml';
|
||||
break;
|
||||
case 'file':
|
||||
$path = JPATH_ADMINISTRATOR . '/manifests/files/' . $element . '.xml';
|
||||
break;
|
||||
case 'package':
|
||||
$path = JPATH_ADMINISTRATOR . '/manifests/packages/' . $element . '.xml';
|
||||
break;
|
||||
case 'language':
|
||||
$path .= '/language/' . $element . '/install.xml';
|
||||
}
|
||||
|
||||
if (file_exists($path) === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$xmlElement = simplexml_load_file($path);
|
||||
|
||||
return ($xmlElement !== false) ? $xmlElement : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the download key of an extension going through their installation xml
|
||||
*
|
||||
* @param CMSObject $extension element of an extension
|
||||
*
|
||||
* @return array An array with the prefix, suffix and value of the download key
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static function getDownloadKey(CMSObject $extension): array
|
||||
{
|
||||
$installXmlFile = self::getInstallationXML(
|
||||
$extension->get('element'),
|
||||
$extension->get('type'),
|
||||
$extension->get('client_id'),
|
||||
$extension->get('folder')
|
||||
);
|
||||
|
||||
if (!$installXmlFile) {
|
||||
return [
|
||||
'supported' => false,
|
||||
'valid' => false,
|
||||
];
|
||||
}
|
||||
|
||||
if (!isset($installXmlFile->dlid)) {
|
||||
return [
|
||||
'supported' => false,
|
||||
'valid' => false,
|
||||
];
|
||||
}
|
||||
|
||||
$prefix = (string) $installXmlFile->dlid['prefix'];
|
||||
$suffix = (string) $installXmlFile->dlid['suffix'];
|
||||
$value = substr($extension->get('extra_query'), \strlen($prefix));
|
||||
|
||||
if ($suffix) {
|
||||
$value = substr($value, 0, -\strlen($suffix));
|
||||
}
|
||||
|
||||
$downloadKey = [
|
||||
'supported' => true,
|
||||
'valid' => (bool) $value,
|
||||
'prefix' => $prefix,
|
||||
'suffix' => $suffix,
|
||||
'value' => $value,
|
||||
];
|
||||
|
||||
return $downloadKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the download key of an extension given enough information to locate it in the #__extensions table
|
||||
*
|
||||
* @param string $element Name of the extension, e.g. com_foo
|
||||
* @param string $type The type of the extension, e.g. component
|
||||
* @param int $clientId [optional] Joomla client for the extension, see the #__extensions table
|
||||
* @param string|null $folder Extension folder, only applies for 'plugin' type
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static function getExtensionDownloadKey(
|
||||
string $element,
|
||||
string $type,
|
||||
int $clientId = 1,
|
||||
?string $folder = null
|
||||
): array {
|
||||
// Get the database driver. If it fails we cannot report whether the extension supports download keys.
|
||||
try {
|
||||
$db = Factory::getDbo();
|
||||
} catch (\Exception $e) {
|
||||
return [
|
||||
'supported' => false,
|
||||
'valid' => false,
|
||||
];
|
||||
}
|
||||
|
||||
// Try to retrieve the extension information as a CMSObject
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('extension_id'))
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('type') . ' = :type')
|
||||
->where($db->quoteName('element') . ' = :element')
|
||||
->where($db->quoteName('folder') . ' = :folder')
|
||||
->where($db->quoteName('client_id') . ' = :client_id');
|
||||
$query->bind(':type', $type, ParameterType::STRING);
|
||||
$query->bind(':element', $element, ParameterType::STRING);
|
||||
$query->bind(':client_id', $clientId, ParameterType::INTEGER);
|
||||
$query->bind(':folder', $folder, ParameterType::STRING);
|
||||
|
||||
try {
|
||||
$extension = new CMSObject($db->setQuery($query)->loadAssoc());
|
||||
} catch (\Exception $e) {
|
||||
return [
|
||||
'supported' => false,
|
||||
'valid' => false,
|
||||
];
|
||||
}
|
||||
|
||||
// Use the getDownloadKey() method to return the download key information
|
||||
return self::getDownloadKey($extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of update site IDs which support download keys. By default this returns all qualifying update
|
||||
* sites, even if they are not enabled.
|
||||
*
|
||||
*
|
||||
* @param bool $onlyEnabled [optional] Set true to only returned enabled update sites.
|
||||
*
|
||||
* @return int[]
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static function getDownloadKeySupportedSites($onlyEnabled = false): array
|
||||
{
|
||||
/**
|
||||
* NOTE: The closures are not inlined because in this case the Joomla Code Style standard produces two mutually
|
||||
* exclusive errors, making the file impossible to commit. Using closures in variables makes the code less
|
||||
* readable but works around that issue.
|
||||
*/
|
||||
|
||||
$extensions = self::getUpdateSitesInformation($onlyEnabled);
|
||||
|
||||
$filterClosure = function (CMSObject $extension) {
|
||||
$dlidInfo = self::getDownloadKey($extension);
|
||||
|
||||
return $dlidInfo['supported'];
|
||||
};
|
||||
$extensions = array_filter($extensions, $filterClosure);
|
||||
|
||||
$mapClosure = function (CMSObject $extension) {
|
||||
return $extension->get('update_site_id');
|
||||
};
|
||||
|
||||
return array_map($mapClosure, $extensions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of update site IDs which are missing download keys. By default this returns all qualifying update
|
||||
* sites, even if they are not enabled.
|
||||
*
|
||||
* @param bool $exists [optional] If true, returns update sites with a valid download key. When false,
|
||||
* returns update sites with an invalid / missing download key.
|
||||
* @param bool $onlyEnabled [optional] Set true to only returned enabled update sites.
|
||||
*
|
||||
* @return int[]
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static function getDownloadKeyExistsSites(bool $exists = true, $onlyEnabled = false): array
|
||||
{
|
||||
/**
|
||||
* NOTE: The closures are not inlined because in this case the Joomla Code Style standard produces two mutually
|
||||
* exclusive errors, making the file impossible to commit. Using closures in variables makes the code less
|
||||
* readable but works around that issue.
|
||||
*/
|
||||
|
||||
$extensions = self::getUpdateSitesInformation($onlyEnabled);
|
||||
|
||||
// Filter the extensions by what supports Download Keys
|
||||
$filterClosure = function (CMSObject $extension) use ($exists) {
|
||||
$dlidInfo = self::getDownloadKey($extension);
|
||||
|
||||
if (!$dlidInfo['supported']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $exists ? $dlidInfo['valid'] : !$dlidInfo['valid'];
|
||||
};
|
||||
$extensions = array_filter($extensions, $filterClosure);
|
||||
|
||||
// Return only the update site IDs
|
||||
$mapClosure = function (CMSObject $extension) {
|
||||
return $extension->get('update_site_id');
|
||||
};
|
||||
|
||||
return array_map($mapClosure, $extensions);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get information about the update sites
|
||||
*
|
||||
* @param bool $onlyEnabled Only return enabled update sites
|
||||
*
|
||||
* @return CMSObject[] List of update site and linked extension information
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected static function getUpdateSitesInformation(bool $onlyEnabled): array
|
||||
{
|
||||
try {
|
||||
$db = Factory::getDbo();
|
||||
} catch (\Exception $e) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select(
|
||||
$db->quoteName(
|
||||
[
|
||||
's.update_site_id',
|
||||
's.enabled',
|
||||
's.extra_query',
|
||||
'e.extension_id',
|
||||
'e.type',
|
||||
'e.element',
|
||||
'e.folder',
|
||||
'e.client_id',
|
||||
'e.manifest_cache',
|
||||
],
|
||||
[
|
||||
'update_site_id',
|
||||
'enabled',
|
||||
'extra_query',
|
||||
'extension_id',
|
||||
'type',
|
||||
'element',
|
||||
'folder',
|
||||
'client_id',
|
||||
'manifest_cache',
|
||||
]
|
||||
)
|
||||
)
|
||||
->from($db->quoteName('#__update_sites', 's'))
|
||||
->innerJoin(
|
||||
$db->quoteName('#__update_sites_extensions', 'se'),
|
||||
$db->quoteName('se.update_site_id') . ' = ' . $db->quoteName('s.update_site_id')
|
||||
)
|
||||
->innerJoin(
|
||||
$db->quoteName('#__extensions', 'e'),
|
||||
$db->quoteName('e.extension_id') . ' = ' . $db->quoteName('se.extension_id')
|
||||
)
|
||||
->where($db->quoteName('state') . ' = 0');
|
||||
|
||||
if ($onlyEnabled) {
|
||||
$enabled = 1;
|
||||
$query->where($db->quoteName('s.enabled') . ' = :enabled')
|
||||
->bind(':enabled', $enabled, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
// Try to get all of the update sites, including related extension information
|
||||
try {
|
||||
$items = [];
|
||||
$db->setQuery($query);
|
||||
|
||||
foreach ($db->getIterator() as $item) {
|
||||
$items[] = new CMSObject($item);
|
||||
}
|
||||
|
||||
return $items;
|
||||
} catch (\Exception $e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,651 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Model;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\Schema\ChangeSet;
|
||||
use Joomla\CMS\Table\Extension;
|
||||
use Joomla\CMS\Version;
|
||||
use Joomla\Component\Installer\Administrator\Helper\InstallerHelper;
|
||||
use Joomla\Database\Exception\ExecutionFailureException;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Database\QueryInterface;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
\JLoader::register('JoomlaInstallerScript', JPATH_ADMINISTRATOR . '/components/com_admin/script.php');
|
||||
|
||||
/**
|
||||
* Installer Database Model
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class DatabaseModel extends InstallerModel
|
||||
{
|
||||
/**
|
||||
* Set the model context
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $_context = 'com_installer.discover';
|
||||
|
||||
/**
|
||||
* ChangeSet of all extensions
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private $changeSetList = [];
|
||||
|
||||
/**
|
||||
* Total of errors
|
||||
*
|
||||
* @var integer
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private $errorCount = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
*
|
||||
* @see ListModel
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct($config = [], ?MVCFactoryInterface $factory = null)
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'update_site_name',
|
||||
'name',
|
||||
'client_id',
|
||||
'client', 'client_translated',
|
||||
'status',
|
||||
'type', 'type_translated',
|
||||
'folder', 'folder_translated',
|
||||
'extension_id',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to return the total number of errors in all the extensions, saved in cache.
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getErrorCount()
|
||||
{
|
||||
return $this->errorCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to populate the schema cache.
|
||||
*
|
||||
* @param integer $cid The extension ID to get the schema for
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function fetchSchemaCache($cid = 0)
|
||||
{
|
||||
// We already have it
|
||||
if (\array_key_exists($cid, $this->changeSetList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the ID to the state so it can be used for filtering
|
||||
if ($cid) {
|
||||
$this->setState('filter.extension_id', $cid);
|
||||
}
|
||||
|
||||
// With the parent::save it can get the limit and we need to make sure it gets all extensions
|
||||
$results = $this->_getList($this->getListQuery());
|
||||
|
||||
foreach ($results as $result) {
|
||||
$errorMessages = [];
|
||||
$errorCount = 0;
|
||||
|
||||
if (strcmp($result->element, 'joomla') === 0) {
|
||||
$result->element = 'com_admin';
|
||||
|
||||
if (!$this->getDefaultTextFilters()) {
|
||||
$errorMessages[] = Text::_('COM_INSTALLER_MSG_DATABASE_FILTER_ERROR');
|
||||
$errorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
$db = $this->getDatabase();
|
||||
|
||||
if ($result->type === 'component') {
|
||||
$basePath = JPATH_ADMINISTRATOR . '/components/' . $result->element;
|
||||
} elseif ($result->type === 'plugin') {
|
||||
$basePath = JPATH_PLUGINS . '/' . $result->folder . '/' . $result->element;
|
||||
} elseif ($result->type === 'module') {
|
||||
// Typehint to integer to normalise some DBs returning strings and others integers
|
||||
if ((int) $result->client_id === 1) {
|
||||
$basePath = JPATH_ADMINISTRATOR . '/modules/' . $result->element;
|
||||
} elseif ((int) $result->client_id === 0) {
|
||||
$basePath = JPATH_SITE . '/modules/' . $result->element;
|
||||
} else {
|
||||
// Module with unknown client id!? - bail
|
||||
continue;
|
||||
}
|
||||
} elseif ($result->type === 'file' && $result->element === 'com_admin') {
|
||||
// Specific bodge for the Joomla CMS special database check which points to com_admin
|
||||
$basePath = JPATH_ADMINISTRATOR . '/components/' . $result->element;
|
||||
} else {
|
||||
// Unknown extension type (library, files etc which don't have known SQL paths right now)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Search the standard SQL Path for the SQL Updates and then if not there check the configuration of the XML
|
||||
// file. This just gives us a small performance win of not parsing the XML every time.
|
||||
$folderTmp = $basePath . '/sql/updates/';
|
||||
|
||||
if (!file_exists($folderTmp)) {
|
||||
$installationXML = InstallerHelper::getInstallationXML(
|
||||
$result->element,
|
||||
$result->type,
|
||||
$result->client_id,
|
||||
$result->type === 'plugin' ? $result->folder : null
|
||||
);
|
||||
|
||||
if ($installationXML !== null) {
|
||||
$folderTmp = (string) $installationXML->update->schemas->schemapath[0];
|
||||
$a = explode('/', $folderTmp);
|
||||
array_pop($a);
|
||||
$folderTmp = $basePath . '/' . implode('/', $a);
|
||||
}
|
||||
}
|
||||
|
||||
// Can't find the folder still - give up now and move on.
|
||||
if (!file_exists($folderTmp)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$changeSet = new ChangeSet($db, $folderTmp);
|
||||
|
||||
// If the version in the #__schemas is different
|
||||
// than the update files, add to problems message
|
||||
$schema = $changeSet->getSchema();
|
||||
|
||||
// If the schema is empty we couldn't find any update files. Just ignore the extension.
|
||||
if (empty($schema)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($result->version_id !== $schema) {
|
||||
$errorMessages[] = Text::sprintf('COM_INSTALLER_MSG_DATABASE_SCHEMA_ERROR', $result->version_id, $schema);
|
||||
$errorCount++;
|
||||
}
|
||||
|
||||
// If the version in the manifest_cache is different than the
|
||||
// version in the installation xml, add to problems message
|
||||
$compareUpdateMessage = $this->compareUpdateVersion($result);
|
||||
|
||||
if ($compareUpdateMessage) {
|
||||
$errorMessages[] = $compareUpdateMessage;
|
||||
$errorCount++;
|
||||
}
|
||||
|
||||
// If there are errors in the database, add to the problems message
|
||||
$errors = $changeSet->check();
|
||||
|
||||
$errorsMessage = $this->getErrorsMessage($errors);
|
||||
|
||||
if ($errorsMessage) {
|
||||
$errorMessages = array_merge($errorMessages, $errorsMessage);
|
||||
$errorCount++;
|
||||
}
|
||||
|
||||
// Number of database tables Checked and Skipped
|
||||
$errorMessages = array_merge($errorMessages, $this->getOtherInformationMessage($changeSet->getStatus()));
|
||||
|
||||
// Set the total number of errors
|
||||
$this->errorCount += $errorCount;
|
||||
|
||||
// Collect the extension details
|
||||
$this->changeSetList[$result->extension_id] = [
|
||||
'folderTmp' => $folderTmp,
|
||||
'errorsMessage' => $errorMessages,
|
||||
'errorsCount' => $errorCount,
|
||||
'results' => $changeSet->getStatus(),
|
||||
'schema' => $schema,
|
||||
'extension' => $result,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering An optional ordering field.
|
||||
* @param string $direction An optional direction (asc|desc).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function populateState($ordering = 'name', $direction = 'asc')
|
||||
{
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes database problems.
|
||||
*
|
||||
* @param array $cids List of the selected extensions to fix
|
||||
*
|
||||
* @return void|boolean
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function fix($cids = [])
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
foreach ($cids as $i => $cid) {
|
||||
// Load the database issues
|
||||
$this->fetchSchemaCache($cid);
|
||||
|
||||
$changeSet = $this->changeSetList[$cid];
|
||||
$changeSet['changeset'] = new ChangeSet($db, $changeSet['folderTmp']);
|
||||
$changeSet['changeset']->fix();
|
||||
|
||||
$this->fixSchemaVersion($changeSet['changeset'], $changeSet['extension']->extension_id);
|
||||
$this->fixUpdateVersion($changeSet['extension']->extension_id);
|
||||
|
||||
if ($changeSet['extension']->element === 'com_admin') {
|
||||
$installer = new \JoomlaInstallerScript();
|
||||
$installer->deleteUnexistingFiles();
|
||||
$this->fixDefaultTextFilters();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the changeset array.
|
||||
*
|
||||
* @return array Array with the information of the versions problems, errors and the extensions itself
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getItems()
|
||||
{
|
||||
$this->fetchSchemaCache();
|
||||
|
||||
$results = parent::getItems();
|
||||
$results = $this->mergeSchemaCache($results);
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database query
|
||||
*
|
||||
* @return QueryInterface The database query
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getListQuery()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select(
|
||||
$db->quoteName(
|
||||
[
|
||||
'extensions.client_id',
|
||||
'extensions.element',
|
||||
'extensions.extension_id',
|
||||
'extensions.folder',
|
||||
'extensions.manifest_cache',
|
||||
'extensions.name',
|
||||
'extensions.type',
|
||||
'schemas.version_id',
|
||||
]
|
||||
)
|
||||
)
|
||||
->from(
|
||||
$db->quoteName(
|
||||
'#__schemas',
|
||||
'schemas'
|
||||
)
|
||||
)
|
||||
->join(
|
||||
'INNER',
|
||||
$db->quoteName('#__extensions', 'extensions'),
|
||||
$db->quoteName('schemas.extension_id') . ' = ' . $db->quoteName('extensions.extension_id')
|
||||
);
|
||||
|
||||
$type = $this->getState('filter.type');
|
||||
$clientId = $this->getState('filter.client_id');
|
||||
$extensionId = $this->getState('filter.extension_id');
|
||||
$folder = $this->getState('filter.folder');
|
||||
|
||||
if ($type) {
|
||||
$query->where($db->quoteName('extensions.type') . ' = :type')
|
||||
->bind(':type', $type);
|
||||
}
|
||||
|
||||
if ($clientId != '') {
|
||||
$clientId = (int) $clientId;
|
||||
$query->where($db->quoteName('extensions.client_id') . ' = :clientid')
|
||||
->bind(':clientid', $clientId, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
if ($extensionId != '') {
|
||||
$extensionId = (int) $extensionId;
|
||||
$query->where($db->quoteName('extensions.extension_id') . ' = :extensionid')
|
||||
->bind(':extensionid', $extensionId, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
if ($folder != '' && \in_array($type, ['plugin', 'library', ''])) {
|
||||
$folder = $folder === '*' ? '' : $folder;
|
||||
$query->where($db->quoteName('extensions.folder') . ' = :folder')
|
||||
->bind(':folder', $folder);
|
||||
}
|
||||
|
||||
// Process search filter (update site id).
|
||||
$search = $this->getState('filter.search');
|
||||
|
||||
if (!empty($search) && stripos($search, 'id:') === 0) {
|
||||
$ids = (int) substr($search, 3);
|
||||
$query->where($db->quoteName('schemas.extension_id') . ' = :eid')
|
||||
->bind(':eid', $ids, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the items that will be visible with the changeSet information in cache
|
||||
*
|
||||
* @param array $results extensions returned from parent::getItems().
|
||||
*
|
||||
* @return array the changeSetList of the merged items
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function mergeSchemaCache($results)
|
||||
{
|
||||
$changeSetList = $this->changeSetList;
|
||||
$finalResults = [];
|
||||
|
||||
foreach ($results as $result) {
|
||||
if (\array_key_exists($result->extension_id, $changeSetList) && $changeSetList[$result->extension_id]) {
|
||||
$finalResults[] = $changeSetList[$result->extension_id];
|
||||
}
|
||||
}
|
||||
|
||||
return $finalResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get version from #__schemas table.
|
||||
*
|
||||
* @param integer $extensionId id of the extensions.
|
||||
*
|
||||
* @return mixed the return value from the query, or null if the query fails.
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getSchemaVersion($extensionId)
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$extensionId = (int) $extensionId;
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('version_id'))
|
||||
->from($db->quoteName('#__schemas'))
|
||||
->where($db->quoteName('extension_id') . ' = :extensionid')
|
||||
->bind(':extensionid', $extensionId, ParameterType::INTEGER);
|
||||
$db->setQuery($query);
|
||||
|
||||
return $db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix schema version if wrong.
|
||||
*
|
||||
* @param ChangeSet $changeSet Schema change set.
|
||||
* @param integer $extensionId ID of the extensions.
|
||||
*
|
||||
* @return mixed string schema version if success, false if fail.
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function fixSchemaVersion($changeSet, $extensionId)
|
||||
{
|
||||
// Get correct schema version -- last file in array.
|
||||
$schema = $changeSet->getSchema();
|
||||
|
||||
// Check value. If ok, don't do update.
|
||||
if ($schema == $this->getSchemaVersion($extensionId)) {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
// Delete old row.
|
||||
$extensionId = (int) $extensionId;
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__schemas'))
|
||||
->where($db->quoteName('extension_id') . ' = :extensionid')
|
||||
->bind(':extensionid', $extensionId, ParameterType::INTEGER);
|
||||
$db->setQuery($query)->execute();
|
||||
|
||||
// Add new row.
|
||||
$query->clear()
|
||||
->insert($db->quoteName('#__schemas'))
|
||||
->columns($db->quoteName('extension_id') . ',' . $db->quoteName('version_id'))
|
||||
->values(':extensionid, :schema')
|
||||
->bind(':extensionid', $extensionId, ParameterType::INTEGER)
|
||||
->bind(':schema', $schema);
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$db->execute();
|
||||
} catch (ExecutionFailureException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current version from #__extensions table.
|
||||
*
|
||||
* @param object $extension data from #__extensions of a single extension.
|
||||
*
|
||||
* @return mixed string message with the errors with the update version or null if none
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function compareUpdateVersion($extension)
|
||||
{
|
||||
$updateVersion = json_decode($extension->manifest_cache)->version;
|
||||
|
||||
if ($extension->element === 'com_admin') {
|
||||
$extensionVersion = JVERSION;
|
||||
} else {
|
||||
$installationXML = InstallerHelper::getInstallationXML(
|
||||
$extension->element,
|
||||
$extension->type,
|
||||
$extension->client_id,
|
||||
$extension->type === 'plugin' ? $extension->folder : null
|
||||
);
|
||||
|
||||
$extensionVersion = (string) $installationXML->version;
|
||||
}
|
||||
|
||||
if (version_compare($extensionVersion, $updateVersion) != 0) {
|
||||
return Text::sprintf('COM_INSTALLER_MSG_DATABASE_UPDATEVERSION_ERROR', $updateVersion, $extension->name, $extensionVersion);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a message of the tables skipped and checked
|
||||
*
|
||||
* @param array $status status of the update files
|
||||
*
|
||||
* @return array Messages with the errors with the update version
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function getOtherInformationMessage($status)
|
||||
{
|
||||
$problemsMessage = [];
|
||||
$problemsMessage[] = Text::sprintf('COM_INSTALLER_MSG_DATABASE_CHECKED_OK', \count($status['ok']));
|
||||
$problemsMessage[] = Text::sprintf('COM_INSTALLER_MSG_DATABASE_SKIPPED', \count($status['skipped']));
|
||||
|
||||
return $problemsMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a message with all errors found in a given extension
|
||||
*
|
||||
* @param array $errors data from #__extensions of a single extension.
|
||||
*
|
||||
* @return array List of messages with the errors in the database
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function getErrorsMessage($errors)
|
||||
{
|
||||
$errorMessages = [];
|
||||
|
||||
foreach ($errors as $line => $error) {
|
||||
$key = 'COM_INSTALLER_MSG_DATABASE_' . $error->queryType;
|
||||
$messages = $error->msgElements;
|
||||
$file = basename($error->file);
|
||||
$message0 = $messages[0] ?? ' ';
|
||||
$message1 = $messages[1] ?? ' ';
|
||||
$message2 = $messages[2] ?? ' ';
|
||||
$errorMessages[] = Text::sprintf($key, $file, $message0, $message1, $message2);
|
||||
}
|
||||
|
||||
return $errorMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix Joomla version in #__extensions table if wrong (doesn't equal \JVersion short version).
|
||||
*
|
||||
* @param integer $extensionId id of the extension
|
||||
*
|
||||
* @return mixed string update version if success, false if fail.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function fixUpdateVersion($extensionId)
|
||||
{
|
||||
$table = new Extension($this->getDatabase());
|
||||
$table->load($extensionId);
|
||||
$cache = new Registry($table->manifest_cache);
|
||||
$updateVersion = $cache->get('version');
|
||||
|
||||
if ($table->type === 'file' && $table->element === 'joomla') {
|
||||
$extensionVersion = new Version();
|
||||
$extensionVersion = $extensionVersion->getShortVersion();
|
||||
} else {
|
||||
$installationXML = InstallerHelper::getInstallationXML(
|
||||
$table->element,
|
||||
$table->type,
|
||||
$table->client_id,
|
||||
$table->type === 'plugin' ? $table->folder : null
|
||||
);
|
||||
$extensionVersion = (string) $installationXML->version;
|
||||
}
|
||||
|
||||
if ($updateVersion === $extensionVersion) {
|
||||
return $updateVersion;
|
||||
}
|
||||
|
||||
$cache->set('version', $extensionVersion);
|
||||
$table->manifest_cache = $cache->toString();
|
||||
|
||||
if ($table->store()) {
|
||||
return $extensionVersion;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* For version 2.5.x only
|
||||
* Check if com_config parameters are blank.
|
||||
*
|
||||
* @return string default text filters (if any).
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getDefaultTextFilters()
|
||||
{
|
||||
$table = new Extension($this->getDatabase());
|
||||
$table->load($table->find(['name' => 'com_config']));
|
||||
|
||||
return $table->params;
|
||||
}
|
||||
|
||||
/**
|
||||
* For version 2.5.x only
|
||||
* Check if com_config parameters are blank. If so, populate with com_content text filters.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function fixDefaultTextFilters()
|
||||
{
|
||||
$table = new Extension($this->getDatabase());
|
||||
$table->load($table->find(['name' => 'com_config']));
|
||||
|
||||
// Check for empty $config and non-empty content filters.
|
||||
if (!$table->params) {
|
||||
// Get filters from com_content and store if you find them.
|
||||
$contentParams = ComponentHelper::getComponent('com_content')->getParams();
|
||||
|
||||
if ($contentParams->get('filters')) {
|
||||
$newParams = new Registry();
|
||||
$newParams->set('filters', $contentParams->get('filters'));
|
||||
$table->params = (string) $newParams;
|
||||
$table->store();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,309 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Installer\Installer;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\Database\Exception\ExecutionFailureException;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Database\QueryInterface;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer Discover Model
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class DiscoverModel extends InstallerModel
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
*
|
||||
* @see \Joomla\CMS\MVC\Model\ListModel
|
||||
* @since 1.6
|
||||
*/
|
||||
public function __construct($config = [], ?MVCFactoryInterface $factory = null)
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'name',
|
||||
'client_id',
|
||||
'client', 'client_translated',
|
||||
'type', 'type_translated',
|
||||
'folder', 'folder_translated',
|
||||
'extension_id',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering An optional ordering field.
|
||||
* @param string $direction An optional direction (asc|desc).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
protected function populateState($ordering = 'name', $direction = 'asc')
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
|
||||
$this->setState('message', $app->getUserState('com_installer.message'));
|
||||
$this->setState('extension_message', $app->getUserState('com_installer.extension_message'));
|
||||
|
||||
$app->setUserState('com_installer.message', '');
|
||||
$app->setUserState('com_installer.extension_message', '');
|
||||
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database query.
|
||||
*
|
||||
* @return QueryInterface The database query
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
protected function getListQuery()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('state') . ' = -1');
|
||||
|
||||
// Process select filters.
|
||||
$type = $this->getState('filter.type');
|
||||
$clientId = $this->getState('filter.client_id');
|
||||
$folder = $this->getState('filter.folder');
|
||||
|
||||
if ($type) {
|
||||
$query->where($db->quoteName('type') . ' = :type')
|
||||
->bind(':type', $type);
|
||||
}
|
||||
|
||||
if ($clientId != '') {
|
||||
$clientId = (int) $clientId;
|
||||
$query->where($db->quoteName('client_id') . ' = :clientid')
|
||||
->bind(':clientid', $clientId, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
if ($folder != '' && \in_array($type, ['plugin', 'library', ''])) {
|
||||
$folder = $folder === '*' ? '' : $folder;
|
||||
$query->where($db->quoteName('folder') . ' = :folder')
|
||||
->bind(':folder', $folder);
|
||||
}
|
||||
|
||||
// Process search filter.
|
||||
$search = $this->getState('filter.search');
|
||||
|
||||
if (!empty($search)) {
|
||||
if (stripos($search, 'id:') === 0) {
|
||||
$ids = (int) substr($search, 3);
|
||||
$query->where($db->quoteName('extension_id') . ' = :eid')
|
||||
->bind(':eid', $ids, ParameterType::INTEGER);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: The search for name, ordering and pagination are processed by the parent InstallerModel class (in extension.php).
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover extensions.
|
||||
*
|
||||
* Finds uninstalled extensions
|
||||
*
|
||||
* @return int The count of discovered extensions
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function discover()
|
||||
{
|
||||
// Purge the list of discovered extensions and fetch them again.
|
||||
$this->purge();
|
||||
$results = Installer::getInstance()->discover();
|
||||
|
||||
// Get all templates, including discovered ones
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName(['extension_id', 'element', 'folder', 'client_id', 'type']))
|
||||
->from($db->quoteName('#__extensions'));
|
||||
$db->setQuery($query);
|
||||
$installedtmp = $db->loadObjectList();
|
||||
|
||||
$extensions = [];
|
||||
|
||||
foreach ($installedtmp as $install) {
|
||||
$key = implode(
|
||||
':',
|
||||
[
|
||||
$install->type,
|
||||
str_replace('\\', '/', $install->element),
|
||||
$install->folder,
|
||||
$install->client_id,
|
||||
]
|
||||
);
|
||||
$extensions[$key] = $install;
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
|
||||
foreach ($results as $result) {
|
||||
// Check if we have a match on the element
|
||||
$key = implode(
|
||||
':',
|
||||
[
|
||||
$result->type,
|
||||
str_replace('\\', '/', $result->element),
|
||||
$result->folder,
|
||||
$result->client_id,
|
||||
]
|
||||
);
|
||||
|
||||
if (!\array_key_exists($key, $extensions)) {
|
||||
// Put it into the table
|
||||
$result->check();
|
||||
$result->store();
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs a discovered extension.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function discover_install()
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
$input = $app->getInput();
|
||||
$eid = $input->get('cid', 0, 'array');
|
||||
|
||||
if (\is_array($eid) || $eid) {
|
||||
if (!\is_array($eid)) {
|
||||
$eid = [$eid];
|
||||
}
|
||||
|
||||
$eid = ArrayHelper::toInteger($eid);
|
||||
$failed = false;
|
||||
|
||||
foreach ($eid as $id) {
|
||||
$installer = new Installer();
|
||||
$installer->setDatabase($this->getDatabase());
|
||||
|
||||
$result = $installer->discover_install($id);
|
||||
|
||||
if (!$result) {
|
||||
$failed = true;
|
||||
$app->enqueueMessage(Text::_('COM_INSTALLER_MSG_DISCOVER_INSTALLFAILED') . ': ' . $id);
|
||||
}
|
||||
}
|
||||
|
||||
// @todo - We are only receiving the message for the last Installer instance
|
||||
$this->setState('action', 'remove');
|
||||
$this->setState('name', $installer->get('name'));
|
||||
$app->setUserState('com_installer.message', $installer->message);
|
||||
$app->setUserState('com_installer.extension_message', $installer->get('extension_message'));
|
||||
|
||||
if (!$failed) {
|
||||
$app->enqueueMessage(Text::_('COM_INSTALLER_MSG_DISCOVER_INSTALLSUCCESSFUL'), 'success');
|
||||
}
|
||||
} else {
|
||||
$app->enqueueMessage(Text::_('COM_INSTALLER_MSG_DISCOVER_NOEXTENSIONSELECTED'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans out the list of discovered extensions.
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function purge()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('state') . ' = -1');
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$db->execute();
|
||||
} catch (ExecutionFailureException $e) {
|
||||
$this->_message = Text::_('COM_INSTALLER_MSG_DISCOVER_FAILEDTOPURGEEXTENSIONS');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->_message = Text::_('COM_INSTALLER_MSG_DISCOVER_PURGEDDISCOVEREDEXTENSIONS');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manipulate the query to be used to evaluate if this is an Empty State to provide specific conditions for this extension.
|
||||
*
|
||||
* @return QueryInterface
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getEmptyStateQuery()
|
||||
{
|
||||
$query = parent::getEmptyStateQuery();
|
||||
|
||||
$query->where($this->getDatabase()->quoteName('state') . ' = -1');
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for not installed extensions in extensions table.
|
||||
*
|
||||
* @return boolean True if there are discovered extensions in the database.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public function checkExtensions()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('state') . ' = -1');
|
||||
$db->setQuery($query);
|
||||
$discoveredExtensions = $db->loadObjectList();
|
||||
|
||||
return \count($discoveredExtensions) > 0;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,443 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Event\Installer\AfterInstallerEvent;
|
||||
use Joomla\CMS\Event\Installer\BeforeInstallationEvent;
|
||||
use Joomla\CMS\Event\Installer\BeforeInstallerEvent;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Installer\Installer;
|
||||
use Joomla\CMS\Installer\InstallerHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Updater\Update;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
use Joomla\Filesystem\Exception\FilesystemException;
|
||||
use Joomla\Filesystem\File;
|
||||
use Joomla\Filesystem\Path;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Extension Manager Install Model
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class InstallModel extends BaseDatabaseModel
|
||||
{
|
||||
/**
|
||||
* @var \Joomla\CMS\Table\Table Table object
|
||||
*/
|
||||
protected $_table = null;
|
||||
|
||||
/**
|
||||
* @var string URL
|
||||
*/
|
||||
protected $_url = null;
|
||||
|
||||
/**
|
||||
* Model context string.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_context = 'com_installer.install';
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function populateState()
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
|
||||
$this->setState('message', $app->getUserState('com_installer.message'));
|
||||
$this->setState('extension_message', $app->getUserState('com_installer.extension_message'));
|
||||
$app->setUserState('com_installer.message', '');
|
||||
$app->setUserState('com_installer.extension_message', '');
|
||||
|
||||
parent::populateState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Install an extension from either folder, URL or upload.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
$this->setState('action', 'install');
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$dispatcher = $this->getDispatcher();
|
||||
|
||||
// Load installer plugins for assistance if required:
|
||||
PluginHelper::importPlugin('installer', null, true, $dispatcher);
|
||||
|
||||
$package = null;
|
||||
|
||||
// This event allows an input pre-treatment, a custom pre-packing or custom installation.
|
||||
// (e.g. from a \JSON description).
|
||||
$eventBefore = new BeforeInstallationEvent('onInstallerBeforeInstallation', [
|
||||
'subject' => $this,
|
||||
'package' => &$package, // @todo: Remove reference in Joomla 6, see InstallerEvent::__constructor()
|
||||
]);
|
||||
$results = $dispatcher->dispatch('onInstallerBeforeInstallation', $eventBefore)->getArgument('result', []);
|
||||
$package = $eventBefore->getPackage();
|
||||
|
||||
if (\in_array(true, $results, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (\in_array(false, $results, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$installType = $app->getInput()->getWord('installtype');
|
||||
$installLang = $app->getInput()->getWord('package');
|
||||
|
||||
if ($package === null) {
|
||||
switch ($installType) {
|
||||
case 'folder':
|
||||
// Remember the 'Install from Directory' path.
|
||||
$app->getUserStateFromRequest($this->_context . '.install_directory', 'install_directory');
|
||||
$package = $this->_getPackageFromFolder();
|
||||
break;
|
||||
|
||||
case 'upload':
|
||||
$package = $this->_getPackageFromUpload();
|
||||
break;
|
||||
|
||||
case 'url':
|
||||
$package = $this->_getPackageFromUrl();
|
||||
break;
|
||||
|
||||
default:
|
||||
$app->setUserState('com_installer.message', Text::_('COM_INSTALLER_NO_INSTALL_TYPE_FOUND'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// No one of installType was able to resolve $package. Nothing to Install.
|
||||
if (!$package) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This event allows a custom installation of the package or a customization of the package:
|
||||
$eventBeforeInst = new BeforeInstallerEvent('onInstallerBeforeInstaller', [
|
||||
'subject' => $this,
|
||||
'package' => &$package, // @todo: Remove reference in Joomla 6, see InstallerEvent::__constructor()
|
||||
]);
|
||||
$results = $dispatcher->dispatch('onInstallerBeforeInstaller', $eventBeforeInst)->getArgument('result', []);
|
||||
$package = $eventBeforeInst->getPackage();
|
||||
|
||||
if (\in_array(true, $results, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (\in_array(false, $results, true)) {
|
||||
if (\in_array($installType, ['upload', 'url'])) {
|
||||
InstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if package was uploaded successfully.
|
||||
if (!\is_array($package)) {
|
||||
$app->enqueueMessage(Text::_('COM_INSTALLER_UNABLE_TO_FIND_INSTALL_PACKAGE'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get an installer instance.
|
||||
$installer = Installer::getInstance();
|
||||
|
||||
/*
|
||||
* Check for a Joomla core package.
|
||||
* To do this we need to set the source path to find the manifest (the same first step as Installer::install())
|
||||
*
|
||||
* This must be done before the unpacked check because InstallerHelper::detectType() returns a boolean false since the manifest
|
||||
* can't be found in the expected location.
|
||||
*/
|
||||
if (isset($package['dir']) && is_dir($package['dir'])) {
|
||||
$installer->setPath('source', $package['dir']);
|
||||
|
||||
if (!$installer->findManifest()) {
|
||||
// If a manifest isn't found at the source, this may be a Joomla package; check the package directory for the Joomla manifest
|
||||
if (file_exists($package['dir'] . '/administrator/manifests/files/joomla.xml')) {
|
||||
// We have a Joomla package
|
||||
if (\in_array($installType, ['upload', 'url'])) {
|
||||
InstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);
|
||||
}
|
||||
|
||||
$app->enqueueMessage(
|
||||
Text::sprintf('COM_INSTALLER_UNABLE_TO_INSTALL_JOOMLA_PACKAGE', Route::_('index.php?option=com_joomlaupdate')),
|
||||
'warning'
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Was the package unpacked?
|
||||
if (empty($package['type'])) {
|
||||
if (\in_array($installType, ['upload', 'url'])) {
|
||||
InstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);
|
||||
}
|
||||
|
||||
$app->enqueueMessage(Text::_('JLIB_INSTALLER_ABORT_DETECTMANIFEST'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Install the package.
|
||||
if (!$installer->install($package['dir'])) {
|
||||
// There was an error installing the package.
|
||||
$msg = Text::sprintf('COM_INSTALLER_INSTALL_ERROR', Text::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($package['type'])));
|
||||
$result = false;
|
||||
$msgType = 'error';
|
||||
} else {
|
||||
// Package installed successfully.
|
||||
$msg = Text::sprintf('COM_INSTALLER_INSTALL_SUCCESS', Text::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($installLang . $package['type'])));
|
||||
$result = true;
|
||||
$msgType = 'message';
|
||||
}
|
||||
|
||||
// This event allows a custom a post-flight:
|
||||
$eventAfterInst = new AfterInstallerEvent('onInstallerAfterInstaller', [
|
||||
'subject' => $this,
|
||||
'package' => &$package, // @todo: Remove reference in Joomla 6, see InstallerEvent::__constructor()
|
||||
'installer' => $installer,
|
||||
'installerResult' => &$result, // @todo: Remove reference in Joomla 6, see AfterInstallerEvent::__constructor()
|
||||
'message' => &$msg, // @todo: Remove reference in Joomla 6, see AfterInstallerEvent::__constructor()
|
||||
]);
|
||||
$dispatcher->dispatch('onInstallerAfterInstaller', $eventAfterInst);
|
||||
$package = $eventAfterInst->getPackage();
|
||||
$result = $eventAfterInst->getInstallerResult();
|
||||
$msg = $eventAfterInst->getMessage();
|
||||
|
||||
// Set some model state values.
|
||||
$app->enqueueMessage($msg, $msgType);
|
||||
$this->setState('name', $installer->get('name'));
|
||||
$this->setState('result', $result);
|
||||
$app->setUserState('com_installer.message', $installer->message);
|
||||
$app->setUserState('com_installer.extension_message', $installer->get('extension_message'));
|
||||
$app->setUserState('com_installer.redirect_url', $installer->get('redirect_url'));
|
||||
|
||||
// Cleanup the install files.
|
||||
if (!is_file($package['packagefile'])) {
|
||||
$package['packagefile'] = $app->get('tmp_path') . '/' . $package['packagefile'];
|
||||
}
|
||||
|
||||
InstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);
|
||||
|
||||
// Clear the cached extension data and menu cache
|
||||
$this->cleanCache('_system');
|
||||
$this->cleanCache('com_modules');
|
||||
$this->cleanCache('com_plugins');
|
||||
$this->cleanCache('mod_menu');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Works out an installation package from a HTTP upload.
|
||||
*
|
||||
* @return mixed Package definition or false on failure.
|
||||
*/
|
||||
protected function _getPackageFromUpload()
|
||||
{
|
||||
// Get the uploaded file information.
|
||||
$input = Factory::getApplication()->getInput();
|
||||
|
||||
// Do not change the filter type 'raw'. We need this to let files containing PHP code to upload. See \JInputFiles::get.
|
||||
$userfile = $input->files->get('install_package', null, 'raw');
|
||||
|
||||
// Make sure that file uploads are enabled in php.
|
||||
if (!(bool) \ini_get('file_uploads')) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLFILE'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure that zlib is loaded so that the package can be unpacked.
|
||||
if (!\extension_loaded('zlib')) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLZLIB'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there is no uploaded file, we have a problem...
|
||||
if (!\is_array($userfile)) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_NO_FILE_SELECTED'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the PHP tmp directory missing?
|
||||
if ($userfile['error'] && ($userfile['error'] == UPLOAD_ERR_NO_TMP_DIR)) {
|
||||
Factory::getApplication()->enqueueMessage(
|
||||
Text::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR') . '<br>' . Text::_('COM_INSTALLER_MSG_WARNINGS_PHPUPLOADNOTSET'),
|
||||
'error'
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the max upload size too small in php.ini?
|
||||
if ($userfile['error'] && ($userfile['error'] == UPLOAD_ERR_INI_SIZE)) {
|
||||
Factory::getApplication()->enqueueMessage(
|
||||
Text::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR') . '<br>' . Text::_('COM_INSTALLER_MSG_WARNINGS_SMALLUPLOADSIZE'),
|
||||
'error'
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if there was a different problem uploading the file.
|
||||
if ($userfile['error'] || $userfile['size'] < 1) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Build the appropriate paths.
|
||||
$config = Factory::getApplication()->getConfig();
|
||||
$tmp_dest = $config->get('tmp_path') . '/' . $userfile['name'];
|
||||
$tmp_src = $userfile['tmp_name'];
|
||||
|
||||
// Move uploaded file.
|
||||
try {
|
||||
File::upload($tmp_src, $tmp_dest, false, true);
|
||||
} catch (FilesystemException $exception) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLUPLOADERROR'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unpack the downloaded package file.
|
||||
$package = InstallerHelper::unpack($tmp_dest, true);
|
||||
|
||||
return $package;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install an extension from a directory
|
||||
*
|
||||
* @return array Package details or false on failure
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected function _getPackageFromFolder()
|
||||
{
|
||||
$input = Factory::getApplication()->getInput();
|
||||
|
||||
// Get the path to the package to install.
|
||||
$p_dir = $input->getString('install_directory');
|
||||
$p_dir = Path::clean($p_dir);
|
||||
|
||||
// Did you give us a valid directory?
|
||||
if (!is_dir($p_dir)) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_PLEASE_ENTER_A_PACKAGE_DIRECTORY'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Detect the package type
|
||||
$type = InstallerHelper::detectType($p_dir);
|
||||
|
||||
// Did you give us a valid package?
|
||||
if (!$type) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_PATH_DOES_NOT_HAVE_A_VALID_PACKAGE'), 'error');
|
||||
}
|
||||
|
||||
$package['packagefile'] = null;
|
||||
$package['extractdir'] = null;
|
||||
$package['dir'] = $p_dir;
|
||||
$package['type'] = $type;
|
||||
|
||||
return $package;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install an extension from a URL.
|
||||
*
|
||||
* @return bool|array Package details or false on failure.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
protected function _getPackageFromUrl()
|
||||
{
|
||||
$input = Factory::getApplication()->getInput();
|
||||
|
||||
// Get the URL of the package to install.
|
||||
$url = $input->getString('install_url');
|
||||
|
||||
// Did you give us a URL?
|
||||
if (!$url) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_ENTER_A_URL'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// We only allow http & https here
|
||||
$uri = new Uri($url);
|
||||
|
||||
if (!\in_array($uri->getScheme(), ['http', 'https'])) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_INVALID_URL_SCHEME'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle updater XML file case:
|
||||
if (preg_match('/\.xml\s*$/', $url)) {
|
||||
$update = new Update();
|
||||
$update->loadFromXml($url);
|
||||
$package_url = trim($update->get('downloadurl', false)->_data);
|
||||
|
||||
if ($package_url) {
|
||||
$url = $package_url;
|
||||
}
|
||||
|
||||
unset($update);
|
||||
}
|
||||
|
||||
// Download the package at the URL given.
|
||||
$p_file = InstallerHelper::downloadPackage($url);
|
||||
|
||||
// Was the package downloaded?
|
||||
if (!$p_file) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_INVALID_URL'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$tmp_dest = Factory::getApplication()->get('tmp_path');
|
||||
|
||||
// Unpack the downloaded package file.
|
||||
$package = InstallerHelper::unpack($tmp_dest . '/' . $p_file, true);
|
||||
|
||||
return $package;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\Database\DatabaseQuery;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Extension Manager Abstract Extension Model.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class InstallerModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
*
|
||||
* @see \Joomla\CMS\MVC\Model\ListModel
|
||||
* @since 1.6
|
||||
*/
|
||||
public function __construct($config = [], ?MVCFactoryInterface $factory = null)
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'name',
|
||||
'client_id',
|
||||
'client', 'client_translated',
|
||||
'enabled',
|
||||
'type', 'type_translated',
|
||||
'folder', 'folder_translated',
|
||||
'extension_id',
|
||||
'creationDate',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object list
|
||||
*
|
||||
* @param DatabaseQuery $query The query
|
||||
* @param int $limitstart Offset
|
||||
* @param int $limit The number of records
|
||||
*
|
||||
* @return object[]
|
||||
*/
|
||||
protected function _getList($query, $limitstart = 0, $limit = 0)
|
||||
{
|
||||
$listOrder = $this->getState('list.ordering', 'name');
|
||||
$listDirn = $this->getState('list.direction', 'asc');
|
||||
|
||||
// Replace slashes so preg_match will work
|
||||
$search = $this->getState('filter.search', '');
|
||||
$search = str_replace('/', ' ', $search);
|
||||
$db = $this->getDatabase();
|
||||
|
||||
// Define which fields have to be processed in a custom way because of translation.
|
||||
$customOrderFields = ['name', 'client_translated', 'type_translated', 'folder_translated', 'creationDate'];
|
||||
|
||||
// Process searching, ordering and pagination for fields that need to be translated.
|
||||
if (\in_array($listOrder, $customOrderFields) || (!empty($search) && stripos($search, 'id:') !== 0)) {
|
||||
// Get results from database and translate them.
|
||||
$db->setQuery($query);
|
||||
$result = $db->loadObjectList();
|
||||
$this->translate($result);
|
||||
|
||||
// Process searching.
|
||||
if (!empty($search) && stripos($search, 'id:') !== 0) {
|
||||
$escapedSearchString = $this->refineSearchStringToRegex($search, '/');
|
||||
|
||||
// By default search only the extension name field.
|
||||
$searchFields = ['name'];
|
||||
|
||||
// If in update sites view search also in the update site name field.
|
||||
if ($this instanceof UpdatesitesModel) {
|
||||
$searchFields[] = 'update_site_name';
|
||||
}
|
||||
|
||||
foreach ($result as $i => $item) {
|
||||
// Check if search string exists in any of the fields to be searched.
|
||||
$found = 0;
|
||||
|
||||
foreach ($searchFields as $key => $field) {
|
||||
if (!$found && preg_match('/' . $escapedSearchString . '/i', $item->{$field})) {
|
||||
$found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If search string was not found in any of the fields searched remove it from results array.
|
||||
if (!$found) {
|
||||
unset($result[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process ordering.
|
||||
// Sort array object by selected ordering and selected direction. Sort is case insensitive and using locale sorting.
|
||||
$result = ArrayHelper::sortObjects($result, $listOrder, strtolower($listDirn) == 'desc' ? -1 : 1, false, true);
|
||||
|
||||
// Process pagination.
|
||||
$total = \count($result);
|
||||
$this->cache[$this->getStoreId('getTotal')] = $total;
|
||||
|
||||
if ($total <= $limitstart) {
|
||||
$limitstart = 0;
|
||||
$this->setState('list.limitstart', 0);
|
||||
}
|
||||
|
||||
return \array_slice($result, $limitstart, $limit ?: null);
|
||||
}
|
||||
|
||||
// Process searching, ordering and pagination for regular database fields.
|
||||
$query->order($db->quoteName($listOrder) . ' ' . $db->escape($listDirn));
|
||||
$result = parent::_getList($query, $limitstart, $limit);
|
||||
$this->translate($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a list of objects
|
||||
*
|
||||
* @param array $items The array of objects
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function translate(&$items)
|
||||
{
|
||||
$lang = Factory::getLanguage();
|
||||
|
||||
foreach ($items as &$item) {
|
||||
if (\strlen($item->manifest_cache) && $data = json_decode($item->manifest_cache)) {
|
||||
foreach ($data as $key => $value) {
|
||||
if ($key == 'type') {
|
||||
// Ignore the type field
|
||||
continue;
|
||||
}
|
||||
|
||||
$item->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$item->author_info = @$item->authorEmail . '<br>' . @$item->authorUrl;
|
||||
$item->client = Text::_([0 => 'JSITE', 1 => 'JADMINISTRATOR', 3 => 'JAPI'][$item->client_id] ?? 'JSITE');
|
||||
$item->client_translated = $item->client;
|
||||
$item->type_translated = Text::_('COM_INSTALLER_TYPE_' . strtoupper($item->type));
|
||||
$item->folder_translated = @$item->folder ? $item->folder : Text::_('COM_INSTALLER_TYPE_NONAPPLICABLE');
|
||||
|
||||
$path = $item->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE;
|
||||
|
||||
switch ($item->type) {
|
||||
case 'component':
|
||||
$extension = $item->element;
|
||||
$source = JPATH_ADMINISTRATOR . '/components/' . $extension;
|
||||
$lang->load("$extension.sys", JPATH_ADMINISTRATOR) || $lang->load("$extension.sys", $source);
|
||||
break;
|
||||
case 'file':
|
||||
$extension = 'files_' . $item->element;
|
||||
$lang->load("$extension.sys", JPATH_SITE);
|
||||
break;
|
||||
case 'library':
|
||||
$parts = explode('/', $item->element);
|
||||
$vendor = (isset($parts[1]) ? $parts[0] : null);
|
||||
$extension = 'lib_' . ($vendor ? implode('_', $parts) : $item->element);
|
||||
|
||||
if (!$lang->load("$extension.sys", $path)) {
|
||||
$source = $path . '/libraries/' . ($vendor ? $vendor . '/' . $parts[1] : $item->element);
|
||||
$lang->load("$extension.sys", $source);
|
||||
}
|
||||
break;
|
||||
case 'module':
|
||||
$extension = $item->element;
|
||||
$source = $path . '/modules/' . $extension;
|
||||
$lang->load("$extension.sys", $path) || $lang->load("$extension.sys", $source);
|
||||
break;
|
||||
case 'plugin':
|
||||
$extension = 'plg_' . $item->folder . '_' . $item->element;
|
||||
$source = JPATH_PLUGINS . '/' . $item->folder . '/' . $item->element;
|
||||
$lang->load("$extension.sys", JPATH_ADMINISTRATOR) || $lang->load("$extension.sys", $source);
|
||||
break;
|
||||
case 'template':
|
||||
$extension = 'tpl_' . $item->element;
|
||||
$source = $path . '/templates/' . $item->element;
|
||||
$lang->load("$extension.sys", $path) || $lang->load("$extension.sys", $source);
|
||||
break;
|
||||
case 'package':
|
||||
default:
|
||||
$extension = $item->element;
|
||||
$lang->load("$extension.sys", JPATH_SITE);
|
||||
break;
|
||||
}
|
||||
|
||||
// Translate the extension name if possible
|
||||
$item->name = Text::_($item->name);
|
||||
|
||||
settype($item->description, 'string');
|
||||
|
||||
if (!\in_array($item->type, ['language'])) {
|
||||
$item->description = Text::_($item->description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,267 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Http\HttpFactory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\String\StringHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Languages Installer Model
|
||||
*
|
||||
* @since 2.5.7
|
||||
*/
|
||||
class LanguagesModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* Language count
|
||||
*
|
||||
* @var integer
|
||||
* @since 3.7.0
|
||||
*/
|
||||
private $languageCount;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
*
|
||||
* @see \Joomla\CMS\MVC\Model\ListModel
|
||||
* @since 1.6
|
||||
*/
|
||||
public function __construct($config = [], ?MVCFactoryInterface $factory = null)
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'name',
|
||||
'element',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Update Site
|
||||
*
|
||||
* @since 3.7.0
|
||||
*
|
||||
* @return string The URL of the Accredited Languagepack Updatesite XML
|
||||
*/
|
||||
private function getUpdateSite()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('us.location'))
|
||||
->from($db->quoteName('#__extensions', 'e'))
|
||||
->where($db->quoteName('e.type') . ' = ' . $db->quote('package'))
|
||||
->where($db->quoteName('e.element') . ' = ' . $db->quote('pkg_en-GB'))
|
||||
->where($db->quoteName('e.client_id') . ' = 0')
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__update_sites_extensions', 'use')
|
||||
. ' ON ' . $db->quoteName('use.extension_id') . ' = ' . $db->quoteName('e.extension_id')
|
||||
)
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__update_sites', 'us')
|
||||
. ' ON ' . $db->quoteName('us.update_site_id') . ' = ' . $db->quoteName('use.update_site_id')
|
||||
);
|
||||
|
||||
return $db->setQuery($query)->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get an array of data items.
|
||||
*
|
||||
* @return mixed An array of data items on success, false on failure.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public function getItems()
|
||||
{
|
||||
// Get a storage key.
|
||||
$store = $this->getStoreId();
|
||||
|
||||
// Try to load the data from internal storage.
|
||||
if (isset($this->cache[$store])) {
|
||||
return $this->cache[$store];
|
||||
}
|
||||
|
||||
try {
|
||||
// Load the list items and add the items to the internal cache.
|
||||
$this->cache[$store] = $this->getLanguages();
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->setError($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->cache[$store];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of objects from the updatesite.
|
||||
*
|
||||
* @return object[] An array of results.
|
||||
*
|
||||
* @since 3.0
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function getLanguages()
|
||||
{
|
||||
$updateSite = $this->getUpdateSite();
|
||||
|
||||
// Check whether the updateserver is found
|
||||
if (empty($updateSite)) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_WARNING_NO_LANGUAGES_UPDATESERVER'), 'warning');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$response = HttpFactory::getHttp()->get($updateSite);
|
||||
} catch (\RuntimeException $e) {
|
||||
$response = null;
|
||||
}
|
||||
|
||||
if ($response === null || $response->code !== 200) {
|
||||
Factory::getApplication()->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_ERROR_CANT_CONNECT_TO_UPDATESERVER', $updateSite), 'error');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$updateSiteXML = simplexml_load_string($response->body);
|
||||
|
||||
if (!$updateSiteXML) {
|
||||
Factory::getApplication()->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_ERROR_CANT_RETRIEVE_XML', $updateSite), 'error');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$languages = [];
|
||||
$search = strtolower($this->getState('filter.search', ''));
|
||||
|
||||
foreach ($updateSiteXML->extension as $extension) {
|
||||
$language = new \stdClass();
|
||||
|
||||
foreach ($extension->attributes() as $key => $value) {
|
||||
$language->$key = (string) $value;
|
||||
}
|
||||
|
||||
if ($search) {
|
||||
if (
|
||||
strpos(strtolower($language->name), $search) === false
|
||||
&& strpos(strtolower($language->element), $search) === false
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$languages[$language->name] = $language;
|
||||
}
|
||||
|
||||
// Workaround for php 5.3
|
||||
$that = $this;
|
||||
|
||||
// Sort the array by value of subarray
|
||||
usort(
|
||||
$languages,
|
||||
function ($a, $b) use ($that) {
|
||||
$ordering = $that->getState('list.ordering', 'name');
|
||||
|
||||
if (strtolower($that->getState('list.direction', 'asc')) === 'asc') {
|
||||
return StringHelper::strcmp($a->$ordering, $b->$ordering);
|
||||
}
|
||||
|
||||
return StringHelper::strcmp($b->$ordering, $a->$ordering);
|
||||
}
|
||||
);
|
||||
|
||||
// Count the non-paginated list
|
||||
$this->languageCount = \count($languages);
|
||||
$limit = ($this->getState('list.limit', 20) > 0) ? $this->getState('list.limit', 20) : $this->languageCount;
|
||||
|
||||
return \array_slice($languages, $this->getStart() ?? 0, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a record count for the updatesite.
|
||||
*
|
||||
* @param \Joomla\Database\DatabaseQuery|string $query The query.
|
||||
*
|
||||
* @return integer Number of rows for query.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected function _getListCount($query)
|
||||
{
|
||||
return $this->languageCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a store id based on model configuration state.
|
||||
*
|
||||
* @param string $id A prefix for the store id.
|
||||
*
|
||||
* @return string A store id.
|
||||
*
|
||||
* @since 2.5.7
|
||||
*/
|
||||
protected function getStoreId($id = '')
|
||||
{
|
||||
// Compile the store id.
|
||||
$id .= ':' . $this->getState('filter.search');
|
||||
|
||||
return parent::getStoreId($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering list order
|
||||
* @param string $direction direction in the list
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5.7
|
||||
*/
|
||||
protected function populateState($ordering = 'name', $direction = 'asc')
|
||||
{
|
||||
$this->setState('extension_message', Factory::getApplication()->getUserState('com_installer.extension_message'));
|
||||
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to compare two languages in order to sort them.
|
||||
*
|
||||
* @param object $lang1 The first language.
|
||||
* @param object $lang2 The second language.
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected function compareLanguages($lang1, $lang2)
|
||||
{
|
||||
return strcmp($lang1->name, $lang2->name);
|
||||
}
|
||||
}
|
||||
457
administrator/components/com_installer/src/Model/ManageModel.php
Normal file
457
administrator/components/com_installer/src/Model/ManageModel.php
Normal file
@ -0,0 +1,457 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Changelog\Changelog;
|
||||
use Joomla\CMS\Event\Model\BeforeChangeStateEvent;
|
||||
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\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Table\Extension;
|
||||
use Joomla\Component\Templates\Administrator\Table\StyleTable;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Database\QueryInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer Manage Model
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class ManageModel extends InstallerModel
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
*
|
||||
* @see \Joomla\CMS\MVC\Model\ListModel
|
||||
* @since 1.6
|
||||
*/
|
||||
public function __construct($config = [], ?MVCFactoryInterface $factory = null)
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'status',
|
||||
'name',
|
||||
'client_id',
|
||||
'client', 'client_translated',
|
||||
'type', 'type_translated',
|
||||
'folder', 'folder_translated',
|
||||
'package_id',
|
||||
'extension_id',
|
||||
'creationDate',
|
||||
'core',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering An optional ordering field.
|
||||
* @param string $direction An optional direction (asc|desc).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function populateState($ordering = 'name', $direction = 'asc')
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
|
||||
$this->setState('message', $app->getUserState('com_installer.message'));
|
||||
$this->setState('extension_message', $app->getUserState('com_installer.extension_message'));
|
||||
$app->setUserState('com_installer.message', '');
|
||||
$app->setUserState('com_installer.extension_message', '');
|
||||
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable an extension.
|
||||
*
|
||||
* @param array $eid Extension ids to un/publish
|
||||
* @param int $value Publish value
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function publish(&$eid = [], $value = 1)
|
||||
{
|
||||
if (!$this->getCurrentUser()->authorise('core.edit.state', 'com_installer')) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = true;
|
||||
|
||||
/*
|
||||
* Ensure eid is an array of extension ids
|
||||
* @todo: If it isn't an array do we want to set an error and fail?
|
||||
*/
|
||||
if (!\is_array($eid)) {
|
||||
$eid = [$eid];
|
||||
}
|
||||
|
||||
// Get a table object for the extension type
|
||||
$table = new Extension($this->getDatabase());
|
||||
$context = $this->option . '.' . $this->name;
|
||||
$dispatcher = $this->getDispatcher();
|
||||
|
||||
PluginHelper::importPlugin('extension', null, true, $dispatcher);
|
||||
|
||||
// Enable the extension in the table and store it in the database
|
||||
foreach ($eid as $i => $id) {
|
||||
$table->load($id);
|
||||
|
||||
if ($table->type == 'template') {
|
||||
$style = new StyleTable($this->getDatabase());
|
||||
|
||||
if ($style->load(['template' => $table->element, 'client_id' => $table->client_id, 'home' => 1])) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_ERROR_DISABLE_DEFAULT_TEMPLATE_NOT_PERMITTED'), 'notice');
|
||||
unset($eid[$i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parent template cannot be disabled if there are children
|
||||
if ($style->load(['parent' => $table->element, 'client_id' => $table->client_id])) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_ERROR_DISABLE_PARENT_TEMPLATE_NOT_PERMITTED'), 'notice');
|
||||
unset($eid[$i]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($table->protected == 1) {
|
||||
$result = false;
|
||||
Factory::getApplication()->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 'error');
|
||||
} else {
|
||||
$table->enabled = $value;
|
||||
}
|
||||
|
||||
// Trigger the before change state event.
|
||||
$dispatcher->dispatch('onExtensionChangeState', new BeforeChangeStateEvent('onExtensionChangeState', [
|
||||
'context' => $context,
|
||||
'subject' => $eid,
|
||||
'value' => $value,
|
||||
]));
|
||||
|
||||
if (!$table->store()) {
|
||||
$this->setError($table->getError());
|
||||
$result = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the cached extension data and menu cache
|
||||
$this->cleanCache('_system');
|
||||
$this->cleanCache('com_modules');
|
||||
$this->cleanCache('mod_menu');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the cached manifest information for an extension.
|
||||
*
|
||||
* @param int|int[] $eid extension identifier (key in #__extensions)
|
||||
*
|
||||
* @return boolean result of refresh
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function refresh($eid)
|
||||
{
|
||||
if (!\is_array($eid)) {
|
||||
$eid = [$eid => 0];
|
||||
}
|
||||
|
||||
// Get an installer object for the extension type
|
||||
$installer = Installer::getInstance();
|
||||
$result = 0;
|
||||
|
||||
// Uninstall the chosen extensions
|
||||
foreach ($eid as $id) {
|
||||
$result |= $installer->refreshManifestCache($id);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove (uninstall) an extension
|
||||
*
|
||||
* @param array $eid An array of identifiers
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function remove($eid = [])
|
||||
{
|
||||
if (!$this->getCurrentUser()->authorise('core.delete', 'com_installer')) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('JERROR_CORE_DELETE_NOT_PERMITTED'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure eid is an array of extension ids in the form id => client_id
|
||||
* @todo: If it isn't an array do we want to set an error and fail?
|
||||
*/
|
||||
if (!\is_array($eid)) {
|
||||
$eid = [$eid => 0];
|
||||
}
|
||||
|
||||
// Get an installer object for the extension type
|
||||
$installer = Installer::getInstance();
|
||||
$row = new \Joomla\CMS\Table\Extension($this->getDatabase());
|
||||
|
||||
// Uninstall the chosen extensions
|
||||
$msgs = [];
|
||||
$result = false;
|
||||
|
||||
foreach ($eid as $id) {
|
||||
$id = trim($id);
|
||||
$row->load($id);
|
||||
$result = false;
|
||||
|
||||
// Do not allow to uninstall locked extensions.
|
||||
if ((int) $row->locked === 1) {
|
||||
$msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR_LOCKED_EXTENSION', $row->name, $id);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$langstring = 'COM_INSTALLER_TYPE_TYPE_' . strtoupper($row->type);
|
||||
$rowtype = Text::_($langstring);
|
||||
|
||||
if (strpos($rowtype, $langstring) !== false) {
|
||||
$rowtype = $row->type;
|
||||
}
|
||||
|
||||
if ($row->type) {
|
||||
$result = $installer->uninstall($row->type, $id);
|
||||
|
||||
// Build an array of extensions that failed to uninstall
|
||||
if ($result === false) {
|
||||
// There was an error in uninstalling the package
|
||||
$msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Package uninstalled successfully
|
||||
$msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_SUCCESS', $rowtype);
|
||||
$result = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// There was an error in uninstalling the package
|
||||
$msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype);
|
||||
}
|
||||
|
||||
$msg = implode('<br>', $msgs);
|
||||
$app = Factory::getApplication();
|
||||
$app->enqueueMessage($msg);
|
||||
$this->setState('action', 'remove');
|
||||
$this->setState('name', $installer->get('name'));
|
||||
$app->setUserState('com_installer.message', $installer->message);
|
||||
$app->setUserState('com_installer.extension_message', $installer->get('extension_message'));
|
||||
|
||||
// Clear the cached extension data and menu cache
|
||||
$this->cleanCache('_system');
|
||||
$this->cleanCache('com_modules');
|
||||
$this->cleanCache('com_plugins');
|
||||
$this->cleanCache('mod_menu');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database query
|
||||
*
|
||||
* @return QueryInterface The database query
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function getListQuery()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->select('2*protected+(1-protected)*enabled AS status')
|
||||
->from('#__extensions')
|
||||
->where('state = 0');
|
||||
|
||||
// Process select filters.
|
||||
$status = $this->getState('filter.status', '');
|
||||
$type = $this->getState('filter.type');
|
||||
$clientId = $this->getState('filter.client_id', '');
|
||||
$folder = $this->getState('filter.folder');
|
||||
$core = $this->getState('filter.core', '');
|
||||
$packageId = $this->getState('filter.package_id', '');
|
||||
|
||||
if ($status !== '') {
|
||||
if ($status === '2') {
|
||||
$query->where('protected = 1');
|
||||
} elseif ($status === '3') {
|
||||
$query->where('protected = 0');
|
||||
} else {
|
||||
$status = (int) $status;
|
||||
$query->where($db->quoteName('protected') . ' = 0')
|
||||
->where($db->quoteName('enabled') . ' = :status')
|
||||
->bind(':status', $status, ParameterType::INTEGER);
|
||||
}
|
||||
}
|
||||
|
||||
if ($type) {
|
||||
$query->where($db->quoteName('type') . ' = :type')
|
||||
->bind(':type', $type);
|
||||
}
|
||||
|
||||
if ($clientId !== '') {
|
||||
$clientId = (int) $clientId;
|
||||
$query->where($db->quoteName('client_id') . ' = :clientid')
|
||||
->bind(':clientid', $clientId, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
if ($packageId !== '') {
|
||||
$packageId = (int) $packageId;
|
||||
$query->where(
|
||||
'((' . $db->quoteName('package_id') . ' = :packageId1) OR '
|
||||
. '(' . $db->quoteName('extension_id') . ' = :packageId2))'
|
||||
)
|
||||
->bind([':packageId1',':packageId2'], $packageId, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
if ($folder) {
|
||||
$folder = $folder === '*' ? '' : $folder;
|
||||
$query->where($db->quoteName('folder') . ' = :folder')
|
||||
->bind(':folder', $folder);
|
||||
}
|
||||
|
||||
// Filter by core extensions.
|
||||
if ($core === '1' || $core === '0') {
|
||||
$coreExtensionIds = ExtensionHelper::getCoreExtensionIds();
|
||||
$method = $core === '1' ? 'whereIn' : 'whereNotIn';
|
||||
$query->$method($db->quoteName('extension_id'), $coreExtensionIds);
|
||||
}
|
||||
|
||||
// Process search filter (extension id).
|
||||
$search = $this->getState('filter.search');
|
||||
|
||||
if (!empty($search) && stripos($search, 'id:') === 0) {
|
||||
$ids = (int) substr($search, 3);
|
||||
$query->where($db->quoteName('extension_id') . ' = :eid')
|
||||
->bind(':eid', $ids, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
// Note: The search for name, ordering and pagination are processed by the parent InstallerModel class (in extension.php).
|
||||
|
||||
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 4.0.0
|
||||
*/
|
||||
public function loadChangelog($eid, $source)
|
||||
{
|
||||
// Get the changelog URL
|
||||
$eid = (int) $eid;
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select(
|
||||
$db->quoteName(
|
||||
[
|
||||
'extensions.element',
|
||||
'extensions.type',
|
||||
'extensions.folder',
|
||||
'extensions.changelogurl',
|
||||
'extensions.manifest_cache',
|
||||
'extensions.client_id',
|
||||
]
|
||||
)
|
||||
)
|
||||
->select($db->quoteName('updates.version', 'updateVersion'))
|
||||
->from($db->quoteName('#__extensions', 'extensions'))
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__updates', 'updates'),
|
||||
$db->quoteName('updates.extension_id') . ' = ' . $db->quoteName('extensions.extension_id')
|
||||
)
|
||||
->where($db->quoteName('extensions.extension_id') . ' = :eid')
|
||||
->bind(':eid', $eid, ParameterType::INTEGER);
|
||||
$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 = [
|
||||
'security' => [],
|
||||
'fix' => [],
|
||||
'addition' => [],
|
||||
'change' => [],
|
||||
'remove' => [],
|
||||
'language' => [],
|
||||
'note' => [],
|
||||
];
|
||||
|
||||
foreach (array_keys($entries) as $name) {
|
||||
$field = $changelog->get($name);
|
||||
if ($field) {
|
||||
$entries[$name] = $changelog->get($name)->data;
|
||||
}
|
||||
}
|
||||
|
||||
$layout = new FileLayout('joomla.installer.changelog');
|
||||
$output = $layout->render($entries);
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
639
administrator/components/com_installer/src/Model/UpdateModel.php
Normal file
639
administrator/components/com_installer/src/Model/UpdateModel.php
Normal file
@ -0,0 +1,639 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Extension\ExtensionHelper;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Installer\Installer;
|
||||
use Joomla\CMS\Installer\InstallerHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Updater\Update;
|
||||
use Joomla\CMS\Updater\Updater;
|
||||
use Joomla\Database\Exception\ExecutionFailureException;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Database\QueryInterface;
|
||||
use Joomla\Filesystem\Path;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer Update Model
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class UpdateModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
*
|
||||
* @see \Joomla\CMS\MVC\Model\ListModel
|
||||
* @since 1.6
|
||||
*/
|
||||
public function __construct($config = [], ?MVCFactoryInterface $factory = null)
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'name', 'u.name',
|
||||
'client_id', 'u.client_id', 'client_translated',
|
||||
'type', 'u.type', 'type_translated',
|
||||
'folder', 'u.folder', 'folder_translated',
|
||||
'extension_id', 'u.extension_id',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering An optional ordering field.
|
||||
* @param string $direction An optional direction (asc|desc).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function populateState($ordering = 'u.name', $direction = 'asc')
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
$this->setState('message', $app->getUserState('com_installer.message'));
|
||||
$this->setState('extension_message', $app->getUserState('com_installer.extension_message'));
|
||||
$app->setUserState('com_installer.message', '');
|
||||
$app->setUserState('com_installer.extension_message', '');
|
||||
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database query
|
||||
*
|
||||
* @return QueryInterface The database query
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function getListQuery()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
// Grab updates ignoring new installs
|
||||
$query = $db->getQuery(true)
|
||||
->select('u.*')
|
||||
->select($db->quoteName('e.manifest_cache'))
|
||||
->from($db->quoteName('#__updates', 'u'))
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__extensions', 'e'),
|
||||
$db->quoteName('e.extension_id') . ' = ' . $db->quoteName('u.extension_id')
|
||||
)
|
||||
->where($db->quoteName('u.extension_id') . ' != 0');
|
||||
|
||||
// Process select filters.
|
||||
$clientId = $this->getState('filter.client_id');
|
||||
$type = $this->getState('filter.type');
|
||||
$folder = $this->getState('filter.folder');
|
||||
$extensionId = $this->getState('filter.extension_id');
|
||||
|
||||
if ($type) {
|
||||
$query->where($db->quoteName('u.type') . ' = :type')
|
||||
->bind(':type', $type);
|
||||
}
|
||||
|
||||
if ($clientId != '') {
|
||||
$clientId = (int) $clientId;
|
||||
$query->where($db->quoteName('u.client_id') . ' = :clientid')
|
||||
->bind(':clientid', $clientId, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
if ($folder != '' && \in_array($type, ['plugin', 'library', ''])) {
|
||||
$folder = $folder === '*' ? '' : $folder;
|
||||
$query->where($db->quoteName('u.folder') . ' = :folder')
|
||||
->bind(':folder', $folder);
|
||||
}
|
||||
|
||||
if ($extensionId) {
|
||||
$extensionId = (int) $extensionId;
|
||||
$query->where($db->quoteName('u.extension_id') . ' = :extensionid')
|
||||
->bind(':extensionid', $extensionId, ParameterType::INTEGER);
|
||||
} else {
|
||||
$eid = ExtensionHelper::getExtensionRecord('joomla', 'file')->extension_id;
|
||||
$query->where($db->quoteName('u.extension_id') . ' != :eid')
|
||||
->bind(':eid', $eid, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
// Process search filter.
|
||||
$search = $this->getState('filter.search');
|
||||
|
||||
if (!empty($search)) {
|
||||
if (stripos($search, 'eid:') !== false) {
|
||||
$sid = (int) substr($search, 4);
|
||||
$query->where($db->quoteName('u.extension_id') . ' = :sid')
|
||||
->bind(':sid', $sid, ParameterType::INTEGER);
|
||||
} else {
|
||||
if (stripos($search, 'uid:') !== false) {
|
||||
$suid = (int) substr($search, 4);
|
||||
$query->where($db->quoteName('u.update_site_id') . ' = :suid')
|
||||
->bind(':suid', $suid, ParameterType::INTEGER);
|
||||
} elseif (stripos($search, 'id:') !== false) {
|
||||
$uid = (int) substr($search, 3);
|
||||
$query->where($db->quoteName('u.update_id') . ' = :uid')
|
||||
->bind(':uid', $uid, ParameterType::INTEGER);
|
||||
} else {
|
||||
$search = '%' . str_replace(' ', '%', trim($search)) . '%';
|
||||
$query->where($db->quoteName('u.name') . ' LIKE :search')
|
||||
->bind(':search', $search);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a list of objects
|
||||
*
|
||||
* @param array $items The array of objects
|
||||
*
|
||||
* @return array The array of translated objects
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
protected function translate(&$items)
|
||||
{
|
||||
foreach ($items as &$item) {
|
||||
$item->client_translated = Text::_([0 => 'JSITE', 1 => 'JADMINISTRATOR', 3 => 'JAPI'][$item->client_id] ?? 'JSITE');
|
||||
$manifest = json_decode($item->manifest_cache);
|
||||
$item->current_version = $manifest->version ?? Text::_('JLIB_UNKNOWN');
|
||||
$item->description = $item->description !== '' ? $item->description : Text::_('COM_INSTALLER_MSG_UPDATE_NODESC');
|
||||
$item->type_translated = Text::_('COM_INSTALLER_TYPE_' . strtoupper($item->type));
|
||||
$item->folder_translated = $item->folder ?: Text::_('COM_INSTALLER_TYPE_NONAPPLICABLE');
|
||||
$item->install_type = $item->extension_id ? Text::_('COM_INSTALLER_MSG_UPDATE_UPDATE') : Text::_('COM_INSTALLER_NEW_INSTALL');
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object list
|
||||
*
|
||||
* @param QueryInterface $query The query
|
||||
* @param int $limitstart Offset
|
||||
* @param int $limit The number of records
|
||||
*
|
||||
* @return object[]
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
protected function _getList($query, $limitstart = 0, $limit = 0)
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$listOrder = $this->getState('list.ordering', 'u.name');
|
||||
$listDirn = $this->getState('list.direction', 'asc');
|
||||
|
||||
// Process ordering.
|
||||
if (\in_array($listOrder, ['client_translated', 'folder_translated', 'type_translated'])) {
|
||||
$db->setQuery($query);
|
||||
$result = $db->loadObjectList();
|
||||
$this->translate($result);
|
||||
$result = ArrayHelper::sortObjects($result, $listOrder, strtolower($listDirn) === 'desc' ? -1 : 1, true, true);
|
||||
$total = \count($result);
|
||||
|
||||
if ($total < $limitstart) {
|
||||
$limitstart = 0;
|
||||
$this->setState('list.start', 0);
|
||||
}
|
||||
|
||||
return \array_slice($result, $limitstart, $limit ?: null);
|
||||
}
|
||||
|
||||
$query->order($db->quoteName($listOrder) . ' ' . $db->escape($listDirn));
|
||||
|
||||
$result = parent::_getList($query, $limitstart, $limit);
|
||||
$this->translate($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of disabled update sites
|
||||
*
|
||||
* @return integer
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function getDisabledUpdateSites()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('COUNT(*)')
|
||||
->from($db->quoteName('#__update_sites'))
|
||||
->where($db->quoteName('enabled') . ' = 0');
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
return $db->loadResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds updates for an extension.
|
||||
*
|
||||
* @param int $eid Extension identifier to look for
|
||||
* @param int $cacheTimeout Cache timeout
|
||||
* @param int $minimumStability Minimum stability for updates {@see Updater} (0=dev, 1=alpha, 2=beta, 3=rc, 4=stable)
|
||||
*
|
||||
* @return boolean Result
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function findUpdates($eid = 0, $cacheTimeout = 0, $minimumStability = Updater::STABILITY_STABLE)
|
||||
{
|
||||
Updater::getInstance()->findUpdates($eid, $cacheTimeout, $minimumStability);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the updates from the table.
|
||||
*
|
||||
* @return boolean result of operation
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function purge()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
try {
|
||||
$db->truncateTable('#__updates');
|
||||
} catch (ExecutionFailureException $e) {
|
||||
$this->_message = Text::_('JLIB_INSTALLER_FAILED_TO_PURGE_UPDATES');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset the last update check timestamp
|
||||
$query = $db->getQuery(true)
|
||||
->update($db->quoteName('#__update_sites'))
|
||||
->set($db->quoteName('last_check_timestamp') . ' = ' . $db->quote(0));
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
// Clear the administrator cache
|
||||
$this->cleanCache('_system');
|
||||
|
||||
$this->_message = Text::_('JLIB_INSTALLER_PURGED_UPDATES');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update function.
|
||||
*
|
||||
* Sets the "result" state with the result of the operation.
|
||||
*
|
||||
* @param int[] $uids List of updates to apply
|
||||
* @param int $minimumStability The minimum allowed stability for installed updates {@see Updater}
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function update($uids, $minimumStability = Updater::STABILITY_STABLE)
|
||||
{
|
||||
$result = true;
|
||||
|
||||
foreach ($uids as $uid) {
|
||||
$update = new Update();
|
||||
$instance = new \Joomla\CMS\Table\Update($this->getDatabase());
|
||||
|
||||
if (!$instance->load($uid)) {
|
||||
// Update no longer available, maybe already updated by a package.
|
||||
continue;
|
||||
}
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('type')
|
||||
->from('#__update_sites')
|
||||
->where($db->quoteName('update_site_id') . ' = :id')
|
||||
->bind(':id', $instance->update_site_id, ParameterType::INTEGER);
|
||||
|
||||
$updateSiteType = (string) $db->setQuery($query)->loadResult();
|
||||
|
||||
// TUF is currently only supported for Joomla core
|
||||
if ($updateSiteType === 'tuf') {
|
||||
$app->enqueueMessage(Text::_('JLIB_INSTALLER_TUF_NOT_AVAILABLE'), 'error');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$update->loadFromXml($instance->detailsurl, $minimumStability);
|
||||
|
||||
// Find and use extra_query from update_site if available
|
||||
$updateSiteInstance = new \Joomla\CMS\Table\UpdateSite($this->getDatabase());
|
||||
$updateSiteInstance->load($instance->update_site_id);
|
||||
|
||||
if ($updateSiteInstance->extra_query) {
|
||||
$update->set('extra_query', $updateSiteInstance->extra_query);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->preparePreUpdate($update, $instance);
|
||||
|
||||
// Install sets state and enqueues messages
|
||||
$res = $this->install($update);
|
||||
} catch (\Throwable $t) {
|
||||
$res = false;
|
||||
|
||||
Factory::getApplication()->enqueueMessage(
|
||||
Text::sprintf(
|
||||
'COM_INSTALLER_UPDATE_ERROR',
|
||||
$instance->name,
|
||||
$t->getMessage(),
|
||||
(JDEBUG ? str_replace(JPATH_ROOT, 'JROOT', Path::clean($t->getFile())) . ':' . $t->getLine() : '')
|
||||
),
|
||||
'error'
|
||||
);
|
||||
}
|
||||
|
||||
if ($res) {
|
||||
$instance->delete($uid);
|
||||
}
|
||||
|
||||
$result = $res & $result;
|
||||
}
|
||||
|
||||
// Clear the cached extension data and menu cache
|
||||
$this->cleanCache('_system');
|
||||
$this->cleanCache('com_modules');
|
||||
$this->cleanCache('com_plugins');
|
||||
$this->cleanCache('mod_menu');
|
||||
|
||||
// Set the final state
|
||||
$this->setState('result', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the actual update installation.
|
||||
*
|
||||
* @param Update $update An update definition
|
||||
*
|
||||
* @return boolean Result of install
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
private function install($update)
|
||||
{
|
||||
// Load overrides plugin.
|
||||
PluginHelper::importPlugin('installer');
|
||||
|
||||
$app = Factory::getApplication();
|
||||
|
||||
if (!isset($update->get('downloadurl')->_data)) {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_INVALID_EXTENSION_UPDATE'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$url = trim($update->downloadurl->_data);
|
||||
$sources = $update->get('downloadSources', []);
|
||||
|
||||
if ($extra_query = $update->get('extra_query')) {
|
||||
$url .= (strpos($url, '?') === false) ? '?' : '&';
|
||||
$url .= $extra_query;
|
||||
}
|
||||
|
||||
$mirror = 0;
|
||||
|
||||
while (!($p_file = InstallerHelper::downloadPackage($url)) && isset($sources[$mirror])) {
|
||||
$name = $sources[$mirror];
|
||||
$url = trim($name->url);
|
||||
|
||||
if ($extra_query) {
|
||||
$url .= (strpos($url, '?') === false) ? '?' : '&';
|
||||
$url .= $extra_query;
|
||||
}
|
||||
|
||||
$mirror++;
|
||||
}
|
||||
|
||||
// Was the package downloaded?
|
||||
if (!$p_file) {
|
||||
Factory::getApplication()->enqueueMessage(Text::sprintf('COM_INSTALLER_PACKAGE_DOWNLOAD_FAILED', $url), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$config = $app->getConfig();
|
||||
$tmp_dest = $config->get('tmp_path');
|
||||
|
||||
// Unpack the downloaded package file
|
||||
$package = InstallerHelper::unpack($tmp_dest . '/' . $p_file);
|
||||
|
||||
if (empty($package)) {
|
||||
$app->enqueueMessage(Text::sprintf('COM_INSTALLER_UNPACK_ERROR', $p_file), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get an installer instance
|
||||
$installer = Installer::getInstance();
|
||||
$update->set('type', $package['type']);
|
||||
|
||||
// Check the package
|
||||
$check = InstallerHelper::isChecksumValid($package['packagefile'], $update);
|
||||
|
||||
if ($check === InstallerHelper::HASH_NOT_VALIDATED) {
|
||||
$app->enqueueMessage(Text::_('COM_INSTALLER_INSTALL_CHECKSUM_WRONG'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($check === InstallerHelper::HASH_NOT_PROVIDED) {
|
||||
$app->enqueueMessage(Text::_('COM_INSTALLER_INSTALL_CHECKSUM_WARNING'), 'warning');
|
||||
}
|
||||
|
||||
// Install the package
|
||||
if (!$installer->update($package['dir'])) {
|
||||
// There was an error updating the package
|
||||
$app->enqueueMessage(
|
||||
Text::sprintf(
|
||||
'COM_INSTALLER_MSG_UPDATE_ERROR',
|
||||
Text::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($package['type']))
|
||||
),
|
||||
'error'
|
||||
);
|
||||
$result = false;
|
||||
} else {
|
||||
// Package updated successfully
|
||||
$app->enqueueMessage(
|
||||
Text::sprintf(
|
||||
'COM_INSTALLER_MSG_UPDATE_SUCCESS',
|
||||
Text::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($package['type']))
|
||||
),
|
||||
'success'
|
||||
);
|
||||
$result = true;
|
||||
}
|
||||
|
||||
// Quick change
|
||||
$this->type = $package['type'];
|
||||
|
||||
$this->setState('name', $installer->get('name'));
|
||||
$this->setState('result', $result);
|
||||
$app->setUserState('com_installer.message', $installer->message);
|
||||
$app->setUserState('com_installer.extension_message', $installer->get('extension_message'));
|
||||
|
||||
// Cleanup the install files
|
||||
if (!is_file($package['packagefile'])) {
|
||||
$package['packagefile'] = $config->get('tmp_path') . '/' . $package['packagefile'];
|
||||
}
|
||||
|
||||
InstallerHelper::cleanupInstall($package['packagefile'], $package['extractdir']);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the row form.
|
||||
*
|
||||
* @param array $data Data for the form.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return Form|bool A Form object on success, false on failure
|
||||
*
|
||||
* @since 2.5.2
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
Form::addFormPath(JPATH_COMPONENT . '/models/forms');
|
||||
Form::addFieldPath(JPATH_COMPONENT . '/models/fields');
|
||||
$form = Form::getInstance('com_installer.update', 'update', ['load_data' => $loadData]);
|
||||
|
||||
// Check for an error.
|
||||
if ($form == false) {
|
||||
$this->setError($form->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the session for previously entered form data.
|
||||
$data = $this->loadFormData();
|
||||
|
||||
// Bind the form data if present.
|
||||
if (!empty($data)) {
|
||||
$form->bind($data);
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return mixed The data for the form.
|
||||
*
|
||||
* @since 2.5.2
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
// Check the session for previously entered form data.
|
||||
$data = Factory::getApplication()->getUserState($this->context, []);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add parameters to the update
|
||||
*
|
||||
* @param Update $update An update definition
|
||||
* @param \Joomla\CMS\Table\Update $table The update instance from the database
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected function preparePreUpdate($update, $table)
|
||||
{
|
||||
switch ($table->type) {
|
||||
case 'component':
|
||||
// Components could have a helper which adds additional data
|
||||
$ename = str_replace('com_', '', $table->element);
|
||||
$fname = $ename . '.php';
|
||||
$cname = ucfirst($ename) . 'Helper';
|
||||
|
||||
$path = JPATH_ADMINISTRATOR . '/components/' . $table->element . '/helpers/' . $fname;
|
||||
|
||||
if (is_file($path)) {
|
||||
require_once $path;
|
||||
|
||||
if (class_exists($cname) && \is_callable([$cname, 'prepareUpdate'])) {
|
||||
\call_user_func_array([$cname, 'prepareUpdate'], [&$update, &$table]);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'module':
|
||||
// Modules could have a helper which adds additional data
|
||||
$cname = str_replace('_', '', $table->element) . 'Helper';
|
||||
$path = ($table->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/modules/' . $table->element . '/helper.php';
|
||||
|
||||
if (is_file($path)) {
|
||||
require_once $path;
|
||||
|
||||
if (class_exists($cname) && \is_callable([$cname, 'prepareUpdate'])) {
|
||||
\call_user_func_array([$cname, 'prepareUpdate'], [&$update, &$table]);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'plugin':
|
||||
// If we have a plugin, we can use the plugin trigger "onInstallerBeforePackageDownload"
|
||||
// But we should make sure, that our plugin is loaded, so we don't need a second "installer" plugin
|
||||
$cname = str_replace('plg_', '', $table->element);
|
||||
PluginHelper::importPlugin($table->folder, $cname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manipulate the query to be used to evaluate if this is an Empty State to provide specific conditions for this extension.
|
||||
*
|
||||
* @return QueryInterface
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getEmptyStateQuery()
|
||||
{
|
||||
$query = parent::getEmptyStateQuery();
|
||||
|
||||
$query->where($this->getDatabase()->quoteName('extension_id') . ' != 0');
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\MVC\Model\AdminModel;
|
||||
use Joomla\CMS\Object\CMSObject;
|
||||
use Joomla\Component\Installer\Administrator\Helper\InstallerHelper;
|
||||
use Joomla\Database\ParameterType;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Item Model for an update site.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class UpdatesiteModel extends AdminModel
|
||||
{
|
||||
/**
|
||||
* The type alias for this content type.
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $typeAlias = 'com_installer.updatesite';
|
||||
|
||||
/**
|
||||
* Method to get the row form.
|
||||
*
|
||||
* @param array $data Data for the form.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return Form|boolean A Form object on success, false on failure
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_installer.updatesite', 'updatesite', ['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 4.0.0
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
$data = $this->getItem();
|
||||
$this->preprocessData('com_installer.updatesite', $data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a single record.
|
||||
*
|
||||
* @param integer $pk The id of the primary key.
|
||||
*
|
||||
* @return \stdClass|boolean Object on success, false on failure.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getItem($pk = null)
|
||||
{
|
||||
$item = parent::getItem($pk);
|
||||
|
||||
$db = $this->getDatabase();
|
||||
$updateSiteId = (int) $item->get('update_site_id');
|
||||
$query = $db->getQuery(true)
|
||||
->select(
|
||||
$db->quoteName(
|
||||
[
|
||||
'update_sites.extra_query',
|
||||
'extensions.type',
|
||||
'extensions.element',
|
||||
'extensions.folder',
|
||||
'extensions.client_id',
|
||||
'extensions.checked_out',
|
||||
]
|
||||
)
|
||||
)
|
||||
->from($db->quoteName('#__update_sites', 'update_sites'))
|
||||
->join(
|
||||
'INNER',
|
||||
$db->quoteName('#__update_sites_extensions', 'update_sites_extensions'),
|
||||
$db->quoteName('update_sites_extensions.update_site_id') . ' = ' . $db->quoteName('update_sites.update_site_id')
|
||||
)
|
||||
->join(
|
||||
'INNER',
|
||||
$db->quoteName('#__extensions', 'extensions'),
|
||||
$db->quoteName('extensions.extension_id') . ' = ' . $db->quoteName('update_sites_extensions.extension_id')
|
||||
)
|
||||
->where($db->quoteName('update_sites.update_site_id') . ' = :updatesiteid')
|
||||
->bind(':updatesiteid', $updateSiteId, ParameterType::INTEGER);
|
||||
|
||||
$db->setQuery($query);
|
||||
$extension = new CMSObject($db->loadAssoc());
|
||||
|
||||
$downloadKey = InstallerHelper::getDownloadKey($extension);
|
||||
|
||||
$item->set('extra_query', $downloadKey['value'] ?? '');
|
||||
$item->set('downloadIdPrefix', $downloadKey['prefix'] ?? '');
|
||||
$item->set('downloadIdSuffix', $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 4.0.0
|
||||
*/
|
||||
public function save($data): bool
|
||||
{
|
||||
// Apply the extra_query. Always empty when saving a free extension's update site.
|
||||
if (isset($data['extra_query'])) {
|
||||
$data['extra_query'] = $data['downloadIdPrefix'] . $data['extra_query'] . $data['downloadIdSuffix'];
|
||||
}
|
||||
|
||||
// Force Joomla to recheck for updates
|
||||
$data['last_check_timestamp'] = 0;
|
||||
|
||||
$result = parent::save($data);
|
||||
|
||||
if (!$result) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Delete update records forcing Joomla to fetch them again, applying the new extra_query.
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__updates'))
|
||||
->where($db->quoteName('update_site_id') . ' = :updateSiteId');
|
||||
$query->bind(':updateSiteId', $data['update_site_id'], ParameterType::INTEGER);
|
||||
|
||||
try {
|
||||
$db->setQuery($query)->execute();
|
||||
} catch (\Exception $e) {
|
||||
// No problem if this fails for any reason.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,628 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Filesystem\Folder;
|
||||
use Joomla\CMS\Installer\Installer;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\Object\CMSObject;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Table\UpdateSite as UpdateSiteTable;
|
||||
use Joomla\Component\Installer\Administrator\Helper\InstallerHelper;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Database\QueryInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer Update Sites Model
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
class UpdatesitesModel extends InstallerModel
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param ?MVCFactoryInterface $factory The factory.
|
||||
*
|
||||
* @since 1.6
|
||||
* @see \Joomla\CMS\MVC\Model\ListModel
|
||||
*/
|
||||
public function __construct($config = [], ?MVCFactoryInterface $factory = null)
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'update_site_name',
|
||||
'name',
|
||||
'client_id',
|
||||
'client',
|
||||
'client_translated',
|
||||
'status',
|
||||
'type',
|
||||
'type_translated',
|
||||
'folder',
|
||||
'folder_translated',
|
||||
'update_site_id',
|
||||
'enabled',
|
||||
'supported',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable an extension.
|
||||
*
|
||||
* @param array $eid Extension ids to un/publish
|
||||
* @param int $value Publish value
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @throws \Exception on ACL error
|
||||
* @since 3.4
|
||||
*
|
||||
*/
|
||||
public function publish(&$eid = [], $value = 1)
|
||||
{
|
||||
if (!$this->getCurrentUser()->authorise('core.edit.state', 'com_installer')) {
|
||||
throw new \Exception(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 403);
|
||||
}
|
||||
|
||||
$result = true;
|
||||
|
||||
// Ensure eid is an array of extension ids
|
||||
if (!\is_array($eid)) {
|
||||
$eid = [$eid];
|
||||
}
|
||||
|
||||
// Get a table object for the extension type
|
||||
$table = new UpdateSiteTable($this->getDatabase());
|
||||
|
||||
// Enable the update site in the table and store it in the database
|
||||
foreach ($eid as $i => $id) {
|
||||
$table->load($id);
|
||||
$table->enabled = $value;
|
||||
|
||||
if (!$table->store()) {
|
||||
$this->setError($table->getError());
|
||||
$result = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an update site.
|
||||
*
|
||||
* @param array $ids Extension ids to delete.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception on ACL error
|
||||
* @since 3.6
|
||||
*
|
||||
*/
|
||||
public function delete($ids = [])
|
||||
{
|
||||
if (!$this->getCurrentUser()->authorise('core.delete', 'com_installer')) {
|
||||
throw new \Exception(Text::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), 403);
|
||||
}
|
||||
|
||||
// Ensure eid is an array of extension ids
|
||||
if (!\is_array($ids)) {
|
||||
$ids = [$ids];
|
||||
}
|
||||
|
||||
$db = $this->getDatabase();
|
||||
$app = Factory::getApplication();
|
||||
|
||||
$count = 0;
|
||||
|
||||
// Gets the update site names.
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName(['update_site_id', 'name']))
|
||||
->from($db->quoteName('#__update_sites'))
|
||||
->whereIn($db->quoteName('update_site_id'), $ids);
|
||||
$db->setQuery($query);
|
||||
$updateSitesNames = $db->loadObjectList('update_site_id');
|
||||
|
||||
// Gets Joomla core update sites Ids.
|
||||
$joomlaUpdateSitesIds = $this->getJoomlaUpdateSitesIds(0);
|
||||
|
||||
// Enable the update site in the table and store it in the database
|
||||
foreach ($ids as $i => $id) {
|
||||
// Don't allow to delete Joomla Core update sites.
|
||||
if (\in_array((int) $id, $joomlaUpdateSitesIds)) {
|
||||
$app->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_UPDATESITES_DELETE_CANNOT_DELETE', $updateSitesNames[$id]->name), 'error');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Delete the update site from all tables.
|
||||
try {
|
||||
$id = (int) $id;
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__update_sites'))
|
||||
->where($db->quoteName('update_site_id') . ' = :id')
|
||||
->bind(':id', $id, ParameterType::INTEGER);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__update_sites_extensions'))
|
||||
->where($db->quoteName('update_site_id') . ' = :id')
|
||||
->bind(':id', $id, ParameterType::INTEGER);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__updates'))
|
||||
->where($db->quoteName('update_site_id') . ' = :id')
|
||||
->bind(':id', $id, ParameterType::INTEGER);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
$count++;
|
||||
} catch (\RuntimeException $e) {
|
||||
$app->enqueueMessage(
|
||||
Text::sprintf(
|
||||
'COM_INSTALLER_MSG_UPDATESITES_DELETE_ERROR',
|
||||
$updateSitesNames[$id]->name,
|
||||
$e->getMessage()
|
||||
),
|
||||
'error'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($count > 0) {
|
||||
$app->enqueueMessage(Text::plural('COM_INSTALLER_MSG_UPDATESITES_N_DELETE_UPDATESITES_DELETED', $count), 'message');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the Joomla update sites ids.
|
||||
*
|
||||
* @param integer $column Column to return. 0 for update site ids, 1 for extension ids.
|
||||
*
|
||||
* @return array Array with joomla core update site ids.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
protected function getJoomlaUpdateSitesIds($column = 0)
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
// Fetch the Joomla core update sites ids and their extension ids. We search for all except the core joomla extension with update sites.
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName(['use.update_site_id', 'e.extension_id']))
|
||||
->from($db->quoteName('#__update_sites_extensions', 'use'))
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__update_sites', 'us'),
|
||||
$db->quoteName('us.update_site_id') . ' = ' . $db->quoteName('use.update_site_id')
|
||||
)
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__extensions', 'e'),
|
||||
$db->quoteName('e.extension_id') . ' = ' . $db->quoteName('use.extension_id')
|
||||
)
|
||||
->where('('
|
||||
. '(' . $db->quoteName('e.type') . ' = ' . $db->quote('file') .
|
||||
' AND ' . $db->quoteName('e.element') . ' = ' . $db->quote('joomla') . ')'
|
||||
. ' OR (' . $db->quoteName('e.type') . ' = ' . $db->quote('package') . ' AND ' . $db->quoteName('e.element')
|
||||
. ' = ' . $db->quote('pkg_en-GB') . ') OR (' . $db->quoteName('e.type') . ' = ' . $db->quote('component')
|
||||
. ' AND ' . $db->quoteName('e.element') . ' = ' . $db->quote('com_joomlaupdate') . ')'
|
||||
. ')');
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
return $db->loadColumn($column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild update sites tables.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception on ACL error
|
||||
* @since 3.6
|
||||
*
|
||||
*/
|
||||
public function rebuild(): void
|
||||
{
|
||||
if (!$this->getCurrentUser()->authorise('core.admin', 'com_installer')) {
|
||||
throw new \Exception(Text::_('COM_INSTALLER_MSG_UPDATESITES_REBUILD_NOT_PERMITTED'), 403);
|
||||
}
|
||||
|
||||
$db = $this->getDatabase();
|
||||
$app = Factory::getApplication();
|
||||
|
||||
// Check if Joomla Extension plugin is enabled.
|
||||
if (!PluginHelper::isEnabled('extension', 'joomla')) {
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('extension_id'))
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
|
||||
->where($db->quoteName('element') . ' = ' . $db->quote('joomla'))
|
||||
->where($db->quoteName('folder') . ' = ' . $db->quote('extension'));
|
||||
$db->setQuery($query);
|
||||
|
||||
$pluginId = (int) $db->loadResult();
|
||||
|
||||
$link = Route::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . $pluginId);
|
||||
$app->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_UPDATESITES_REBUILD_EXTENSION_PLUGIN_NOT_ENABLED', $link), 'error');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$clients = [JPATH_SITE, JPATH_ADMINISTRATOR, JPATH_API];
|
||||
$extensionGroupFolders = ['components', 'modules', 'plugins', 'templates', 'language', 'manifests'];
|
||||
|
||||
$pathsToSearch = [];
|
||||
|
||||
// Identifies which folders to search for manifest files.
|
||||
foreach ($clients as $clientPath) {
|
||||
foreach ($extensionGroupFolders as $extensionGroupFolderName) {
|
||||
// Components, modules, plugins, templates, languages and manifest (files, libraries, etc)
|
||||
if ($extensionGroupFolderName !== 'plugins') {
|
||||
foreach (glob($clientPath . '/' . $extensionGroupFolderName . '/*', GLOB_NOSORT | GLOB_ONLYDIR) as $extensionFolderPath) {
|
||||
$pathsToSearch[] = $extensionFolderPath;
|
||||
}
|
||||
} else {
|
||||
// Plugins (another directory level is needed)
|
||||
foreach (
|
||||
glob(
|
||||
$clientPath . '/' . $extensionGroupFolderName . '/*',
|
||||
GLOB_NOSORT | GLOB_ONLYDIR
|
||||
) as $pluginGroupFolderPath
|
||||
) {
|
||||
foreach (glob($pluginGroupFolderPath . '/*', GLOB_NOSORT | GLOB_ONLYDIR) as $extensionFolderPath) {
|
||||
$pathsToSearch[] = $extensionFolderPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gets Joomla core update sites Ids.
|
||||
$joomlaUpdateSitesIds = $this->getJoomlaUpdateSitesIds(0);
|
||||
|
||||
// First backup any custom extra_query for the sites
|
||||
$query = $db->getQuery(true)
|
||||
->select('TRIM(' . $db->quoteName('location') . ') AS ' . $db->quoteName('location') . ', ' . $db->quoteName('extra_query'))
|
||||
->from($db->quoteName('#__update_sites'));
|
||||
$db->setQuery($query);
|
||||
$backupExtraQuerys = $db->loadAssocList('location');
|
||||
|
||||
// Delete from all tables (except joomla core update sites).
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__update_sites'))
|
||||
->whereNotIn($db->quoteName('update_site_id'), $joomlaUpdateSitesIds);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__update_sites_extensions'))
|
||||
->whereNotIn($db->quoteName('update_site_id'), $joomlaUpdateSitesIds);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__updates'))
|
||||
->whereNotIn($db->quoteName('update_site_id'), $joomlaUpdateSitesIds);
|
||||
$db->setQuery($query);
|
||||
$db->execute();
|
||||
|
||||
$count = 0;
|
||||
|
||||
// Gets Joomla core extension Ids.
|
||||
$joomlaCoreExtensionIds = $this->getJoomlaUpdateSitesIds(1);
|
||||
|
||||
// Search for updateservers in manifest files inside the folders to search.
|
||||
foreach ($pathsToSearch as $extensionFolderPath) {
|
||||
$tmpInstaller = new Installer();
|
||||
$tmpInstaller->setDatabase($this->getDatabase());
|
||||
|
||||
$tmpInstaller->setPath('source', $extensionFolderPath);
|
||||
|
||||
// Main folder manifests (higher priority)
|
||||
$parentXmlfiles = Folder::files($tmpInstaller->getPath('source'), '.xml$', false, true);
|
||||
|
||||
// Search for children manifests (lower priority)
|
||||
$allXmlFiles = Folder::files($tmpInstaller->getPath('source'), '.xml$', 1, true);
|
||||
|
||||
// Create a unique array of files ordered by priority
|
||||
$xmlfiles = array_unique(array_merge($parentXmlfiles, $allXmlFiles));
|
||||
|
||||
if (!empty($xmlfiles)) {
|
||||
foreach ($xmlfiles as $file) {
|
||||
// Is it a valid Joomla installation manifest file?
|
||||
$manifest = $tmpInstaller->isManifest($file);
|
||||
|
||||
if ($manifest !== null) {
|
||||
/**
|
||||
* Search if the extension exists in the extensions table. Excluding Joomla
|
||||
* core extensions and discovered but not yet installed extensions.
|
||||
*/
|
||||
|
||||
$name = (string) $manifest->name;
|
||||
$pkgName = (string) $manifest->packagename;
|
||||
$type = (string) $manifest['type'];
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('extension_id'))
|
||||
->from($db->quoteName('#__extensions'))
|
||||
->where(
|
||||
[
|
||||
$db->quoteName('type') . ' = :type',
|
||||
$db->quoteName('state') . ' != -1',
|
||||
]
|
||||
)
|
||||
->extendWhere(
|
||||
'AND',
|
||||
[
|
||||
$db->quoteName('name') . ' = :name',
|
||||
$db->quoteName('name') . ' = :pkgname',
|
||||
],
|
||||
'OR'
|
||||
)
|
||||
->whereNotIn($db->quoteName('extension_id'), $joomlaCoreExtensionIds)
|
||||
->bind(':name', $name)
|
||||
->bind(':pkgname', $pkgName)
|
||||
->bind(':type', $type);
|
||||
$db->setQuery($query);
|
||||
|
||||
$eid = (int) $db->loadResult();
|
||||
|
||||
if ($eid && $manifest->updateservers) {
|
||||
// Set the manifest object and path
|
||||
$tmpInstaller->manifest = $manifest;
|
||||
$tmpInstaller->setPath('manifest', $file);
|
||||
|
||||
// Remove last extra_query as we are in a foreach
|
||||
$tmpInstaller->extraQuery = '';
|
||||
|
||||
if (
|
||||
$tmpInstaller->manifest->updateservers
|
||||
&& $tmpInstaller->manifest->updateservers->server
|
||||
&& isset($backupExtraQuerys[trim((string) $tmpInstaller->manifest->updateservers->server)])
|
||||
) {
|
||||
$tmpInstaller->extraQuery = $backupExtraQuerys[trim((string) $tmpInstaller->manifest->updateservers->server)]['extra_query'];
|
||||
}
|
||||
|
||||
// Load the extension plugin (if not loaded yet).
|
||||
PluginHelper::importPlugin('extension', 'joomla');
|
||||
|
||||
// Fire the onExtensionAfterUpdate
|
||||
$app->triggerEvent('onExtensionAfterUpdate', ['installer' => $tmpInstaller, 'eid' => $eid]);
|
||||
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($count > 0) {
|
||||
$app->enqueueMessage(Text::_('COM_INSTALLER_MSG_UPDATESITES_REBUILD_SUCCESS'), 'message');
|
||||
} else {
|
||||
$app->enqueueMessage(Text::_('COM_INSTALLER_MSG_UPDATESITES_REBUILD_MESSAGE'), 'message');
|
||||
}
|
||||
|
||||
// Flush the system cache to ensure extra_query is correctly loaded next time.
|
||||
$this->cleanCache('_system');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get an array of data items.
|
||||
*
|
||||
* @return mixed An array of data items on success, false on failure.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getItems()
|
||||
{
|
||||
$items = parent::getItems();
|
||||
|
||||
array_walk(
|
||||
$items,
|
||||
static function ($item) {
|
||||
$data = new CMSObject($item);
|
||||
$item->downloadKey = InstallerHelper::getDownloadKey($data);
|
||||
}
|
||||
);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering An optional ordering field.
|
||||
* @param string $direction An optional direction (asc|desc).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function populateState($ordering = 'name', $direction = 'asc')
|
||||
{
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
protected function getStoreId($id = '')
|
||||
{
|
||||
$id .= ':' . $this->getState('search');
|
||||
$id .= ':' . $this->getState('client_id');
|
||||
$id .= ':' . $this->getState('enabled');
|
||||
$id .= ':' . $this->getState('type');
|
||||
$id .= ':' . $this->getState('folder');
|
||||
$id .= ':' . $this->getState('supported');
|
||||
|
||||
return parent::getStoreId($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database query
|
||||
*
|
||||
* @return QueryInterface The database query
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function getListQuery()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select(
|
||||
$db->quoteName(
|
||||
[
|
||||
's.update_site_id',
|
||||
's.name',
|
||||
's.type',
|
||||
's.location',
|
||||
's.enabled',
|
||||
's.checked_out',
|
||||
's.checked_out_time',
|
||||
's.extra_query',
|
||||
'e.extension_id',
|
||||
'e.name',
|
||||
'e.type',
|
||||
'e.element',
|
||||
'e.folder',
|
||||
'e.client_id',
|
||||
'e.state',
|
||||
'e.manifest_cache',
|
||||
'u.name',
|
||||
],
|
||||
[
|
||||
'update_site_id',
|
||||
'update_site_name',
|
||||
'update_site_type',
|
||||
'location',
|
||||
'enabled',
|
||||
'checked_out',
|
||||
'checked_out_time',
|
||||
'extra_query',
|
||||
'extension_id',
|
||||
'name',
|
||||
'type',
|
||||
'element',
|
||||
'folder',
|
||||
'client_id',
|
||||
'state',
|
||||
'manifest_cache',
|
||||
'editor',
|
||||
]
|
||||
)
|
||||
)
|
||||
->from($db->quoteName('#__update_sites', 's'))
|
||||
->join(
|
||||
'INNER',
|
||||
$db->quoteName('#__update_sites_extensions', 'se'),
|
||||
$db->quoteName('se.update_site_id') . ' = ' . $db->quoteName('s.update_site_id')
|
||||
)
|
||||
->join(
|
||||
'INNER',
|
||||
$db->quoteName('#__extensions', 'e'),
|
||||
$db->quoteName('e.extension_id') . ' = ' . $db->quoteName('se.extension_id')
|
||||
)
|
||||
->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__users', 'u'),
|
||||
$db->quoteName('s.checked_out') . ' = ' . $db->quoteName('u.id')
|
||||
)
|
||||
->where($db->quoteName('state') . ' = 0');
|
||||
|
||||
// Process select filters.
|
||||
$supported = $this->getState('filter.supported');
|
||||
$enabled = $this->getState('filter.enabled', '');
|
||||
$type = $this->getState('filter.type');
|
||||
$clientId = $this->getState('filter.client_id');
|
||||
$folder = $this->getState('filter.folder');
|
||||
|
||||
if ($enabled !== '') {
|
||||
$enabled = (int) $enabled;
|
||||
$query->where($db->quoteName('s.enabled') . ' = :enabled')
|
||||
->bind(':enabled', $enabled, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
if ($type) {
|
||||
$query->where($db->quoteName('e.type') . ' = :type')
|
||||
->bind(':type', $type);
|
||||
}
|
||||
|
||||
if ($clientId !== null && $clientId !== '') {
|
||||
$clientId = (int) $clientId;
|
||||
$query->where($db->quoteName('e.client_id') . ' = :clientId')
|
||||
->bind(':clientId', $clientId, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
if ($folder !== '' && \in_array($type, ['plugin', 'library', ''], true)) {
|
||||
$folderForBinding = $folder === '*' ? '' : $folder;
|
||||
$query->where($db->quoteName('e.folder') . ' = :folder')
|
||||
->bind(':folder', $folderForBinding);
|
||||
}
|
||||
|
||||
// Process search filter (update site id).
|
||||
$search = $this->getState('filter.search');
|
||||
|
||||
if (!empty($search) && stripos($search, 'id:') === 0) {
|
||||
$uid = (int) substr($search, 3);
|
||||
$query->where($db->quoteName('s.update_site_id') . ' = :siteId')
|
||||
->bind(':siteId', $uid, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
if (is_numeric($supported)) {
|
||||
switch ($supported) {
|
||||
case 1:
|
||||
// Show Update Sites which support Download Keys
|
||||
$supportedIDs = InstallerHelper::getDownloadKeySupportedSites($enabled);
|
||||
break;
|
||||
|
||||
case -1:
|
||||
// Show Update Sites which are missing Download Keys
|
||||
$supportedIDs = InstallerHelper::getDownloadKeyExistsSites(false, $enabled);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Show Update Sites which have valid Download Keys
|
||||
$supportedIDs = InstallerHelper::getDownloadKeyExistsSites(true, $enabled);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($supportedIDs)) {
|
||||
// Don't remove array_values(). whereIn expect a zero-based array.
|
||||
$query->whereIn($db->quoteName('s.update_site_id'), array_values($supportedIDs));
|
||||
} else {
|
||||
// In case of an empty list of IDs we apply a fake filter to effectively return no data
|
||||
$query->where($db->quoteName('s.update_site_id') . ' = 0');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: The search for name, ordering and pagination are processed by the parent InstallerModel class (in
|
||||
* extension.php).
|
||||
*/
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer Warnings Model
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class WarningsModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* Extension Type
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'warnings';
|
||||
|
||||
/**
|
||||
* Return the byte value of a particular string.
|
||||
*
|
||||
* @param string $val String optionally with G, M or K suffix
|
||||
*
|
||||
* @return integer size in bytes
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function return_bytes($val)
|
||||
{
|
||||
if (empty($val)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$val = trim($val);
|
||||
|
||||
preg_match('#([0-9]+)[\s]*([a-z]+)#i', $val, $matches);
|
||||
|
||||
$last = '';
|
||||
|
||||
if (isset($matches[2])) {
|
||||
$last = $matches[2];
|
||||
}
|
||||
|
||||
if (isset($matches[1])) {
|
||||
$val = (int) $matches[1];
|
||||
}
|
||||
|
||||
switch (strtolower($last)) {
|
||||
case 'g':
|
||||
case 'gb':
|
||||
$val *= (1024 * 1024 * 1024);
|
||||
break;
|
||||
case 'm':
|
||||
case 'mb':
|
||||
$val *= (1024 * 1024);
|
||||
break;
|
||||
case 'k':
|
||||
case 'kb':
|
||||
$val *= 1024;
|
||||
break;
|
||||
}
|
||||
|
||||
return (int) $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the data.
|
||||
*
|
||||
* @return array Messages
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getItems()
|
||||
{
|
||||
static $messages;
|
||||
|
||||
if ($messages) {
|
||||
return $messages;
|
||||
}
|
||||
|
||||
$messages = [];
|
||||
|
||||
// 16MB
|
||||
$minLimit = 16 * 1024 * 1024;
|
||||
|
||||
$file_uploads = \ini_get('file_uploads');
|
||||
|
||||
if (!$file_uploads) {
|
||||
$messages[] = [
|
||||
'message' => Text::_('COM_INSTALLER_MSG_WARNINGS_FILEUPLOADSDISABLED'),
|
||||
'description' => Text::_('COM_INSTALLER_MSG_WARNINGS_FILEUPLOADISDISABLEDDESC'),
|
||||
];
|
||||
}
|
||||
|
||||
$upload_dir = \ini_get('upload_tmp_dir');
|
||||
|
||||
if (!$upload_dir) {
|
||||
$messages[] = [
|
||||
'message' => Text::_('COM_INSTALLER_MSG_WARNINGS_PHPUPLOADNOTSET'),
|
||||
'description' => Text::_('COM_INSTALLER_MSG_WARNINGS_PHPUPLOADNOTSETDESC'),
|
||||
];
|
||||
} elseif (!is_writable($upload_dir)) {
|
||||
$messages[] = [
|
||||
'message' => Text::_('COM_INSTALLER_MSG_WARNINGS_PHPUPLOADNOTWRITEABLE'),
|
||||
'description' => Text::sprintf('COM_INSTALLER_MSG_WARNINGS_PHPUPLOADNOTWRITEABLEDESC', $upload_dir),
|
||||
];
|
||||
}
|
||||
|
||||
$tmp_path = Factory::getApplication()->get('tmp_path');
|
||||
|
||||
if (!$tmp_path) {
|
||||
$messages[] = [
|
||||
'message' => Text::_('COM_INSTALLER_MSG_WARNINGS_JOOMLATMPNOTSET'),
|
||||
'description' => Text::_('COM_INSTALLER_MSG_WARNINGS_JOOMLATMPNOTSETDESC'),
|
||||
];
|
||||
} elseif (!is_writable($tmp_path)) {
|
||||
$messages[] = [
|
||||
'message' => Text::_('COM_INSTALLER_MSG_WARNINGS_JOOMLATMPNOTWRITEABLE'),
|
||||
'description' => Text::sprintf('COM_INSTALLER_MSG_WARNINGS_JOOMLATMPNOTWRITEABLEDESC', $tmp_path),
|
||||
];
|
||||
}
|
||||
|
||||
$memory_limit = $this->return_bytes(\ini_get('memory_limit'));
|
||||
|
||||
if ($memory_limit > -1) {
|
||||
if ($memory_limit < $minLimit) {
|
||||
// 16MB
|
||||
$messages[] = [
|
||||
'message' => Text::_('COM_INSTALLER_MSG_WARNINGS_LOWMEMORYWARN'),
|
||||
'description' => Text::_('COM_INSTALLER_MSG_WARNINGS_LOWMEMORYDESC'),
|
||||
];
|
||||
} elseif ($memory_limit < ($minLimit * 1.5)) {
|
||||
// 24MB
|
||||
$messages[] = [
|
||||
'message' => Text::_('COM_INSTALLER_MSG_WARNINGS_MEDMEMORYWARN'),
|
||||
'description' => Text::_('COM_INSTALLER_MSG_WARNINGS_MEDMEMORYDESC'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$post_max_size = $this->return_bytes(\ini_get('post_max_size'));
|
||||
$upload_max_filesize = $this->return_bytes(\ini_get('upload_max_filesize'));
|
||||
|
||||
if ($post_max_size > 0 && $post_max_size < $upload_max_filesize) {
|
||||
$messages[] = [
|
||||
'message' => Text::_('COM_INSTALLER_MSG_WARNINGS_UPLOADBIGGERTHANPOST'),
|
||||
'description' => Text::_('COM_INSTALLER_MSG_WARNINGS_UPLOADBIGGERTHANPOSTDESC'),
|
||||
];
|
||||
}
|
||||
|
||||
if ($post_max_size > 0 && $post_max_size < $minLimit) {
|
||||
$messages[] = [
|
||||
'message' => Text::_('COM_INSTALLER_MSG_WARNINGS_SMALLPOSTSIZE'),
|
||||
'description' => Text::_('COM_INSTALLER_MSG_WARNINGS_SMALLPOSTSIZEDESC'),
|
||||
];
|
||||
}
|
||||
|
||||
if ($upload_max_filesize > 0 && $upload_max_filesize < $minLimit) {
|
||||
$messages[] = [
|
||||
'message' => Text::_('COM_INSTALLER_MSG_WARNINGS_SMALLUPLOADSIZE'),
|
||||
'description' => Text::_('COM_INSTALLER_MSG_WARNINGS_SMALLUPLOADSIZEDESC'),
|
||||
];
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Service\HTML;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer HTML class.
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
class Manage
|
||||
{
|
||||
/**
|
||||
* Returns a published state on a grid.
|
||||
*
|
||||
* @param integer $value The state value.
|
||||
* @param integer $i The row index.
|
||||
* @param boolean $enabled An optional setting for access control on the action.
|
||||
* @param string $checkbox An optional prefix for checkboxes.
|
||||
*
|
||||
* @return string The Html code
|
||||
*
|
||||
* @see JHtmlJGrid::state
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function state($value, $i, $enabled = true, $checkbox = 'cb')
|
||||
{
|
||||
$states = [
|
||||
2 => [
|
||||
'',
|
||||
'COM_INSTALLER_EXTENSION_PROTECTED',
|
||||
'',
|
||||
'COM_INSTALLER_EXTENSION_PROTECTED',
|
||||
true,
|
||||
'protected',
|
||||
'protected',
|
||||
],
|
||||
1 => [
|
||||
'unpublish',
|
||||
'COM_INSTALLER_EXTENSION_ENABLED',
|
||||
'COM_INSTALLER_EXTENSION_DISABLE',
|
||||
'COM_INSTALLER_EXTENSION_ENABLED',
|
||||
true,
|
||||
'publish',
|
||||
'publish',
|
||||
],
|
||||
0 => [
|
||||
'publish',
|
||||
'COM_INSTALLER_EXTENSION_DISABLED',
|
||||
'COM_INSTALLER_EXTENSION_ENABLE',
|
||||
'COM_INSTALLER_EXTENSION_DISABLED',
|
||||
true,
|
||||
'unpublish',
|
||||
'unpublish',
|
||||
],
|
||||
];
|
||||
|
||||
return HTMLHelper::_('jgrid.state', $states, $value, $i, 'manage.', $enabled, true, $checkbox);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Service\HTML;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Installer HTML class.
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
class Updatesites
|
||||
{
|
||||
/**
|
||||
* Returns a published state on a grid.
|
||||
*
|
||||
* @param integer $value The state value.
|
||||
* @param integer $i The row index.
|
||||
* @param boolean $enabled An optional setting for access control on the action.
|
||||
* @param string $checkbox An optional prefix for checkboxes.
|
||||
*
|
||||
* @return string The HTML code
|
||||
*
|
||||
* @see JHtmlJGrid::state()
|
||||
* @since 3.5
|
||||
*/
|
||||
public function state($value, $i, $enabled = true, $checkbox = 'cb')
|
||||
{
|
||||
$states = [
|
||||
1 => [
|
||||
'unpublish',
|
||||
'COM_INSTALLER_UPDATESITE_ENABLED',
|
||||
'COM_INSTALLER_UPDATESITE_DISABLE',
|
||||
'COM_INSTALLER_UPDATESITE_ENABLED',
|
||||
true,
|
||||
'publish',
|
||||
'publish',
|
||||
],
|
||||
0 => [
|
||||
'publish',
|
||||
'COM_INSTALLER_UPDATESITE_DISABLED',
|
||||
'COM_INSTALLER_UPDATESITE_ENABLE',
|
||||
'COM_INSTALLER_UPDATESITE_DISABLED',
|
||||
true,
|
||||
'unpublish',
|
||||
'unpublish',
|
||||
],
|
||||
];
|
||||
|
||||
return HTMLHelper::_('jgrid.state', $states, $value, $i, 'updatesites.', $enabled, true, $checkbox);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\Table;
|
||||
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Downloadkey Table class.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class UpdatesiteTable extends Table
|
||||
{
|
||||
/**
|
||||
* Indicates that columns fully support the NULL value in the database
|
||||
*
|
||||
* @var boolean
|
||||
*
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected $_supportNullValue = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param DatabaseDriver $db Database connector object
|
||||
* @param ?DispatcherInterface $dispatcher Event dispatcher for this table
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct(DatabaseDriver $db, ?DispatcherInterface $dispatcher = null)
|
||||
{
|
||||
$this->typeAlias = 'com_installer.downloadkey';
|
||||
|
||||
parent::__construct('#__update_sites', 'update_site_id', $db, $dispatcher);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\View\Database;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Pagination\Pagination;
|
||||
use Joomla\Component\Installer\Administrator\Model\DatabaseModel;
|
||||
use Joomla\Component\Installer\Administrator\View\Installer\HtmlView as InstallerViewDefault;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Extension Manager Database View
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class HtmlView extends InstallerViewDefault
|
||||
{
|
||||
/**
|
||||
* List of change sets
|
||||
*
|
||||
* @var array
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $changeSet = [];
|
||||
|
||||
/**
|
||||
* The number of errors found
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $errorCount = 0;
|
||||
|
||||
/**
|
||||
* List pagination.
|
||||
*
|
||||
* @var Pagination
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* The filter form
|
||||
*
|
||||
* @var Form
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* A list of form filters
|
||||
*
|
||||
* @var array
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $activeFilters = [];
|
||||
|
||||
/**
|
||||
* Display the view.
|
||||
*
|
||||
* @param string $tpl Template
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Get the application
|
||||
$app = Factory::getApplication();
|
||||
|
||||
// Get data from the model.
|
||||
/** @var DatabaseModel $model */
|
||||
$model = $this->getModel();
|
||||
|
||||
try {
|
||||
$this->changeSet = $model->getItems();
|
||||
} catch (\Exception $exception) {
|
||||
$app->enqueueMessage($exception->getMessage(), 'error');
|
||||
}
|
||||
|
||||
$this->errorCount = $model->getErrorCount();
|
||||
$this->pagination = $model->getPagination();
|
||||
$this->filterForm = $model->getFilterForm();
|
||||
$this->activeFilters = $model->getActiveFilters();
|
||||
|
||||
if ($this->changeSet) {
|
||||
($this->errorCount === 0)
|
||||
? $app->enqueueMessage(Text::_('COM_INSTALLER_MSG_DATABASE_CORE_OK'), 'info')
|
||||
: $app->enqueueMessage(Text::_('COM_INSTALLER_MSG_DATABASE_CORE_ERRORS'), 'warning');
|
||||
}
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$toolbar = $this->getDocument()->getToolbar();
|
||||
|
||||
$toolbar->standardButton('fix', 'COM_INSTALLER_TOOLBAR_DATABASE_FIX', 'database.fix')
|
||||
->listCheck(true)
|
||||
->icon('icon-refresh');
|
||||
$toolbar->divider();
|
||||
|
||||
parent::addToolbar();
|
||||
|
||||
$toolbar->help('Information:_Database');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\View\Discover;
|
||||
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\Component\Installer\Administrator\View\Installer\HtmlView as InstallerViewDefault;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Extension Manager Discover View
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class HtmlView extends InstallerViewDefault
|
||||
{
|
||||
/**
|
||||
* An array of items
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 5.2.0
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* The pagination object
|
||||
*
|
||||
* @var \Joomla\CMS\Pagination\Pagination
|
||||
*
|
||||
* @since 5.2.0
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* Is this view an Empty State
|
||||
*
|
||||
* @var boolean
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private $isEmptyState = false;
|
||||
|
||||
/**
|
||||
* Form object for search filters
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $activeFilters;
|
||||
|
||||
/**
|
||||
* Display the view.
|
||||
*
|
||||
* @param string $tpl Template
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Run discover from the model.
|
||||
if (!$this->getModel()->checkExtensions()) {
|
||||
$this->getModel()->discover();
|
||||
}
|
||||
|
||||
// Get data from the model.
|
||||
$this->items = $this->get('Items');
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->filterForm = $this->get('FilterForm');
|
||||
$this->activeFilters = $this->get('ActiveFilters');
|
||||
|
||||
if (!\count($this->items) && $this->isEmptyState = $this->get('IsEmptyState')) {
|
||||
$this->setLayout('emptystate');
|
||||
}
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$toolbar = $this->getDocument()->getToolbar();
|
||||
|
||||
if (!$this->isEmptyState) {
|
||||
$toolbar->standardButton('upload', 'JTOOLBAR_INSTALL', 'discover.install')
|
||||
->listCheck(true)
|
||||
->icon('icon-upload');
|
||||
}
|
||||
|
||||
$toolbar->standardButton('discover', 'COM_INSTALLER_TOOLBAR_DISCOVER', 'discover.refresh')
|
||||
->icon('icon-refresh');
|
||||
$toolbar->divider();
|
||||
|
||||
parent::addToolbar();
|
||||
|
||||
$toolbar->help('Extensions:_Discover');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\View\Install;
|
||||
|
||||
use Joomla\CMS\Access\Exception\NotAllowed;
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\Component\Installer\Administrator\View\Installer\HtmlView as InstallerViewDefault;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Extension Manager Install View
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class HtmlView extends InstallerViewDefault
|
||||
{
|
||||
/**
|
||||
* Display the view
|
||||
*
|
||||
* @param string $tpl Template
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
if (!$this->getCurrentUser()->authorise('core.admin')) {
|
||||
throw new NotAllowed(Text::_('JERROR_ALERTNOAUTHOR'), 403);
|
||||
}
|
||||
|
||||
$paths = new \stdClass();
|
||||
$paths->first = '';
|
||||
|
||||
$this->paths = &$paths;
|
||||
|
||||
PluginHelper::importPlugin('installer');
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$toolbar = $this->getDocument()->getToolbar();
|
||||
|
||||
if (ContentHelper::getActions('com_installer')->get('core.manage')) {
|
||||
$toolbar->linkButton('list', 'COM_INSTALLER_TOOLBAR_MANAGE')
|
||||
->url('index.php?option=com_installer&view=manage');
|
||||
$toolbar->divider();
|
||||
}
|
||||
|
||||
parent::addToolbar();
|
||||
|
||||
$toolbar->help('Extensions:_Install');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\View\Installer;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Extension Manager Default View
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var \Joomla\Registry\Registry
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $state;
|
||||
|
||||
/**
|
||||
* True if there are extension messages to be displayed
|
||||
*
|
||||
* @var boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $showMessage;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config Configuration array
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function __construct($config = null)
|
||||
{
|
||||
parent::__construct($config);
|
||||
|
||||
$this->_addPath('template', $this->_basePath . '/tmpl/installer');
|
||||
$this->_addPath('template', JPATH_THEMES . '/' . Factory::getApplication()->getTemplate() . '/html/com_installer/installer');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the view.
|
||||
*
|
||||
* @param string $tpl Template
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Get data from the model.
|
||||
$state = $this->get('State');
|
||||
|
||||
// Are there messages to display?
|
||||
$showMessage = false;
|
||||
|
||||
if (\is_object($state)) {
|
||||
$message1 = $state->get('message');
|
||||
$message2 = $state->get('extension_message');
|
||||
$showMessage = ($message1 || $message2);
|
||||
}
|
||||
|
||||
$this->showMessage = $showMessage;
|
||||
$this->state = &$state;
|
||||
|
||||
$this->addToolbar();
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$canDo = ContentHelper::getActions('com_installer');
|
||||
$toolbar = $this->getDocument()->getToolbar();
|
||||
|
||||
ToolbarHelper::title(Text::_('COM_INSTALLER_HEADER_' . strtoupper($this->getName())), 'puzzle-piece install');
|
||||
|
||||
if ($canDo->get('core.admin') || $canDo->get('core.options')) {
|
||||
$toolbar->preferences('com_installer');
|
||||
$toolbar->divider();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\View\Languages;
|
||||
|
||||
use Joomla\CMS\Access\Exception\NotAllowed;
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Language\LanguageHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\Component\Installer\Administrator\View\Installer\HtmlView as InstallerViewDefault;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Extension Manager Language Install View
|
||||
*
|
||||
* @since 2.5.7
|
||||
*/
|
||||
class HtmlView extends InstallerViewDefault
|
||||
{
|
||||
/**
|
||||
* @var object item list
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* @var object pagination information
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* Form object for search filters
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $activeFilters;
|
||||
|
||||
/**
|
||||
* Display the view.
|
||||
*
|
||||
* @param string $tpl template to display
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
if (!$this->getCurrentUser()->authorise('core.admin')) {
|
||||
throw new NotAllowed(Text::_('JERROR_ALERTNOAUTHOR'), 403);
|
||||
}
|
||||
|
||||
// Get data from the model.
|
||||
$this->items = $this->get('Items');
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->filterForm = $this->get('FilterForm');
|
||||
$this->activeFilters = $this->get('ActiveFilters');
|
||||
$this->installedLang = LanguageHelper::getInstalledLanguages();
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$canDo = ContentHelper::getActions('com_languages');
|
||||
$toolbar = $this->getDocument()->getToolbar();
|
||||
|
||||
if ($canDo->get('core.manage')) {
|
||||
$toolbar->linkButton('list', 'COM_INSTALLER_TOOLBAR_MANAGE_LANGUAGES')
|
||||
->url('index.php?option=com_languages&view=installed');
|
||||
$toolbar->linkButton('comments', 'COM_INSTALLER_TOOLBAR_MANAGE_LANGUAGES_CONTENT')
|
||||
->url('index.php?option=com_languages&view=languages');
|
||||
$toolbar->divider();
|
||||
}
|
||||
|
||||
parent::addToolbar();
|
||||
|
||||
$toolbar->help('Extensions:_Languages');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\View\Manage;
|
||||
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\Pagination\Pagination;
|
||||
use Joomla\Component\Installer\Administrator\View\Installer\HtmlView as InstallerViewDefault;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Extension Manager Manage View
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class HtmlView extends InstallerViewDefault
|
||||
{
|
||||
/**
|
||||
* List of updatesites
|
||||
*
|
||||
* @var \stdClass[]
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* Pagination object
|
||||
*
|
||||
* @var Pagination
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* Form object
|
||||
*
|
||||
* @var Form
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* Form object for search filters
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $activeFilters;
|
||||
|
||||
/**
|
||||
* Display the view.
|
||||
*
|
||||
* @param string $tpl Template
|
||||
*
|
||||
* @return mixed|void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Get data from the model.
|
||||
$this->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 GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Display the view.
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$toolbar = $this->getDocument()->getToolbar();
|
||||
$canDo = ContentHelper::getActions('com_installer');
|
||||
|
||||
$dropdown = $toolbar->dropdownButton('status-group')
|
||||
->text('JTOOLBAR_CHANGE_STATUS')
|
||||
->toggleSplit(false)
|
||||
->icon('icon-ellipsis-h')
|
||||
->buttonClass('btn btn-action')
|
||||
->listCheck(true);
|
||||
|
||||
$childBar = $dropdown->getChildToolbar();
|
||||
|
||||
if ($canDo->get('core.edit.state')) {
|
||||
$childBar->publish('manage.publish', 'JTOOLBAR_ENABLE')
|
||||
->listCheck(true);
|
||||
$childBar->unpublish('manage.unpublish', 'JTOOLBAR_DISABLE')
|
||||
->listCheck(true);
|
||||
}
|
||||
|
||||
if ($canDo->get('core.delete')) {
|
||||
$childBar->delete('manage.remove', 'JTOOLBAR_UNINSTALL')
|
||||
->message('COM_INSTALLER_CONFIRM_UNINSTALL')
|
||||
->listCheck(true);
|
||||
}
|
||||
|
||||
$childBar->standardButton('refresh', 'JTOOLBAR_REFRESH_CACHE', 'manage.refresh')
|
||||
->listCheck(true);
|
||||
|
||||
if ($canDo->get('core.manage')) {
|
||||
$toolbar->linkButton('upload', 'COM_INSTALLER_TOOLBAR_INSTALL_EXTENSIONS')
|
||||
->url('index.php?option=com_installer&view=install');
|
||||
$toolbar->linkButton('refresh', 'COM_INSTALLER_TOOLBAR_FIND_UPDATES')
|
||||
->url('index.php?option=com_installer&view=update');
|
||||
$toolbar->divider();
|
||||
}
|
||||
|
||||
parent::addToolbar();
|
||||
$toolbar->help('Extensions:_Manage');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\View\Update;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Object\CMSObject;
|
||||
use Joomla\Component\Installer\Administrator\Helper\InstallerHelper as CmsInstallerHelper;
|
||||
use Joomla\Component\Installer\Administrator\View\Installer\HtmlView as InstallerViewDefault;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Extension Manager Update View
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class HtmlView extends InstallerViewDefault
|
||||
{
|
||||
/**
|
||||
* List of update items.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* List pagination.
|
||||
*
|
||||
* @var \Joomla\CMS\Pagination\Pagination
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* How many updates require but are missing Download Keys
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $missingDownloadKeys = 0;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private $isEmptyState = false;
|
||||
|
||||
/**
|
||||
* Form object for search filters
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $activeFilters;
|
||||
|
||||
/**
|
||||
* Display the view.
|
||||
*
|
||||
* @param string $tpl Template
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Get data from the model.
|
||||
$this->items = $this->get('Items');
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->filterForm = $this->get('FilterForm');
|
||||
$this->activeFilters = $this->get('ActiveFilters');
|
||||
|
||||
$paths = new \stdClass();
|
||||
$paths->first = '';
|
||||
|
||||
$this->paths = &$paths;
|
||||
|
||||
if (\count($this->items) === 0 && $this->isEmptyState = $this->get('IsEmptyState')) {
|
||||
$this->setLayout('emptystate');
|
||||
} else {
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_WARNINGS_UPDATE_NOTICE'), 'warning');
|
||||
}
|
||||
|
||||
// Find if there are any updates which require but are missing a Download Key
|
||||
if (!class_exists('Joomla\Component\Installer\Administrator\Helper\InstallerHelper')) {
|
||||
require_once JPATH_COMPONENT_ADMINISTRATOR . '/Helper/InstallerHelper.php';
|
||||
}
|
||||
|
||||
$mappingCallback = function ($item) {
|
||||
$dlkeyInfo = CmsInstallerHelper::getDownloadKey(new CMSObject($item));
|
||||
$item->isMissingDownloadKey = $dlkeyInfo['supported'] && !$dlkeyInfo['valid'];
|
||||
|
||||
if ($item->isMissingDownloadKey) {
|
||||
$this->missingDownloadKeys++;
|
||||
}
|
||||
|
||||
return $item;
|
||||
};
|
||||
$this->items = array_map($mappingCallback, $this->items);
|
||||
|
||||
if ($this->missingDownloadKeys) {
|
||||
$url = 'index.php?option=com_installer&view=updatesites&filter[supported]=-1';
|
||||
$msg = Text::plural('COM_INSTALLER_UPDATE_MISSING_DOWNLOADKEY_LABEL_N', $this->missingDownloadKeys, $url);
|
||||
Factory::getApplication()->enqueueMessage($msg, CMSApplication::MSG_WARNING);
|
||||
}
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$toolbar = $this->getDocument()->getToolbar();
|
||||
|
||||
if (false === $this->isEmptyState) {
|
||||
$toolbar->standardButton('upload', 'COM_INSTALLER_TOOLBAR_UPDATE', 'update.update')
|
||||
->listCheck(true)
|
||||
->icon('icon-upload');
|
||||
}
|
||||
|
||||
$toolbar->standardButton('search', 'COM_INSTALLER_TOOLBAR_FIND_UPDATES', 'update.find')
|
||||
->listCheck(false)
|
||||
->icon('icon-refresh');
|
||||
|
||||
$toolbar->linkButton('list', 'COM_INSTALLER_TOOLBAR_MANAGE')
|
||||
->url('index.php?option=com_installer&view=manage');
|
||||
|
||||
$toolbar->divider();
|
||||
|
||||
parent::addToolbar();
|
||||
$toolbar->help('Extensions:_Update');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\View\Updatesite;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
use Joomla\Component\Installer\Administrator\Helper\InstallerHelper;
|
||||
use Joomla\Component\Installer\Administrator\Model\UpdatesiteModel;
|
||||
use Joomla\Component\Installer\Administrator\View\Installer\HtmlView as InstallerViewDefault;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* View to edit an update site.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class HtmlView extends InstallerViewDefault
|
||||
{
|
||||
/**
|
||||
* The Form object
|
||||
*
|
||||
* @var Form
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* The active item
|
||||
*
|
||||
* @var object
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $item;
|
||||
|
||||
/**
|
||||
* Display the view.
|
||||
*
|
||||
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
/** @var UpdatesiteModel $model */
|
||||
$model = $this->getModel();
|
||||
$this->form = $model->getForm();
|
||||
$this->item = $model->getItem();
|
||||
|
||||
// Remove the extra_query field if it's a free download extension
|
||||
$dlidSupportingSites = InstallerHelper::getDownloadKeySupportedSites(false);
|
||||
$update_site_id = $this->item->get('update_site_id');
|
||||
|
||||
if (!\in_array($update_site_id, $dlidSupportingSites)) {
|
||||
$this->form->removeField('extra_query');
|
||||
}
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $model->getErrors())) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function addToolbar(): void
|
||||
{
|
||||
$toolbar = $this->getDocument()->getToolbar();
|
||||
$app = Factory::getApplication();
|
||||
$app->getInput()->set('hidemainmenu', true);
|
||||
|
||||
$user = $app->getIdentity();
|
||||
$userId = $user->id;
|
||||
$checkedOut = !(\is_null($this->item->checked_out) || $this->item->checked_out === $userId);
|
||||
|
||||
// Since we don't track these assets at the item level, use the category id.
|
||||
$canDo = ContentHelper::getActions('com_installer', 'updatesite');
|
||||
|
||||
ToolbarHelper::title(Text::_('COM_INSTALLER_UPDATESITE_EDIT_TITLE'), 'address contact');
|
||||
|
||||
// Since it's an existing record, check the edit permission, or fall back to edit own if the owner.
|
||||
$itemEditable = $canDo->get('core.edit');
|
||||
|
||||
// Can't save the record if it's checked out and editable
|
||||
if (!$checkedOut && $itemEditable && $this->form->getField('extra_query')) {
|
||||
$saveGroup = $toolbar->dropdownButton('save-group');
|
||||
|
||||
$saveGroup->configure(
|
||||
function (Toolbar $childBar) {
|
||||
$childBar->apply('updatesite.apply');
|
||||
$childBar->save('updatesite.save');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$toolbar->cancel('updatesite.cancel');
|
||||
$toolbar->help('Edit_Update_Site');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2014 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\View\Updatesites;
|
||||
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\Pagination\Pagination;
|
||||
use Joomla\CMS\Toolbar\Button\DropdownButton;
|
||||
use Joomla\Component\Installer\Administrator\Model\UpdatesitesModel;
|
||||
use Joomla\Component\Installer\Administrator\View\Installer\HtmlView as InstallerViewDefault;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Extension Manager Update Sites View
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
class HtmlView extends InstallerViewDefault
|
||||
{
|
||||
/**
|
||||
* The search tools form
|
||||
*
|
||||
* @var Form
|
||||
* @since 3.4
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
* @since 3.4
|
||||
*/
|
||||
public $activeFilters = [];
|
||||
|
||||
/**
|
||||
* List of updatesites
|
||||
*
|
||||
* @var \stdClass[]
|
||||
* @since 3.4
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
/**
|
||||
* Pagination object
|
||||
*
|
||||
* @var Pagination
|
||||
* @since 3.4
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* Display the view
|
||||
*
|
||||
* @param string $tpl Template
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @throws \Exception on errors
|
||||
*/
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
/** @var UpdatesitesModel $model */
|
||||
$model = $this->getModel();
|
||||
$this->items = $model->getItems();
|
||||
$this->pagination = $model->getPagination();
|
||||
$this->filterForm = $model->getFilterForm();
|
||||
$this->activeFilters = $model->getActiveFilters();
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $model->getErrors())) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Display the view
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function addToolbar(): void
|
||||
{
|
||||
$canDo = ContentHelper::getActions('com_installer');
|
||||
|
||||
// Get the toolbar object instance
|
||||
$toolbar = $this->getDocument()->getToolbar();
|
||||
|
||||
if ($canDo->get('core.edit.state')) {
|
||||
/** @var DropdownButton $dropdown */
|
||||
$dropdown = $toolbar->dropdownButton('status-group', 'JTOOLBAR_CHANGE_STATUS')
|
||||
->toggleSplit(false)
|
||||
->icon('icon-ellipsis-h')
|
||||
->buttonClass('btn btn-action')
|
||||
->listCheck(true);
|
||||
|
||||
$childBar = $dropdown->getChildToolbar();
|
||||
|
||||
$childBar->publish('updatesites.publish', 'JTOOLBAR_ENABLE')->listCheck(true);
|
||||
$childBar->unpublish('updatesites.unpublish', 'JTOOLBAR_DISABLE')->listCheck(true);
|
||||
|
||||
if ($canDo->get('core.delete')) {
|
||||
$childBar->delete('updatesites.delete')->listCheck(true);
|
||||
}
|
||||
|
||||
$childBar->checkin('updatesites.checkin')->listCheck(true);
|
||||
}
|
||||
|
||||
if ($canDo->get('core.admin') || $canDo->get('core.options')) {
|
||||
$toolbar->standardButton('rebuild', 'JTOOLBAR_REBUILD', 'updatesites.rebuild')
|
||||
->listCheck(false)
|
||||
->icon('icon-refresh');
|
||||
}
|
||||
|
||||
parent::addToolbar();
|
||||
|
||||
$toolbar->help('Extensions:_Update_Sites');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2008 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Installer\Administrator\View\Warnings;
|
||||
|
||||
use Joomla\Component\Installer\Administrator\View\Installer\HtmlView as InstallerViewDefault;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Extension Manager Warning View
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class HtmlView extends InstallerViewDefault
|
||||
{
|
||||
/**
|
||||
* Display the view
|
||||
*
|
||||
* @param string $tpl Template
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
$this->messages = $this->get('Items');
|
||||
|
||||
if (!\count($this->messages)) {
|
||||
$this->setLayout('emptystate');
|
||||
}
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$toolbar = $this->getDocument()->getToolbar();
|
||||
|
||||
parent::addToolbar();
|
||||
|
||||
$toolbar->help('Information:_Warnings');
|
||||
}
|
||||
}
|
||||
136
administrator/components/com_installer/tmpl/database/default.php
Normal file
136
administrator/components/com_installer/tmpl/database/default.php
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2011 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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Database\HtmlView $this */
|
||||
|
||||
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->getDocument()->getWebAssetManager();
|
||||
$wa->useScript('table.columns')
|
||||
->useScript('multiselect');
|
||||
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirection = $this->escape($this->state->get('list.direction'));
|
||||
|
||||
?>
|
||||
<div id="installer-database" class="clearfix">
|
||||
<form action="<?php echo Route::_('index.php?option=com_installer&view=database'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this]); ?>
|
||||
<?php if (empty($this->changeSet)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_INSTALLER_DATABASE_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_NAME', 'name', $listDirection, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_LOCATION', 'client_translated', $listDirection, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_TYPE', 'type_translated', $listDirection, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10">
|
||||
<?php echo Text::_('COM_INSTALLER_HEADING_PROBLEMS'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-lg-table-cell text-end">
|
||||
<?php echo Text::_('COM_INSTALLER_HEADING_DATABASE_SCHEMA'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-lg-table-cell">
|
||||
<?php echo Text::_('COM_INSTALLER_HEADING_UPDATE_VERSION'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-lg-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_FOLDER', 'folder_translated', $listDirection, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-1 d-none d-lg-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_ID', 'extension_id', $listDirection, $listOrder); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($this->changeSet as $i => $item) : ?>
|
||||
<?php $extension = $item['extension']; ?>
|
||||
<?php $manifest = json_decode($extension->manifest_cache); ?>
|
||||
|
||||
<tr class="row<?php echo $i % 2; ?>">
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('grid.id', $i, $extension->extension_id, false, 'cid', 'cb', $extension->name); ?>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<?php echo $extension->name; ?>
|
||||
<div class="small">
|
||||
<?php echo Text::_($manifest->description); ?>
|
||||
</div>
|
||||
</th>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $extension->client_translated; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $extension->type_translated; ?>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-<?php echo count($item['results']['error']) ? 'danger' : ($item['errorsCount'] ? 'warning' : 'success'); ?>" tabindex="0">
|
||||
<?php echo Text::plural('COM_INSTALLER_MSG_DATABASE_ERRORS', $item['errorsCount']); ?>
|
||||
</span>
|
||||
<div role="tooltip" id="tip<?php echo $i; ?>">
|
||||
<strong><?php echo Text::plural('COM_INSTALLER_MSG_DATABASE_ERRORS', $item['errorsCount']); ?></strong>
|
||||
<ul><li><?php echo implode('</li><li>', $item['errorsMessage']); ?></li></ul>
|
||||
</div>
|
||||
</td>
|
||||
<td class="d-none d-lg-table-cell text-end">
|
||||
<?php echo $extension->version_id; ?>
|
||||
</td>
|
||||
<td class="d-none d-lg-table-cell">
|
||||
<?php echo '‎' . $extension->version; ?>
|
||||
</td>
|
||||
<td class="d-none d-lg-table-cell">
|
||||
<?php echo $extension->folder_translated; ?>
|
||||
</td>
|
||||
<td class="d-none d-lg-table-cell">
|
||||
<?php echo $extension->extension_id; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_INSTALLER_DATABASE_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_INSTALLER_DATABASE_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
<fields name="params">
|
||||
<fieldset name="basic" label="JOPTIONS">
|
||||
<field
|
||||
name="ajax-badge"
|
||||
type="radio"
|
||||
label="COM_INSTALLER_DATABASE_VIEW_DISPLAY_BADGE"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default=""
|
||||
>
|
||||
<option value="">JHIDE</option>
|
||||
<option value="index.php?option=com_installer&task=database.getMenuBadgeData&format=json">JSHOW</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</metadata>
|
||||
131
administrator/components/com_installer/tmpl/discover/default.php
Normal file
131
administrator/components/com_installer/tmpl/discover/default.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2008 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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Discover\HtmlView $this */
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->getDocument()->getWebAssetManager();
|
||||
$wa->useScript('table.columns')
|
||||
->useScript('multiselect');
|
||||
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
?>
|
||||
<div id="installer-discover" class="clearfix">
|
||||
<form action="<?php echo Route::_('index.php?option=com_installer&view=discover'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php if ($this->showMessage) : ?>
|
||||
<?php echo $this->loadTemplate('message'); ?>
|
||||
<?php endif; ?>
|
||||
<?php echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this]); ?>
|
||||
<?php if (empty($this->items)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('COM_INSTALLER_MSG_DISCOVER_DESCRIPTION'); ?>
|
||||
</div>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_INSTALLER_DISCOVER_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_NAME', 'name', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_LOCATION', 'client_translated', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_TYPE', 'type_translated', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo Text::_('JVERSION'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo Text::_('JDATE'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-15 d-none d-md-table-cell">
|
||||
<?php echo Text::_('JAUTHOR'); ?>
|
||||
</th>
|
||||
<th scope="col" class="d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_FOLDER', 'folder_translated', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-1 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ID', 'extension_id', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($this->items as $i => $item) : ?>
|
||||
<tr class="row<?php echo $i % 2; ?>">
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('grid.id', $i, $item->extension_id, false, 'cid', 'cb', $item->name); ?>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<?php echo $item->name; ?>
|
||||
<div class="small"><?php echo $item->description; ?></div>
|
||||
</th>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->client_translated; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $item->type_translated; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo !empty($item->version) ? $item->version : ' '; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo !empty($item->creationDate) ? $item->creationDate : ' '; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo !empty($item->author) ? $item->author : ' '; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->folder_translated; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->extension_id; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_INSTALLER_DISCOVER_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_INSTALLER_DISCOVER_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
<fields name="params">
|
||||
<fieldset name="basic" label="JOPTIONS">
|
||||
<field
|
||||
name="ajax-badge"
|
||||
type="radio"
|
||||
label="COM_INSTALLER_DISCOVER_VIEW_DISPLAY_BADGE"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default=""
|
||||
>
|
||||
<option value="">JHIDE</option>
|
||||
<option value="index.php?option=com_installer&task=discover.getMenuBadgeData&format=json">JSHOW</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</metadata>
|
||||
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2021 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;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Session\Session;
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Discover\HtmlView $this */
|
||||
|
||||
$displayData = [
|
||||
'textPrefix' => 'COM_INSTALLER',
|
||||
'formURL' => 'index.php?option=com_installer&task=discover.refresh',
|
||||
'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Extensions:_Discover',
|
||||
'icon' => 'icon-puzzle-piece install',
|
||||
'createURL' => 'index.php?option=com_installer&task=discover.refresh&' . Session::getFormToken() . '=1',
|
||||
'content' => Text::_('COM_INSTALLER_MSG_DISCOVER_DESCRIPTION'),
|
||||
'title' => Text::_('COM_INSTALLER_EMPTYSTATE_DISCOVER_TITLE'),
|
||||
'btnadd' => Text::_('COM_INSTALLER_EMPTYSTATE_DISCOVER_BUTTON_ADD'),
|
||||
];
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Discover\HtmlView $this */
|
||||
if ($this->showMessage) {
|
||||
echo $this->loadTemplate('message');
|
||||
}
|
||||
|
||||
echo LayoutHelper::render('joomla.content.emptystate', $displayData);
|
||||
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2006 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\Event\Installer\AddInstallationTabEvent;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Install\HtmlView $this */
|
||||
|
||||
// Load JavaScript message titles
|
||||
Text::script('ERROR');
|
||||
Text::script('WARNING');
|
||||
Text::script('NOTICE');
|
||||
Text::script('MESSAGE');
|
||||
|
||||
Text::script('COM_INSTALLER_MSG_INSTALL_ENTER_A_URL');
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->getDocument()->getWebAssetManager();
|
||||
$wa->useScript('core')
|
||||
->usePreset('com_installer.installer')
|
||||
->useScript('webcomponent.core-loader');
|
||||
|
||||
$tabs = Factory::getApplication()->getDispatcher()
|
||||
->dispatch('onInstallerAddInstallationTab', new AddInstallationTabEvent('onInstallerAddInstallationTab', []))
|
||||
->getArgument('result', []);
|
||||
|
||||
?>
|
||||
<div id="installer-install" class="clearfix">
|
||||
|
||||
<form enctype="multipart/form-data" action="<?php echo Route::_('index.php?option=com_installer&view=install'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<?php // Render messages set by extension install scripts here ?>
|
||||
<?php if ($this->showMessage) : ?>
|
||||
<?php echo $this->loadTemplate('message'); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container main-card">
|
||||
<?php if (!$tabs) : ?>
|
||||
<div class="alert alert-warning">
|
||||
<span class="icon-exclamation-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('WARNING'); ?></span>
|
||||
<?php echo Text::_('COM_INSTALLER_NO_INSTALLATION_PLUGINS_FOUND'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($tabs) : ?>
|
||||
<?php echo HTMLHelper::_('uitab.startTabSet', 'myTab', ['active' => $tabs[0]['name'] ?? '', 'recall' => true, 'breakpoint' => 768]); ?>
|
||||
<?php // Show installation tabs ?>
|
||||
<?php foreach ($tabs as $tab) : ?>
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', $tab['name'], $tab['label']); ?>
|
||||
<fieldset class="uploadform option-fieldset options-form">
|
||||
<?php echo $tab['content']; ?>
|
||||
</fieldset>
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.endTabSet'); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<input type="hidden" name="installtype" value="">
|
||||
<input type="hidden" name="task" value="install.install">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="loading"></div>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_INSTALLER_INSTALL_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_INSTALLER_INSTALL_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
</metadata>
|
||||
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Installer\HtmlView $this */
|
||||
|
||||
$state = $this->get('State');
|
||||
$message1 = $state->get('message');
|
||||
$message2 = $state->get('extension_message');
|
||||
?>
|
||||
|
||||
<?php if ($message1) : ?>
|
||||
<div class="alert alert-info">
|
||||
<strong><?php echo $message1; ?></strong>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($message2) : ?>
|
||||
<div class="alert alert-info">
|
||||
<?php echo $message2; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2006 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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Version;
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Languages\HtmlView $this */
|
||||
|
||||
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->getDocument()->getWebAssetManager();
|
||||
$wa->useScript('table.columns')
|
||||
->useScript('multiselect')
|
||||
->useScript('webcomponent.core-loader');
|
||||
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
?>
|
||||
<div id="installer-languages" class="clearfix">
|
||||
<form action="<?php echo Route::_('index.php?option=com_installer&view=languages'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this, 'options' => ['filterButton' => false]]); ?>
|
||||
<?php if (empty($this->items)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_INSTALLER_LANGUAGES_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-5"></td>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_LANGUAGE', 'name', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 text-center">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_LANGUAGE_TAG', 'element', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-15 d-none d-md-table-cell">
|
||||
<?php echo Text::_('JVERSION'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-35 d-none d-md-table-cell">
|
||||
<?php echo Text::_('COM_INSTALLER_HEADING_DETAILS_URL'); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$version = new Version();
|
||||
$currentShortVersion = preg_replace('#^([0-9\.]+)(|.*)$#', '$1', $version->getShortVersion());
|
||||
$i = 0;
|
||||
foreach ($this->items as $language) :
|
||||
preg_match('#^pkg_([a-z]{2,3}-[A-Z]{2})$#', $language->element, $element);
|
||||
$language->code = $element[1];
|
||||
?>
|
||||
<tr class="row<?php echo $i % 2; ?>">
|
||||
<td>
|
||||
<?php $buttonText = (isset($this->installedLang[0][$language->code]) || isset($this->installedLang[1][$language->code])) ? 'REINSTALL' : 'INSTALL'; ?>
|
||||
<?php $buttonClass = (isset($this->installedLang[0][$language->code]) || isset($this->installedLang[1][$language->code])) ? 'btn btn-success btn-sm' : 'btn btn-primary btn-sm'; ?>
|
||||
<?php $onclick = 'document.getElementById(\'install_url\').value = \'' . $language->detailsurl . '\'; Joomla.submitbutton(\'install.install\'); document.body.appendChild(document.createElement(\'joomla-core-loader\'));'; ?>
|
||||
<input type="button"
|
||||
class="<?php echo $buttonClass; ?>"
|
||||
value="<?php echo Text::_('COM_INSTALLER_' . $buttonText . '_BUTTON'); ?>"
|
||||
aria-label="<?php echo Text::sprintf('COM_INSTALLER_' . $buttonText . '_ARIA', $language->name); ?>"
|
||||
onclick="<?php echo $onclick; ?>"
|
||||
>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<?php echo $language->name; ?>
|
||||
</th>
|
||||
<td class="text-center">
|
||||
<?php echo $language->code; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php $minorVersion = $version::MAJOR_VERSION . '.' . $version::MINOR_VERSION; ?>
|
||||
<?php // Display a Note if language pack version is not equal to Joomla version ?>
|
||||
<?php if (strpos($language->version, $minorVersion) !== 0 || strpos($language->version, $currentShortVersion) !== 0) : ?>
|
||||
<span class="badge bg-warning"><?php echo $language->version; ?></span>
|
||||
<span class="icon-info-circle" aria-hidden="true" tabindex="0"></span>
|
||||
<div role="tooltip" class="text-start" id="tip<?php echo $language->code; ?>">
|
||||
<?php echo Text::_('JGLOBAL_LANGUAGE_VERSION_NOT_PLATFORM'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<span class="badge bg-success"><?php echo $language->version; ?></span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="small d-none d-md-table-cell">
|
||||
<a href="<?php echo $language->detailsurl; ?>" target="_blank" rel="noopener noreferrer"><?php echo $language->detailsurl; ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php $i++; ?>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="return" value="<?php echo base64_encode('index.php?option=com_installer&view=languages') ?>">
|
||||
<input type="hidden" id="install_url" name="install_url">
|
||||
<input type="hidden" name="installtype" value="url">
|
||||
<input type="hidden" name="package" value="language">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_INSTALLER_LANGUAGES_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_INSTALLER_LANGUAGES_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
</metadata>
|
||||
184
administrator/components/com_installer/tmpl/manage/default.php
Normal file
184
administrator/components/com_installer/tmpl/manage/default.php
Normal file
@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2008 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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Manage\HtmlView $this */
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->getDocument()->getWebAssetManager();
|
||||
$wa->useScript('table.columns')
|
||||
->useScript('multiselect')
|
||||
->useScript('joomla.dialog-autocreate');
|
||||
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
?>
|
||||
<div id="installer-manage" class="clearfix">
|
||||
<form action="<?php echo Route::_('index.php?option=com_installer&view=manage'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php if ($this->showMessage) : ?>
|
||||
<?php echo $this->loadTemplate('message'); ?>
|
||||
<?php endif; ?>
|
||||
<?php echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this]); ?>
|
||||
<?php if (empty($this->items)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table" id="manageList">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_INSTALLER_MANAGE_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 'status', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_NAME', 'name', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_LOCATION', 'client_translated', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_TYPE', 'type_translated', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo Text::_('JVERSION'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JDATE', 'creationDate', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo Text::_('JAUTHOR'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-5 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_FOLDER', 'folder_translated', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-1 d-none d-md-table-cell">
|
||||
<?php echo Text::_('COM_INSTALLER_HEADING_LOCKED'); ?>
|
||||
</th>
|
||||
<th scope="col" class="d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_PACKAGE_ID', 'package_id', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-1 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_ID', 'extension_id', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php $createdDateFormat = Text::_('DATE_FORMAT_LC4'); ?>
|
||||
<?php foreach ($this->items as $i => $item) : ?>
|
||||
<tr class="row<?php echo $i % 2;
|
||||
if ($item->status == 2) {
|
||||
echo ' protected';
|
||||
} ?>">
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('grid.id', $i, $item->extension_id, false, 'cid', 'cb', $item->name); ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php if (!$item->element) : ?>
|
||||
<strong>X</strong>
|
||||
<?php else : ?>
|
||||
<?php echo HTMLHelper::_('manage.state', $item->status, $i, $item->status < 2, 'cb'); ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<span tabindex="0"><?php echo $item->name; ?></span>
|
||||
<?php if ($item->description) : ?>
|
||||
<div role="tooltip" id="tip<?php echo $i; ?>">
|
||||
<?php echo $item->description; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</th>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->client_translated; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $item->type_translated; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php if (!empty($item->version)) : ?>
|
||||
<?php if (!empty($item->changelogurl)) :
|
||||
$popupOptions = [
|
||||
'popupType' => 'ajax',
|
||||
'textHeader' => Text::sprintf('COM_INSTALLER_CHANGELOG_TITLE', $item->name, $item->version),
|
||||
'src' => Route::_('index.php?option=com_installer&task=manage.loadChangelogRaw&eid=' . $item->extension_id . '&source=manage&format=raw', false),
|
||||
'width' => '800px',
|
||||
'height' => 'fit-content',
|
||||
];
|
||||
?>
|
||||
<button type="button" class="btn btn-info btn-sm"
|
||||
data-joomla-dialog="<?php echo $this->escape(json_encode($popupOptions, JSON_UNESCAPED_SLASHES)); ?>">
|
||||
<?php echo $item->version; ?></button>
|
||||
<?php else : ?>
|
||||
<?php echo $item->version; ?>
|
||||
<?php endif; ?>
|
||||
<?php else :
|
||||
echo ' ';
|
||||
endif; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php if (!empty($item->creationDate)) : ?>
|
||||
<?php try {
|
||||
echo HTMLHelper::date($item->creationDate, $createdDateFormat);
|
||||
} catch (Exception $e) {
|
||||
echo $item->creationDate;
|
||||
}?>
|
||||
<?php else : ?>
|
||||
<?php echo ' '; ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo !empty($item->author) ? $item->author : ' '; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->folder_translated; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->locked ? Text::_('JYES') : Text::_('JNO'); ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->package_id ?: ' '; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->extension_id; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_INSTALLER_MANAGE_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_INSTALLER_MANAGE_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
</metadata>
|
||||
163
administrator/components/com_installer/tmpl/update/default.php
Normal file
163
administrator/components/com_installer/tmpl/update/default.php
Normal file
@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2008 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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Update\HtmlView $this */
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->getDocument()->getWebAssetManager();
|
||||
$wa->useScript('multiselect')
|
||||
->useScript('table.columns')
|
||||
->useScript('joomla.dialog-autocreate');
|
||||
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
?>
|
||||
<div id="installer-update" class="clearfix">
|
||||
<form action="<?php echo Route::_('index.php?option=com_installer&view=update'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php if ($this->showMessage) : ?>
|
||||
<?php echo $this->loadTemplate('message'); ?>
|
||||
<?php endif; ?>
|
||||
<?php echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this]); ?>
|
||||
<?php if (empty($this->items)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('COM_INSTALLER_MSG_UPDATE_NOUPDATES'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_INSTALLER_UPDATE_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_NAME', 'u.name', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_LOCATION', 'client_translated', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_TYPE', 'type_translated', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo Text::_('COM_INSTALLER_CURRENT_VERSION'); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo Text::_('COM_INSTALLER_NEW_VERSION'); ?>
|
||||
</th>
|
||||
<th scope="col" class="d-none d-md-table-cell">
|
||||
<?php echo Text::_('COM_INSTALLER_CHANGELOG'); ?>
|
||||
</th>
|
||||
<th scope="col" class="d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_FOLDER', 'folder_translated', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="d-none d-md-table-cell">
|
||||
<?php echo Text::_('COM_INSTALLER_HEADING_INSTALLTYPE'); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach ($this->items as $i => $item) : ?>
|
||||
<tr class="row<?php echo $i % 2; ?>">
|
||||
<td class="text-center">
|
||||
<?php if ($item->isMissingDownloadKey) : ?>
|
||||
<span class="icon-ban"></span>
|
||||
<?php else : ?>
|
||||
<?php echo HTMLHelper::_('grid.id', $i, $item->update_id, false, 'cid', 'cb', $item->name); ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<span tabindex="0"><?php echo $this->escape($item->name); ?></span>
|
||||
<div role="tooltip" id="tip<?php echo $i; ?>">
|
||||
<?php echo $item->description; ?>
|
||||
</div>
|
||||
<div class="small break-word">
|
||||
<?php echo $item->detailsurl; ?>
|
||||
<?php if (!empty($item->infourl)) : ?>
|
||||
<br>
|
||||
<a href="<?php echo $item->infourl; ?>" target="_blank" rel="noopener noreferrer"><?php echo $this->escape(trim($item->infourl)); ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php if ($item->isMissingDownloadKey) : ?>
|
||||
<?php $url = 'index.php?option=com_installer&task=updatesite.edit&update_site_id=' . (int) $item->update_site_id; ?>
|
||||
<a class="btn btn-danger btn-sm text-decoration-none" href="<?php echo Route::_($url); ?>"><?php echo Text::_('COM_INSTALLER_DOWNLOADKEY_MISSING_LABEL'); ?></a>
|
||||
<?php endif; ?>
|
||||
</th>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->client_translated; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->type_translated; ?>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-warning"><?php echo $item->current_version; ?></span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge bg-success"><?php echo $item->version; ?></span>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell text-center">
|
||||
<?php if (!empty($item->changelogurl)) :
|
||||
$popupOptions = [
|
||||
'popupType' => 'ajax',
|
||||
'textHeader' => Text::sprintf('COM_INSTALLER_CHANGELOG_TITLE', $item->name, $item->version),
|
||||
'src' => Route::_('index.php?option=com_installer&task=manage.loadChangelogRaw&eid=' . $item->extension_id . '&source=update&format=raw', false),
|
||||
'width' => '800px',
|
||||
'height' => 'fit-content',
|
||||
];
|
||||
?>
|
||||
<button type="button" class="btn btn-info btn-sm"
|
||||
data-joomla-dialog="<?php echo $this->escape(json_encode($popupOptions, JSON_UNESCAPED_SLASHES)); ?>">
|
||||
<?php echo Text::_('COM_INSTALLER_CHANGELOG'); ?></button>
|
||||
<?php else :?>
|
||||
<span>
|
||||
<?php echo Text::_('COM_INSTALLER_TYPE_NONAPPLICABLE')?>
|
||||
</span>
|
||||
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->folder_translated; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->install_type; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_INSTALLER_UPDATE_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_INSTALLER_UPDATE_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
<fields name="params">
|
||||
<fieldset name="basic" label="JOPTIONS">
|
||||
<field
|
||||
name="ajax-badge"
|
||||
type="radio"
|
||||
label="COM_INSTALLER_UPDATE_VIEW_DISPLAY_BADGE"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default=""
|
||||
>
|
||||
<option value="">JHIDE</option>
|
||||
<option value="index.php?option=com_installer&task=update.getMenuBadgeData&format=json">JSHOW</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</metadata>
|
||||
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2021 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\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Session\Session;
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Update\HtmlView $this */
|
||||
|
||||
$displayData = [
|
||||
'textPrefix' => 'COM_INSTALLER',
|
||||
'formURL' => 'index.php?option=com_installer&view=update',
|
||||
'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Extensions:_Update',
|
||||
'icon' => 'icon-puzzle-piece install',
|
||||
];
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
|
||||
if ($user->authorise('core.create', 'com_content') || count($user->getAuthorisedCategories('com_content', 'core.create')) > 0) {
|
||||
$displayData['createURL'] = 'index.php?option=com_installer&task=update.find&' . Session::getFormToken() . '=1';
|
||||
}
|
||||
|
||||
echo LayoutHelper::render('joomla.content.emptystate', $displayData);
|
||||
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2019 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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Updatesite\HtmlView $this */
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->getDocument()->getWebAssetManager();
|
||||
$wa->useScript('form.validate');
|
||||
|
||||
?>
|
||||
<h2><?php echo $this->item->name; ?></h2>
|
||||
<form action="<?php echo Route::_('index.php?option=com_installer&view=updatesite&layout=edit&update_site_id=' . (int) $this->item->update_site_id); ?>" method="post" name="adminForm" id="adminForm" aria-label="<?php echo Text::_('COM_INSTALLER_UPDATE_FORM_EDIT'); ?>" class="main-card p-4 form-validate">
|
||||
<?php echo $this->form->renderFieldset('updateSite'); ?>
|
||||
<input type="hidden" name="task" value=""/>
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</form>
|
||||
@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2014 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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Updatesites\HtmlView $this */
|
||||
|
||||
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->getDocument()->getWebAssetManager();
|
||||
$wa->useScript('table.columns')
|
||||
->useScript('multiselect');
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
$userId = $user->id;
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
?>
|
||||
<div id="installer-manage" class="clearfix">
|
||||
<form action="<?php echo Route::_('index.php?option=com_installer&view=updatesites'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this]); ?>
|
||||
<?php if (empty($this->items)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_INSTALLER_UPDATESITES_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 'enabled', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_UPDATESITE_NAME', 'update_site_name', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-20 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_NAME', 'name', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_LOCATION', 'client_translated', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_TYPE', 'type_translated', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_INSTALLER_HEADING_FOLDER', 'folder_translated', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-5 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ID', 'update_site_id', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($this->items as $i => $item) :
|
||||
$canCheckin = $user->authorise('core.manage', 'com_checkin')
|
||||
|| $item->checked_out === $userId
|
||||
|| is_null($item->checked_out);
|
||||
$canEdit = $user->authorise('core.edit', 'com_installer');
|
||||
?>
|
||||
<tr class="row<?php echo $i % 2;
|
||||
if ((int) $item->enabled === 2) {
|
||||
echo ' protected';
|
||||
} ?>">
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('grid.id', $i, $item->update_site_id, false, 'cid', 'cb', $item->update_site_name); ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php if (!$item->element) : ?>
|
||||
<strong>X</strong>
|
||||
<?php else : ?>
|
||||
<?php echo HTMLHelper::_('updatesites.state', $item->enabled, $i, $item->enabled < 2, 'cb'); ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<?php if ($item->checked_out) : ?>
|
||||
<?php echo HTMLHelper::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'updatesites.', $canCheckin); ?>
|
||||
<?php endif; ?>
|
||||
<?php if ($canEdit) : ?>
|
||||
<a
|
||||
href="<?php echo Route::_('index.php?option=com_installer&task=updatesite.edit&update_site_id=' . (int) $item->update_site_id); ?>"
|
||||
title="<?php echo Text::_('JACTION_EDIT'); ?> <?php echo $this->escape($item->update_site_name); ?>"
|
||||
>
|
||||
<?php echo Text::_($item->update_site_name); ?>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<?php echo Text::_($item->update_site_name); ?>
|
||||
<?php endif; ?>
|
||||
<div class="small break-word">
|
||||
<a href="<?php echo $item->location; ?>" target="_blank" rel="noopener noreferrer"><?php echo $this->escape($item->location); ?></a>
|
||||
</div>
|
||||
<div class="small break-word">
|
||||
<?php if ($item->downloadKey['valid']) : ?>
|
||||
<span class="badge bg-info">
|
||||
<?php echo Text::_('COM_INSTALLER_DOWNLOADKEY_EXTRA_QUERY_LABEL'); ?>
|
||||
</span>
|
||||
<code><?php echo $item->downloadKey['value']; ?></code>
|
||||
<?php elseif ($item->downloadKey['supported']) : ?>
|
||||
<span class="badge bg-danger" tabindex="0">
|
||||
<?php echo Text::_('COM_INSTALLER_DOWNLOADKEY_MISSING_LABEL'); ?>
|
||||
</span>
|
||||
<div role="tooltip" id="tip-missing<?php echo $i; ?>">
|
||||
<?php echo Text::_('COM_INSTALLER_DOWNLOADKEY_MISSING_TIP'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</th>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<span tabindex="0">
|
||||
<?php echo $item->name; ?>
|
||||
</span>
|
||||
<?php if ($item->description) : ?>
|
||||
<div role="tooltip" id="tip<?php echo $i; ?>">
|
||||
<?php echo $item->description; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->client_translated; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->type_translated; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->folder_translated; ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->update_site_id; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php // Load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_INSTALLER_UPDATESITES_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_INSTALLER_UPDATESITES_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
</metadata>
|
||||
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2008 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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var \Joomla\Component\Installer\Administrator\View\Warnings\HtmlView $this */
|
||||
?>
|
||||
<div id="installer-warnings" class="clearfix">
|
||||
<form action="<?php echo Route::_('index.php?option=com_installer&view=warnings'); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php if (count($this->messages)) : ?>
|
||||
<?php foreach ($this->messages as $message) : ?>
|
||||
<div class="alert alert-warning">
|
||||
<h4 class="alert-heading">
|
||||
<span class="icon-exclamation-triangle" aria-hidden="true"></span>
|
||||
<span class="visually-hidden"><?php echo Text::_('WARNING'); ?></span>
|
||||
<?php echo $message['message']; ?>
|
||||
</h4>
|
||||
<p class="mb-0"><?php echo $message['description']; ?></p>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<div class="alert alert-info">
|
||||
<h4 class="alert-heading">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span>
|
||||
<span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('COM_INSTALLER_MSG_WARNINGFURTHERINFO'); ?>
|
||||
</h4>
|
||||
<p class="mb-0"><?php echo Text::_('COM_INSTALLER_MSG_WARNINGFURTHERINFODESC'); ?></p>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span>
|
||||
<span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('COM_INSTALLER_MSG_WARNINGS_NONE'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div>
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_INSTALLER_WARNINGS_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_INSTALLER_WARNINGS_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
<fields name="params">
|
||||
<fieldset name="basic" label="JOPTIONS">
|
||||
<field
|
||||
name="ajax-badge"
|
||||
type="radio"
|
||||
label="COM_INSTALLER_WARNINGS_VIEW_DISPLAY_BADGE"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default=""
|
||||
>
|
||||
<option value="">JHIDE</option>
|
||||
<option value="index.php?option=com_installer&task=getMenuBadgeData&format=json">JSHOW</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</metadata>
|
||||
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_installer
|
||||
*
|
||||
* @copyright (C) 2021 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;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
|
||||
$displayData = [
|
||||
'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Information:_Warnings',
|
||||
'icon' => 'icon-puzzle-piece install',
|
||||
'title' => Text::_('COM_INSTALLER_MSG_WARNINGS_NONE'),
|
||||
'content' => '',
|
||||
];
|
||||
|
||||
echo LayoutHelper::render('joomla.content.emptystate', $displayData);
|
||||
Reference in New Issue
Block a user