diff options
| -rw-r--r-- | phpBB/adm/style/acp_ext_details.html | 35 | ||||
| -rw-r--r-- | phpBB/adm/style/acp_ext_list.html | 24 | ||||
| -rw-r--r-- | phpBB/includes/acp/acp_extensions.php | 137 | ||||
| -rw-r--r-- | phpBB/language/en/acp/extensions.php | 7 | ||||
| -rw-r--r-- | phpBB/phpbb/extension/version_helper.php | 257 |
5 files changed, 429 insertions, 31 deletions
diff --git a/phpBB/adm/style/acp_ext_details.html b/phpBB/adm/style/acp_ext_details.html index 6aff4b29cc..435c36ccc6 100644 --- a/phpBB/adm/style/acp_ext_details.html +++ b/phpBB/adm/style/acp_ext_details.html @@ -6,6 +6,19 @@ <h1>{L_EXTENSIONS_ADMIN}</h1> + <!-- IF S_VERSIONCHECK_FAIL --> + <div class="errorbox notice"> + <p>{L_VERSIONCHECK_FAIL}</p> + <p>{VERSIONCHECK_FAIL_REASON}</p> + <p><a href="{U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE}</a></p> + </div> + <!-- ENDIF --> + <!-- IF S_VERSIONCHECK --> + <div class="<!-- IF S_UP_TO_DATE -->successbox<!-- ELSE -->errorbox<!-- ENDIF -->"> + <p>{UP_TO_DATE_MSG} - <a href="{U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE}</a></p> + </div> + <!-- ENDIF --> + <fieldset> <legend>{L_EXT_DETAILS}</legend> <!-- IF META_DISPLAY_NAME --> @@ -46,6 +59,28 @@ </dl> </fieldset> + <!-- IF S_VERSIONCHECK && not S_UP_TO_DATE --> + <fieldset> + <legend>{L_LATEST_VERSION}</legend> + <dl> + <dt><label>{L_VERSION}{L_COLON}</label></dt> + <dd><span id="latest_version">{LATEST_VERSION}</span></dd> + </dl> + <!-- IF LATEST_DOWNLOAD --> + <dl> + <dt><label>{L_DOWNLOAD_LATEST}</label></dt> + <dd><strong id="latest_download"><a href="{LATEST_DOWNLOAD}">{L_DOWNLOAD} {META_NAME} {LATEST_VERSION}</a></strong></dd> + </dl> + <!-- ENDIF --> + <!-- IF LATEST_ANNOUNCEMENT --> + <dl> + <dt><label>{L_ANNOUNCEMENT_TOPIC}</label></dt> + <dd><strong id="latest_announcement"><a href="{LATEST_ANNOUNCEMENT}">{L_RELEASE_ANNOUNCEMENT}</a></strong></dd> + </dl> + <!-- ENDIF --> + </fieldset> + <!-- ENDIF --> + <!-- IF META_REQUIRE_PHPBB || META_REQUIRE_PHP --> <fieldset> <legend>{L_REQUIREMENTS}</legend> diff --git a/phpBB/adm/style/acp_ext_list.html b/phpBB/adm/style/acp_ext_list.html index 2fcc6eab31..d612a959e8 100644 --- a/phpBB/adm/style/acp_ext_list.html +++ b/phpBB/adm/style/acp_ext_list.html @@ -7,22 +7,30 @@ <p>{L_EXTENSIONS_EXPLAIN}</p> <table class="table1"> - <col class="row1" ><col class="row2" ><col class="row2" > + <col class="row1" ><col class="row1" ><col class="row1" ><col class="row2" ><col class="row2" > <thead> <tr> <th>{L_EXTENSION_NAME}</th> - <th>{L_EXTENSION_OPTIONS}</th> - <th>{L_EXTENSION_ACTIONS}</th> + <th width="10%">{L_CURRENT_VERSION}</th> + <th width="10%">{L_LATEST_VERSION}</th> + <th width="10%">{L_EXTENSION_OPTIONS}</th> + <th width="10%">{L_EXTENSION_ACTIONS}</th> </tr> </thead> <tbody> <!-- IF .enabled --> <tr> - <td class="row3" colspan="3"><strong>{L_EXTENSIONS_ENABLED}</strong></td> + <td class="row3" colspan="5"><strong>{L_EXTENSIONS_ENABLED}</strong></td> </tr> <!-- BEGIN enabled --> <tr class="ext_enabled"> <td><strong>{enabled.META_DISPLAY_NAME}</strong></td> + <td style="text-align: center;">{enabled.META_VERSION}</td> + <td style="text-align: center;"> + <!-- IF enabled.S_VERSIONCHECK --> + <strong <!-- IF enabled.S_UP_TO_DATE -->style="color: #228822;"<!-- ELSE -->style="color: #BC2A4D;"<!-- ENDIF -->>{enabled.LATEST_VERSION}</strong> [ <a href="{enabled.U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE}</a> ] + <!-- ENDIF --> + </td> <td style="text-align: center;"><a href="{enabled.U_DETAILS}">{L_DETAILS}</a></td> <td style="text-align: center;"> <!-- BEGIN actions --> @@ -36,11 +44,17 @@ <!-- IF .disabled --> <tr> - <td class="row3" colspan="3"><strong>{L_EXTENSIONS_DISABLED}</strong></td> + <td class="row3" colspan="5"><strong>{L_EXTENSIONS_DISABLED}</strong></td> </tr> <!-- BEGIN disabled --> <tr class="ext_disabled"> <td><strong>{disabled.META_DISPLAY_NAME}</strong></td> + <td style="text-align: center;">{disabled.META_VERSION}</td> + <td style="text-align: center;"> + <!-- IF disabled.S_VERSIONCHECK --> + <strong <!-- IF disabled.S_UP_TO_DATE -->style="color: #228822;"<!-- ELSE -->style="color: #BC2A4D;"<!-- ENDIF -->>{disabled.LATEST_VERSION}</strong> [ <a href="{U_VERSIONCHECK_FORCE}">{L_VERSIONCHECK_FORCE_UPDATE}</a> ] + <!-- ENDIF --> + </td> <td style="text-align: center;"> <!-- IF disabled.U_DETAILS --><a href="{disabled.U_DETAILS}">{L_DETAILS}</a><!-- ENDIF --> </td> diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index 9033fbbe60..ac26621b89 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -27,17 +27,19 @@ class acp_extensions private $config; private $template; private $user; + private $cache; private $log; function main() { // Start the page - global $config, $user, $template, $request, $phpbb_extension_manager, $db, $phpbb_root_path, $phpEx, $phpbb_log; + global $config, $user, $template, $request, $phpbb_extension_manager, $db, $phpbb_root_path, $phpEx, $phpbb_log, $cache; $this->db = $db; $this->config = $config; $this->template = $template; $this->user = $user; + $this->cache = $cache; $this->log = $phpbb_log; $user->add_lang(array('install', 'acp/extensions', 'migrator')); @@ -247,7 +249,24 @@ class acp_extensions // Output it to the template $md_manager->output_template_data(); - $template->assign_var('U_BACK', $this->u_action . '&action=list'); + try + { + $infos = array(); + $this->version_check($md_manager, $infos, $request->variable('versioncheck_force', false)); + $template->assign_vars($infos); + } + catch (\RuntimeException $e) + { + $template->assign_vars(array( + 'S_VERSIONCHECK_FAIL' => true, + 'VERSIONCHECK_FAIL_REASON' => ($e->getMessage() !== $user->lang('VERSIONCHECK_FAIL')) ? $e->getMessage() : '', + )); + } + + $template->assign_vars(array( + 'U_BACK' => $this->u_action . '&action=list', + 'U_VERSIONCHECK_FORCE' => $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')), + )); $this->tpl_name = 'acp_ext_details'; break; @@ -270,25 +289,31 @@ class acp_extensions try { - $enabled_extension_meta_data[$name] = $md_manager->get_metadata('display-name'); + $meta = $md_manager->get_metadata('all'); + $enabled_extension_meta_data[$name] = array( + 'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'), + 'META_VERSION' => $meta['version'], + ); + + $this->version_check($md_manager, $enabled_extension_meta_data[$name]); } catch(\phpbb\extension\exception $e) { $this->template->assign_block_vars('disabled', array( 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), + 'S_VERSIONCHECK' => false, )); } } - natcasesort($enabled_extension_meta_data); + uasort($enabled_extension_meta_data, array('self', 'sort_extension_meta_data_table')); - foreach ($enabled_extension_meta_data as $name => $display_name) + foreach ($enabled_extension_meta_data as $name => $infos) { - $this->template->assign_block_vars('enabled', array( - 'META_DISPLAY_NAME' => $display_name, - - 'U_DETAILS' => $this->u_action . '&action=details&ext_name=' . urlencode($name), - )); + $values = $infos; + $values['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name); + + $this->template->assign_block_vars('enabled', $values); $this->output_actions('enabled', array( 'DISABLE' => $this->u_action . '&action=disable_pre&ext_name=' . urlencode($name), @@ -312,25 +337,31 @@ class acp_extensions try { - $disabled_extension_meta_data[$name] = $md_manager->get_metadata('display-name'); + $meta = $md_manager->get_metadata('all'); + $disabled_extension_meta_data[$name] = array( + 'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'), + 'META_VERSION' => $meta['version'], + ); + + $this->version_check($md_manager, $disabled_extension_meta_data[$name]); } catch(\phpbb\extension\exception $e) { $this->template->assign_block_vars('disabled', array( 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), + 'S_VERSIONCHECK' => false, )); } } - natcasesort($disabled_extension_meta_data); + uasort($disabled_extension_meta_data, array('self', 'sort_extension_meta_data_table')); - foreach ($disabled_extension_meta_data as $name => $display_name) + foreach ($disabled_extension_meta_data as $name => $infos) { - $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $display_name, - - 'U_DETAILS' => $this->u_action . '&action=details&ext_name=' . urlencode($name), - )); + $values = $infos; + $values['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name); + + $this->template->assign_block_vars('disabled', $values); $this->output_actions('disabled', array( 'ENABLE' => $this->u_action . '&action=enable_pre&ext_name=' . urlencode($name), @@ -357,25 +388,31 @@ class acp_extensions try { - $available_extension_meta_data[$name] = $md_manager->get_metadata('display-name'); + $meta = $md_manager->get_metadata('all'); + $available_extension_meta_data[$name] = array( + 'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'), + 'META_VERSION' => $meta['version'], + ); + + $this->version_check($md_manager, $available_extension_meta_data[$name]); } catch(\phpbb\extension\exception $e) { $this->template->assign_block_vars('disabled', array( 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), + 'S_VERSIONCHECK' => false, )); } } - natcasesort($available_extension_meta_data); + uasort($available_extension_meta_data, array('self', 'sort_extension_meta_data_table')); - foreach ($available_extension_meta_data as $name => $display_name) + foreach ($available_extension_meta_data as $name => $infos) { - $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $display_name, - - 'U_DETAILS' => $this->u_action . '&action=details&ext_name=' . urlencode($name), - )); + $values = $infos; + $values['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name); + + $this->template->assign_block_vars('disabled', $values); $this->output_actions('disabled', array( 'ENABLE' => $this->u_action . '&action=enable_pre&ext_name=' . urlencode($name), @@ -400,4 +437,52 @@ class acp_extensions )); } } + + /** + * Check the version and dump to the template + * + * @param \phpbb\extension\metadata_manager $md_manager The metadata manager for the version to check. + * @param array $array_dest The array to bind to the template. + * @param bool $force Ignores cached data. Default to false. + */ + private function version_check(\phpbb\extension\metadata_manager $md_manager, &$array_dest, $force = false) + { + $meta = $md_manager->get_metadata('all'); + + if (! isset($meta['extra']['version-check'])) + { + throw new \RuntimeException($this->user->lang('NO_VERSIONCHECK')); + } + + $version_helper = new \phpbb\extension\version_helper($this->cache, $this->user); + $version_helper->set_metadata($meta); + + try + { + $version_helper->get_version($force); + $version_compare = $version_helper->is_uptodate(); + + $array_dest = array_merge($array_dest, array( + 'S_VERSIONCHECK' => true, + 'S_UP_TO_DATE' => $version_compare, + 'LATEST_VERSION' => $version_helper->get_latest_version(), + 'LATEST_DOWNLOAD' => $version_helper->get_latest_download_link(), + 'LATEST_ANNOUNCEMENT' => $version_helper->get_latest_announcement_link(), + 'UP_TO_DATE_MSG' => $this->user->lang($version_compare ? 'UP_TO_DATE' : 'NOT_UP_TO_DATE', $md_manager->get_metadata('display-name')), + 'U_VERSIONCHECK_FORCE' => $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')), + )); + } + catch(\RuntimeException $e) + { + $array_dest['S_VERSIONCHECK'] = false; + } + } + + /** + * Sort helper for the table containing the metadata about the extensions. + */ + static private function sort_extension_meta_data_table($val1, $val2) + { + return strnatcasecmp($val1['META_DISPLAY_NAME'], $val2['META_DISPLAY_NAME']); + } } diff --git a/phpBB/language/en/acp/extensions.php b/phpBB/language/en/acp/extensions.php index 8b29558fdb..85aef7c2d3 100644 --- a/phpBB/language/en/acp/extensions.php +++ b/phpBB/language/en/acp/extensions.php @@ -106,4 +106,11 @@ $lang = array_merge($lang, array( 'AUTHOR_EMAIL' => 'Email', 'AUTHOR_HOMEPAGE' => 'Homepage', 'AUTHOR_ROLE' => 'Role', + + 'NOT_UP_TO_DATE' => '%s is not up to date', + 'UP_TO_DATE' => '%s is up to date', + 'ANNOUNCEMENT_TOPIC' => 'Release Announcement', + 'DOWNLOAD_LATEST' => 'Download Latest Version', + 'NO_VERSIONCHECK' => 'No informations about how get the latest version.', +// 'NO_INFO' => 'Version server could not be contacted', )); diff --git a/phpBB/phpbb/extension/version_helper.php b/phpBB/phpbb/extension/version_helper.php new file mode 100644 index 0000000000..5d7d4121f0 --- /dev/null +++ b/phpBB/phpbb/extension/version_helper.php @@ -0,0 +1,257 @@ +<?php +/** +* +* @package extension +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +namespace phpbb\extension; + +/** + * Class to handle version checking and comparison for the extensions + */ +class version_helper +{ + /** + * @var string Host + */ + protected $host = ''; + + /** + * @var string Path to file + */ + protected $path = ''; + + /** + * @var string File name + */ + protected $file = ''; + + /** + * @var string Extension name + */ + protected $extension = ''; + + /** + * @var string Current version installed + */ + protected $current_version = ''; + + /** @var \phpbb\cache\service */ + protected $cache; + + /** @var \phpbb\user */ + protected $user; + + /** + * @var array Metadata of the latest versio + */ + protected $latest_version_metadata; + + /** + * Constructor + * + * @param \phpbb\cache\service $cache + * @param \phpbb\user $user + */ + public function __construct(\phpbb\cache\service $cache, \phpbb\user $user) + { + $this->cache = $cache; + $this->user = $user; + } + + /** + * Set the informations concerning the current version from the metadata + * + * @param array $metadata + * @throws \RuntimeException + */ + public function set_metadata($metadata) + { + if (! isset($metadata['extra']['version-check'])) + { + throw new \RuntimeException($this->user->lang('NO_VERSIONCHECK')); + } + + $meta_vc = $metadata['extra']['version-check']; + + $this->set_file_location($meta_vc['host'], $meta_vc['directory'], $meta_vc['filename']); + $this->set_extension($metadata['name']); + $this->set_current_version($metadata['version']); + } + + /** + * Set the name of the extention + * + * @param string Name of the extension + * @return version_helper + */ + public function set_extension($extension) + { + $this->extension = $extension; + + return $this; + } + + /** + * Set location to the file + * + * @param string $host Host (e.g. version.phpbb.com) + * @param string $path Path to file (e.g. /phpbb) + * @param string $file File name (Default: composer.json) + * @return version_helper + */ + public function set_file_location($host, $path, $file = 'composer.json') + { + $this->host = $host; + $this->path = $path; + $this->file = $file; + + return $this; + } + + /** + * Set current version + * + * @param string $version The current version + * @return version_helper + */ + public function set_current_version($version) + { + $this->current_version = $version; + + return $this; + } + + /** + * Wrapper for version_compare() that allows using uppercase A and B + * for alpha and beta releases. + * + * See http://www.php.net/manual/en/function.version-compare.php + * + * @param string $version1 First version number + * @param string $version2 Second version number + * @param string $operator Comparison operator (optional) + * + * @return mixed Boolean (true, false) if comparison operator is specified. + * Integer (-1, 0, 1) otherwise. + */ + public function compare($version1, $version2, $operator = null) + { + return phpbb_version_compare($version1, $version2, $operator); + } + + /** + * Say if the extension is up to date or not + * + * The informations about the lastest version are retrieved if needed + * + * @return bool true if the version is up to date + * @throws \RuntimeException + */ + public function is_uptodate() + { + if (empty($this->latest_version_metadata)) + { + $this->get_version(); + } + + return $this->compare($this->current_version, $this->latest_version_metadata['version'], '>='); + } + + /** + * Return the latest version number + * + * @return The latest version number ready to be displayed. + */ + public function get_latest_version() { + if (empty($this->latest_version_metadata)) + { + $this->get_version(); + } + + return htmlspecialchars($this->latest_version_metadata['version']); + } + + /** + * Return the latest download link + * + * @return The latest download link if existed, an empty string otherwise. + */ + public function get_latest_download_link() { + if (empty($this->latest_version_metadata)) + { + $this->get_version(); + } + + return isset($this->latest_version_metadata['extra']['download']) ? $this->latest_version_metadata['extra']['download']: ''; + } + + /** + * Return the latest announcement link + * + * @return The latest announcement link if existed, an empty string otherwise. + */ + public function get_latest_announcement_link() { + if (empty($this->latest_version_metadata)) + { + $this->get_version(); + } + + return isset($this->latest_version_metadata['extra']['announcement']) ? $this->latest_version_metadata['extra']['announcement']: ''; + } + + /** + * Obtains the latest version information + * + * @param bool $force_update Ignores cached data. Defaults to false. + * @return string Version info + * @throws \RuntimeException + */ + public function get_version($force_update = false) + { +echo 'Force : ' . $force_update; + $cache_file = 'versioncheck_ext_' . $this->extension . ':' . $this->host . $this->path . $this->file; + + $info = $this->cache->get($cache_file); + + if ($info === false || $force_update) + { + $errstr = $errno = ''; + $info = get_remote_file($this->host, $this->path, $this->file, $errstr, $errno); + + if (!empty($errstr)) + { + throw new \RuntimeException($errstr); + } + + $info = json_decode($info, true); + + if (empty($info['version'])) + { + $this->user->add_lang('acp/common'); + + throw new \RuntimeException($this->user->lang('VERSIONCHECK_FAIL')); + } + + // Replace & with & on announcement and download links + if (isset($info['extra']['announcement'])) + { + $info['extra']['announcement'] = str_replace('&', '&', $info['extra']['announcement']); + } + + if (isset($info['extra']['download'])) + { + $info['extra']['download'] = str_replace('&', '&', $info['extra']['download']); + } + + $this->cache->put($cache_file, $info, 86400); // 24 hours + } + + $this->latest_version_metadata = $info; + + return $info; + } +} |
