aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB')
-rw-r--r--phpBB/adm/style/acp_ext_details.html97
-rw-r--r--phpBB/adm/style/acp_ext_disable.html34
-rw-r--r--phpBB/adm/style/acp_ext_enable.html34
-rw-r--r--phpBB/adm/style/acp_ext_list.html61
-rw-r--r--phpBB/adm/style/acp_ext_purge.html34
-rw-r--r--phpBB/adm/style/admin.css10
-rw-r--r--phpBB/config/services.yml1
-rw-r--r--phpBB/includes/acp/acp_extensions.php303
-rw-r--r--phpBB/includes/acp/info/acp_extensions.php34
-rw-r--r--phpBB/includes/extension/exception.php27
-rw-r--r--phpBB/includes/extension/manager.php18
-rw-r--r--phpBB/includes/extension/metadata_manager.php338
-rw-r--r--phpBB/install/database_update.php4
-rw-r--r--phpBB/install/install_install.php6
-rw-r--r--phpBB/install/schemas/schema_data.sql1
-rw-r--r--phpBB/language/en/acp/common.php1
-rw-r--r--phpBB/language/en/acp/extensions.php103
-rw-r--r--phpBB/language/en/acp/permissions_phpbb.php1
18 files changed, 1101 insertions, 6 deletions
diff --git a/phpBB/adm/style/acp_ext_details.html b/phpBB/adm/style/acp_ext_details.html
new file mode 100644
index 0000000000..e7532691ad
--- /dev/null
+++ b/phpBB/adm/style/acp_ext_details.html
@@ -0,0 +1,97 @@
+<!-- INCLUDE overall_header.html -->
+
+<a name="maincontent"></a>
+
+ <a href="{U_BACK}" style="float: {S_CONTENT_FLOW_END};">&laquo; {L_BACK}</a>
+
+ <h1>{L_EXTENSIONS_ADMIN}</h1>
+
+ <fieldset>
+ <legend>{L_EXT_DETAILS}</legend>
+ <!-- IF META_DISPLAY_NAME -->
+ <dl>
+ <dt><label for="meta_display_name">{L_DISPLAY_NAME}:</label></dt>
+ <dd><strong id="meta_display_name">{META_DISPLAY_NAME}</strong></dd>
+ </dl>
+ <!-- ENDIF -->
+ <dl>
+ <dt><label for="meta_name">{L_CLEAN_NAME}:</label></dt>
+ <dd><strong id="meta_name">{META_NAME}</strong></dd>
+ </dl>
+ <!-- IF META_DESCRIPTION -->
+ <dl>
+ <dt><label for="meta_description">{L_DESCRIPTION}:</label></dt>
+ <dd><p id="meta_description">{META_DESCRIPTION}</p></dd>
+ </dl>
+ <!-- ENDIF -->
+ <dl>
+ <dt><label for="meta_version">{L_VERSION}:</label></dt>
+ <dd><p id="meta_version">{META_VERSION}</p></dd>
+ </dl>
+ <!-- IF META_HOMEPAGE -->
+ <dl>
+ <dt><label for="meta_homepage">{L_HOMEPAGE}:</label></dt>
+ <dd><p id="meta_homepage">{META_HOMEPAGE}</p></dd>
+ </dl>
+ <!-- ENDIF -->
+ <!-- IF META_TIME -->
+ <dl>
+ <dt><label for="meta_time">{L_TIME}:</label></dt>
+ <dd><p id="meta_time">{META_TIME}</p></dd>
+ </dl>
+ <!-- ENDIF -->
+ <dl>
+ <dt><label for="meta_license">{L_LICENCE}:</label></dt>
+ <dd><p id="meta_license">{META_LICENCE}</p></dd>
+ </dl>
+ </fieldset>
+
+ <!-- IF META_REQUIRE_PHPBB || META_REQUIRE_PHP -->
+ <fieldset>
+ <legend>{L_REQUIREMENTS}</legend>
+ <!-- IF META_REQUIRE_PHPBB -->
+ <dl<!-- IF META_REQUIRE_PHPBB_FAIL --> class="requirements_not_met"<!-- ENDIF -->>
+ <dt><label for="require_phpbb">{L_PHPBB_VERSION}:</label></dt>
+ <dd><p id="require_phpbb">{META_REQUIRE_PHPBB}</p></dd>
+ </dl>
+ <!-- ENDIF -->
+ <!-- IF META_REQUIRE_PHP -->
+ <dl<!-- IF META_REQUIRE_PHP_FAIL --> class="requirements_not_met"<!-- ENDIF -->>
+ <dt><label for="require_php">{L_PHP_VERSION}:</label></dt>
+ <dd><p id="require_php">{META_REQUIRE_PHP}</p></dd>
+ </dl>
+ <!-- ENDIF -->
+ </fieldset>
+ <!-- ENDIF -->
+
+ <fieldset>
+ <legend>{L_AUTHOR_INFORMATION}</legend>
+ <!-- BEGIN meta_authors -->
+ <fieldset>
+ <dl>
+ <dt><label for="meta_author_name">{L_AUTHOR_NAME}:</label></dt>
+ <dd><strong id="meta_author_name">{meta_authors.AUTHOR_NAME}</strong></dd>
+ </dl>
+ <!-- IF meta_authors.AUTHOR_EMAIL -->
+ <dl>
+ <dt><label for="meta_author_email">{L_AUTHOR_EMAIL}:</label></dt>
+ <dd><strong id="meta_author_email"><a href="mailto:{meta_authors.AUTHOR_EMAIL}">{meta_authors.AUTHOR_EMAIL}</a></strong></dd>
+ </dl>
+ <!-- ENDIF -->
+ <!-- IF meta_authors.AUTHOR_HOMEPAGE -->
+ <dl>
+ <dt><label for="meta_author_url">{L_AUTHOR_HOMEPAGE}:</label></dt>
+ <dd><strong id="meta_author_url"><a href="{meta_authors.AUTHOR_HOMEPAGE}">{meta_authors.AUTHOR_HOMEPAGE}</a></strong></dd>
+ </dl>
+ <!-- ENDIF -->
+ <!-- IF meta_authors.AUTHOR_ROLE -->
+ <dl>
+ <dt><label for="author_role">{L_AUTHOR_ROLE}:</label></dt>
+ <dd><strong id="meta_author_role">{meta_authors.AUTHOR_ROLE}</strong></dd>
+ </dl>
+ <!-- ENDIF -->
+ </fieldset>
+ <!-- END meta_authors -->
+ </fieldset>
+
+<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/adm/style/acp_ext_disable.html b/phpBB/adm/style/acp_ext_disable.html
new file mode 100644
index 0000000000..7dc3f6ec97
--- /dev/null
+++ b/phpBB/adm/style/acp_ext_disable.html
@@ -0,0 +1,34 @@
+<!-- INCLUDE overall_header.html -->
+
+ <a name="maincontent"></a>
+
+ <h1>{L_EXTENSIONS_ADMIN}</h1>
+
+ <p>{L_EXTENSIONS_EXPLAIN}</p>
+ <p>{L_DISABLE_EXPLAIN}</p>
+
+ <!-- IF PRE -->
+ <div class="errorbox">
+ <p>{L_DISABLE_CONFIRM}</p>
+ </div>
+
+ <form id="acp_extensions" method="post" action="{U_DISABLE}">
+ <fieldset class="submit-buttons">
+ <legend>{L_DISABLE}</legend>
+ <input class="button1" type="submit" name="disable" value="{L_DISABLE}" />
+ <input class="button2" type="submit" name="cancel" value="{L_CANCEL}" />
+ </fieldset>
+ </form>
+ <!-- ELSEIF S_NEXT_STEP -->
+ <div class="errorbox">
+ <p>{L_DISABLE_IN_PROGRESS}</p>
+ </div>
+ <!-- ELSE -->
+ <div class="successbox">
+ <p>{L_DISABLE_SUCCESS}</p>
+ <br />
+ <p><a href="{U_RETURN}">{L_RETURN}</a></p>
+ </div>
+ <!-- ENDIF -->
+
+<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/adm/style/acp_ext_enable.html b/phpBB/adm/style/acp_ext_enable.html
new file mode 100644
index 0000000000..3f7be2c847
--- /dev/null
+++ b/phpBB/adm/style/acp_ext_enable.html
@@ -0,0 +1,34 @@
+<!-- INCLUDE overall_header.html -->
+
+ <a name="maincontent"></a>
+
+ <h1>{L_EXTENSIONS_ADMIN}</h1>
+
+ <p>{L_EXTENSIONS_EXPLAIN}</p>
+ <p>{L_ENABLE_EXPLAIN}</p>
+
+ <!-- IF PRE -->
+ <div class="errorbox">
+ <p>{L_ENABLE_CONFIRM}</p>
+ </div>
+
+ <form id="acp_extensions" method="post" action="{U_ENABLE}">
+ <fieldset class="submit-buttons">
+ <legend>{L_ENABLE}</legend>
+ <input class="button1" type="submit" name="enable" value="{L_ENABLE}" />
+ <input class="button2" type="submit" name="cancel" value="{L_CANCEL}" />
+ </fieldset>
+ </form>
+ <!-- ELSEIF S_NEXT_STEP -->
+ <div class="errorbox">
+ <p>{L_ENABLE_IN_PROGRESS}</p>
+ </div>
+ <!-- ELSE -->
+ <div class="successbox">
+ <p>{L_ENABLE_SUCCESS}</p>
+ <br />
+ <p><a href="{U_RETURN}">{L_RETURN}</a></p>
+ </div>
+ <!-- ENDIF -->
+
+<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/adm/style/acp_ext_list.html b/phpBB/adm/style/acp_ext_list.html
new file mode 100644
index 0000000000..53de0b4d12
--- /dev/null
+++ b/phpBB/adm/style/acp_ext_list.html
@@ -0,0 +1,61 @@
+<!-- INCLUDE overall_header.html -->
+
+<a name="maincontent"></a>
+
+ <h1>{L_EXTENSIONS_ADMIN}</h1>
+
+ <p>{L_EXTENSIONS_EXPLAIN}</p>
+
+ <table cellspacing="1">
+ <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>
+ </tr>
+ </thead>
+ <tbody>
+ <!-- IF .enabled -->
+ <tr>
+ <td class="row3" colspan="3">
+ <strong>{L_ENABLED} {L_EXTENSIONS}</strong>
+ </td>
+ </tr>
+ <!-- BEGIN enabled -->
+ <tr class="ext_enabled">
+ <td><strong>{enabled.META_DISPLAY_NAME}</strong></a></td>
+ <td style="text-align: center;"><a href="{enabled.U_DETAILS}">{L_DETAILS}</a></td>
+ <td style="text-align: center;">
+ <!-- BEGIN actions -->
+ <a href="{enabled.actions.U_ACTION}" alt="{enabled.actions.L_ACTION}">{enabled.actions.L_ACTION}</a>
+ <!-- IF not enabled.actions.S_LAST_ROW -->&nbsp;|&nbsp;<!-- ENDIF -->
+ <!-- END actions -->
+ </td>
+ </tr>
+ <!-- END enabled -->
+ <!-- ENDIF -->
+
+ <!-- IF .disabled -->
+ <tr>
+ <td class="row3" colspan="3"><strong>{L_DISABLED} {L_EXTENSIONS}</strong></td>
+ </tr>
+ <!-- BEGIN disabled -->
+ <tr class="ext_disabled">
+ <td><strong>{disabled.META_DISPLAY_NAME}</strong></a></td>
+ <td style="text-align: center;">
+ <!-- IF disabled.U_DETAILS --><a href="{disabled.U_DETAILS}">{L_DETAILS}</a><!-- ENDIF -->
+ </td>
+ <td style="text-align: center;">
+ <!-- BEGIN actions -->
+ <a href="{disabled.actions.U_ACTION}" alt="{disabled.actions.L_ACTION}">{disabled.actions.L_ACTION}</a>
+ <!-- IF not disabled.actions.S_LAST_ROW -->&nbsp;|&nbsp;<!-- ENDIF -->
+ <!-- END actions -->
+ </td>
+ </tr>
+ <!-- END disabled -->
+ <!-- ENDIF -->
+ </tbody>
+ </table>
+
+<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/adm/style/acp_ext_purge.html b/phpBB/adm/style/acp_ext_purge.html
new file mode 100644
index 0000000000..00a58721cb
--- /dev/null
+++ b/phpBB/adm/style/acp_ext_purge.html
@@ -0,0 +1,34 @@
+<!-- INCLUDE overall_header.html -->
+
+ <a name="maincontent"></a>
+
+ <h1>{L_EXTENSIONS_ADMIN}</h1>
+
+ <p>{L_EXTENSIONS_EXPLAIN}</p>
+ <p>{L_PURGE_EXPLAIN}</p>
+
+ <!-- IF PRE -->
+ <div class="errorbox">
+ <p>{L_PURGE_CONFIRM}</p>
+ </div>
+
+ <form id="acp_extensions" method="post" action="{U_PURGE}">
+ <fieldset class="submit-buttons">
+ <legend>{L_PURGE}</legend>
+ <input class="button1" type="submit" name="purge" value="{L_PURGE}" />
+ <input class="button2" type="submit" name="cancel" value="{L_CANCEL}" />
+ </fieldset>
+ </form>
+ <!-- ELSEIF S_NEXT_STEP -->
+ <div class="errorbox">
+ <p>{L_PURGE_IN_PROGRESS}</p>
+ </div>
+ <!-- ELSE -->
+ <div class="successbox">
+ <p>{L_PURGE_SUCCESS}</p>
+ <br />
+ <p><a href="{U_RETURN}">{L_RETURN}</a></p>
+ </div>
+ <!-- ENDIF -->
+
+<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css
index 08613de0dd..585707600d 100644
--- a/phpBB/adm/style/admin.css
+++ b/phpBB/adm/style/admin.css
@@ -1718,3 +1718,13 @@ fieldset.permissions .padding {
.phpinfo td, .phpinfo th, .phpinfo h2, .phpinfo h1 {
text-align: left;
}
+
+.requirements_not_met {
+ padding: 5px;
+ background-color: #BC2A4D;
+}
+
+.requirements_not_met dt label, .requirements_not_met dd p {
+ color: #FFFFFF;
+ font-size: 1.4em;
+} \ No newline at end of file
diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml
index 84de37c28c..133a43b77e 100644
--- a/phpBB/config/services.yml
+++ b/phpBB/config/services.yml
@@ -83,6 +83,7 @@ services:
class: phpbb_extension_manager
arguments:
- @dbal.conn
+ - @config
- %tables.ext%
- %core.root_path%
- .%core.php_ext%
diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php
new file mode 100644
index 0000000000..a0bcf62ecc
--- /dev/null
+++ b/phpBB/includes/acp/acp_extensions.php
@@ -0,0 +1,303 @@
+<?php
+/**
+*
+* @package acp
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* @package acp
+*/
+class acp_extensions
+{
+ var $u_action;
+
+ private $db;
+ private $config;
+ private $template;
+ private $user;
+
+ function main()
+ {
+ // Start the page
+ global $config, $user, $template, $request, $phpbb_extension_manager, $db, $phpbb_root_path, $phpEx;
+
+ $this->db = $db;
+ $this->config = $config;
+ $this->template = $template;
+ $this->user = $user;
+
+ $user->add_lang(array('install', 'acp/extensions'));
+
+ $this->page_title = 'ACP_EXTENSIONS';
+
+ $action = $request->variable('action', 'list');
+ $ext_name = $request->variable('ext_name', '');
+
+ // Cancel action
+ if ($request->is_set_post('cancel'))
+ {
+ $action = 'list';
+ $ext_name = '';
+ }
+
+ // If they've specified an extension, let's load the metadata manager and validate it.
+ if ($ext_name)
+ {
+ $md_manager = new phpbb_extension_metadata_manager($ext_name, $db, $phpbb_extension_manager, $phpbb_root_path, ".$phpEx", $template, $config);
+
+ try
+ {
+ $md_manager->get_metadata('all');
+ }
+ catch(phpbb_extension_exception $e)
+ {
+ trigger_error($e);
+ }
+ }
+
+ // What are we doing?
+ switch ($action)
+ {
+ case 'list':
+ default:
+ $this->list_enabled_exts($phpbb_extension_manager);
+ $this->list_disabled_exts($phpbb_extension_manager);
+ $this->list_available_exts($phpbb_extension_manager);
+
+ $this->tpl_name = 'acp_ext_list';
+ break;
+
+ case 'enable_pre':
+ if (!$md_manager->validate_enable())
+ {
+ trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action));
+ }
+
+ if ($phpbb_extension_manager->enabled($ext_name))
+ {
+ redirect($this->u_action);
+ }
+
+ $this->tpl_name = 'acp_ext_enable';
+
+ $template->assign_vars(array(
+ 'PRE' => true,
+ 'U_ENABLE' => $this->u_action . '&amp;action=enable&amp;ext_name=' . urlencode($ext_name),
+ ));
+ break;
+
+ case 'enable':
+ if (!$md_manager->validate_enable())
+ {
+ trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action));
+ }
+
+ if ($phpbb_extension_manager->enable_step($ext_name))
+ {
+ $template->assign_var('S_NEXT_STEP', true);
+
+ meta_refresh(0, $this->u_action . '&amp;action=enable&amp;ext_name=' . urlencode($ext_name));
+ }
+
+ $this->tpl_name = 'acp_ext_enable';
+
+ $template->assign_vars(array(
+ 'U_RETURN' => $this->u_action . '&amp;action=list',
+ ));
+ break;
+
+ case 'disable_pre':
+ if (!$phpbb_extension_manager->enabled($ext_name))
+ {
+ redirect($this->u_action);
+ }
+
+ $this->tpl_name = 'acp_ext_disable';
+
+ $template->assign_vars(array(
+ 'PRE' => true,
+ 'U_DISABLE' => $this->u_action . '&amp;action=disable&amp;ext_name=' . urlencode($ext_name),
+ ));
+ break;
+
+ case 'disable':
+ if ($phpbb_extension_manager->disable_step($ext_name))
+ {
+ $template->assign_var('S_NEXT_STEP', true);
+
+ meta_refresh(0, $this->u_action . '&amp;action=disable&amp;ext_name=' . urlencode($ext_name));
+ }
+
+ $this->tpl_name = 'acp_ext_disable';
+
+ $template->assign_vars(array(
+ 'U_RETURN' => $this->u_action . '&amp;action=list',
+ ));
+ break;
+
+ case 'purge_pre':
+ $this->tpl_name = 'acp_ext_purge';
+
+ $template->assign_vars(array(
+ 'PRE' => true,
+ 'U_PURGE' => $this->u_action . '&amp;action=purge&amp;ext_name=' . urlencode($ext_name),
+ ));
+ break;
+
+ case 'purge':
+ if ($phpbb_extension_manager->purge_step($ext_name))
+ {
+ $template->assign_var('S_NEXT_STEP', true);
+
+ meta_refresh(0, $this->u_action . '&amp;action=purge&amp;ext_name=' . urlencode($ext_name));
+ }
+
+ $this->tpl_name = 'acp_ext_purge';
+
+ $template->assign_vars(array(
+ 'U_RETURN' => $this->u_action . '&amp;action=list',
+ ));
+ break;
+
+ case 'details':
+ // Output it to the template
+ $md_manager->output_template_data();
+
+ $template->assign_var('U_BACK', $this->u_action . '&amp;action=list');
+
+ $this->tpl_name = 'acp_ext_details';
+ break;
+ }
+ }
+
+ /**
+ * Lists all the enabled extensions and dumps to the template
+ *
+ * @param $phpbb_extension_manager An instance of the extension manager
+ * @return null
+ */
+ public function list_enabled_exts(phpbb_extension_manager $phpbb_extension_manager)
+ {
+ foreach ($phpbb_extension_manager->all_enabled() as $name => $location)
+ {
+ $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name, $this->template);
+
+ try
+ {
+ $this->template->assign_block_vars('enabled', array(
+ 'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'),
+
+ 'U_DETAILS' => $this->u_action . '&amp;action=details&amp;ext_name=' . urlencode($name),
+ ));
+
+ $this->output_actions('enabled', array(
+ 'DISABLE' => $this->u_action . '&amp;action=disable_pre&amp;ext_name=' . urlencode($name),
+ 'PURGE' => $this->u_action . '&amp;action=purge_pre&amp;ext_name=' . urlencode($name),
+ ));
+ }
+ catch(phpbb_extension_exception $e)
+ {
+ $this->template->assign_block_vars('disabled', array(
+ 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e),
+ ));
+ }
+ }
+ }
+
+ /**
+ * Lists all the disabled extensions and dumps to the template
+ *
+ * @param $phpbb_extension_manager An instance of the extension manager
+ * @return null
+ */
+ public function list_disabled_exts(phpbb_extension_manager $phpbb_extension_manager)
+ {
+ foreach ($phpbb_extension_manager->all_disabled() as $name => $location)
+ {
+ $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name, $this->template);
+
+ try
+ {
+ $this->template->assign_block_vars('disabled', array(
+ 'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'),
+
+ 'U_DETAILS' => $this->u_action . '&amp;action=details&amp;ext_name=' . urlencode($name),
+ ));
+
+ $this->output_actions('disabled', array(
+ 'ENABLE' => $this->u_action . '&amp;action=enable_pre&amp;ext_name=' . urlencode($name),
+ 'PURGE' => $this->u_action . '&amp;action=purge_pre&amp;ext_name=' . urlencode($name),
+ ));
+ }
+ catch(phpbb_extension_exception $e)
+ {
+ $this->template->assign_block_vars('disabled', array(
+ 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e),
+ ));
+ }
+ }
+ }
+
+ /**
+ * Lists all the available extensions and dumps to the template
+ *
+ * @param $phpbb_extension_manager An instance of the extension manager
+ * @return null
+ */
+ public function list_available_exts(phpbb_extension_manager $phpbb_extension_manager)
+ {
+ $uninstalled = array_diff_key($phpbb_extension_manager->all_available(), $phpbb_extension_manager->all_configured());
+
+ foreach ($uninstalled as $name => $location)
+ {
+ $md_manager = $phpbb_extension_manager->create_extension_metadata_manager($name, $this->template);
+
+ try
+ {
+ $this->template->assign_block_vars('disabled', array(
+ 'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'),
+
+ 'U_DETAILS' => $this->u_action . '&amp;action=details&amp;ext_name=' . urlencode($name),
+ ));
+
+ $this->output_actions('disabled', array(
+ 'ENABLE' => $this->u_action . '&amp;action=enable_pre&amp;ext_name=' . urlencode($name),
+ ));
+ }
+ catch(phpbb_extension_exception $e)
+ {
+ $this->template->assign_block_vars('disabled', array(
+ 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e),
+ ));
+ }
+ }
+ }
+
+ /**
+ * Output actions to a block
+ *
+ * @param string $block
+ * @param array $actions
+ */
+ private function output_actions($block, $actions)
+ {
+ foreach ($actions as $lang => $url)
+ {
+ $this->template->assign_block_vars($block . '.actions', array(
+ 'L_ACTION' => $this->user->lang($lang),
+ 'U_ACTION' => $url,
+ ));
+ }
+ }
+}
diff --git a/phpBB/includes/acp/info/acp_extensions.php b/phpBB/includes/acp/info/acp_extensions.php
new file mode 100644
index 0000000000..f5953fb1dd
--- /dev/null
+++ b/phpBB/includes/acp/info/acp_extensions.php
@@ -0,0 +1,34 @@
+<?php
+/**
+*
+* @package acp
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @package module_install
+*/
+class acp_extensions_info
+{
+ function module()
+ {
+ return array(
+ 'filename' => 'acp_extensions',
+ 'title' => 'ACP_EXTENSIONS',
+ 'version' => '1.0.0',
+ 'modes' => array(
+ 'main' => array('title' => 'ACP_EXTENSIONS', 'auth' => 'acl_a_extensions', 'cat' => array('ACP_GENERAL_TASKS')),
+ ),
+ );
+ }
+
+ function install()
+ {
+ }
+
+ function uninstall()
+ {
+ }
+}
diff --git a/phpBB/includes/extension/exception.php b/phpBB/includes/extension/exception.php
new file mode 100644
index 0000000000..e08a8912ea
--- /dev/null
+++ b/phpBB/includes/extension/exception.php
@@ -0,0 +1,27 @@
+<?php
+/**
+*
+* @package extension
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+ * Exception class for metadata
+ */
+class phpbb_extension_exception extends UnexpectedValueException
+{
+ public function __toString()
+ {
+ return $this->getMessage();
+ }
+} \ No newline at end of file
diff --git a/phpBB/includes/extension/manager.php b/phpBB/includes/extension/manager.php
index 86d8fab64b..9a518c215f 100644
--- a/phpBB/includes/extension/manager.php
+++ b/phpBB/includes/extension/manager.php
@@ -22,6 +22,8 @@ if (!defined('IN_PHPBB'))
*/
class phpbb_extension_manager
{
+ protected $db;
+ protected $config;
protected $cache;
protected $php_ext;
protected $extensions;
@@ -33,16 +35,18 @@ class phpbb_extension_manager
* Creates a manager and loads information from database
*
* @param dbal $db A database connection
+ * @param phpbb_config $config phpbb_config
* @param string $extension_table The name of the table holding extensions
* @param string $phpbb_root_path Path to the phpbb includes directory.
* @param string $php_ext php file extension
* @param phpbb_cache_driver_interface $cache A cache instance or null
* @param string $cache_name The name of the cache variable, defaults to _ext
*/
- public function __construct(dbal $db, $extension_table, $phpbb_root_path, $php_ext = '.php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext')
+ public function __construct(dbal $db, phpbb_config $config, $extension_table, $phpbb_root_path, $php_ext = '.php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext')
{
$this->phpbb_root_path = $phpbb_root_path;
$this->db = $db;
+ $this->config = $config;
$this->cache = $cache;
$this->php_ext = $php_ext;
$this->extension_table = $extension_table;
@@ -121,6 +125,18 @@ class phpbb_extension_manager
}
/**
+ * Instantiates the metadata manager for the extension with the given name
+ *
+ * @param string $name The extension name
+ * @param string $template The template manager
+ * @return phpbb_extension_metadata_manager Instance of the metadata manager
+ */
+ public function create_extension_metadata_manager($name, phpbb_template $template)
+ {
+ return new phpbb_extension_metadata_manager($name, $this->db, $this, $this->phpbb_root_path, $this->php_ext, $template, $this->config);
+ }
+
+ /**
* Runs a step of the extension enabling process.
*
* Allows the exentension to enable in a long running script that works
diff --git a/phpBB/includes/extension/metadata_manager.php b/phpBB/includes/extension/metadata_manager.php
new file mode 100644
index 0000000000..ea85bd3c4e
--- /dev/null
+++ b/phpBB/includes/extension/metadata_manager.php
@@ -0,0 +1,338 @@
+<?php
+/**
+*
+* @package extension
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* The extension metadata manager validates and gets meta-data for extensions
+*
+* @package extension
+*/
+class phpbb_extension_metadata_manager
+{
+ protected $phpEx;
+ protected $extension_manager;
+ protected $db;
+ protected $phpbb_root_path;
+ protected $template;
+ protected $ext_name;
+ protected $metadata;
+ protected $metadata_file;
+
+ /**
+ * Creates the metadata manager
+ *
+ * @param dbal $db A database connection
+ * @param string $extension_manager An instance of the phpbb extension manager
+ * @param string $phpbb_root_path Path to the phpbb includes directory.
+ * @param string $phpEx php file extension
+ */
+ public function __construct($ext_name, dbal $db, phpbb_extension_manager $extension_manager, $phpbb_root_path, $phpEx = '.php', phpbb_template $template, phpbb_config $config)
+ {
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->db = $db;
+ $this->config = $config;
+ $this->phpEx = $phpEx;
+ $this->template = $template;
+ $this->extension_manager = $extension_manager;
+ $this->ext_name = $ext_name;
+ $this->metadata = array();
+ $this->metadata_file = '';
+ }
+
+ /**
+ * Processes and gets the metadata requested
+ *
+ * @param string $element All for all metadata that it has and is valid, otherwise specify which section you want by its shorthand term.
+ * @return array Contains all of the requested metadata, throws an exception on failure
+ */
+ public function get_metadata($element = 'all')
+ {
+ $this->set_metadata_file();
+
+ // Fetch the metadata
+ $this->fetch_metadata();
+
+ // Clean the metadata
+ $this->clean_metadata_array();
+
+ switch ($element)
+ {
+ case 'all':
+ default:
+ // Validate the metadata
+ if (!$this->validate())
+ {
+ return false;
+ }
+
+ return $this->metadata;
+ break;
+
+ case 'name':
+ return ($this->validate('name')) ? $this->metadata['name'] : false;
+ break;
+
+ case 'display-name':
+ if (isset($this->metadata['extra']['display-name']))
+ {
+ return $this->metadata['extra']['display-name'];
+ }
+ else
+ {
+ return ($this->validate('name')) ? $this->metadata['name'] : false;
+ }
+ break;
+ }
+ }
+
+ /**
+ * Sets the filepath of the metadata file
+ *
+ * @return boolean Set to true if it exists, throws an exception on failure
+ */
+ private function set_metadata_file()
+ {
+ $ext_filepath = $this->extension_manager->get_extension_path($this->ext_name);
+ $metadata_filepath = $this->phpbb_root_path . $ext_filepath . 'composer.json';
+
+ $this->metadata_file = $metadata_filepath;
+
+ if (!file_exists($this->metadata_file))
+ {
+ throw new phpbb_extension_exception('The required file does not exist: ' . $this->metadata_file);
+ }
+ }
+
+ /**
+ * Gets the contents of the composer.json file
+ *
+ * @return bool True if success, throws an exception on failure
+ */
+ private function fetch_metadata()
+ {
+ if (!file_exists($this->metadata_file))
+ {
+ throw new phpbb_extension_exception('The required file does not exist: ' . $this->metadata_file);
+ }
+ else
+ {
+ if (!($file_contents = file_get_contents($this->metadata_file)))
+ {
+ throw new phpbb_extension_exception('file_get_contents failed on ' . $this->metadata_file);
+ }
+
+ if (($metadata = json_decode($file_contents, true)) === NULL)
+ {
+ throw new phpbb_extension_exception('json_decode failed on ' . $this->metadata_file);
+ }
+
+ $this->metadata = $metadata;
+
+ return true;
+ }
+ }
+
+ /**
+ * This array handles the cleaning of the array
+ *
+ * @return array Contains the cleaned metadata array
+ */
+ private function clean_metadata_array()
+ {
+ return $this->metadata;
+ }
+
+ /**
+ * Validate fields
+ *
+ * @param string $name ("all" for display and enable validation
+ * "display" for name, type, and authors
+ * "name", "type")
+ * @return Bool True if valid, throws an exception if invalid
+ */
+ public function validate($name = 'display')
+ {
+ // Basic fields
+ $fields = array(
+ 'name' => '#^[a-zA-Z0-9_\x7f-\xff]{2,}/[a-zA-Z0-9_\x7f-\xff]{2,}$#',
+ 'type' => '#^phpbb3-extension$#',
+ 'licence' => '#.+#',
+ 'version' => '#.+#',
+ );
+
+ switch ($name)
+ {
+ case 'all':
+ $this->validate('display');
+
+ $this->validate_enable();
+ break;
+
+ case 'display':
+ foreach ($fields as $field => $data)
+ {
+ $this->validate($field);
+ }
+
+ $this->validate_authors();
+ break;
+
+ default:
+ if (isset($fields[$name]))
+ {
+ if (!isset($this->metadata[$name]))
+ {
+ throw new phpbb_extension_exception("Required meta field '$name' has not been set.");
+ }
+
+ if (!preg_match($fields[$name], $this->metadata[$name]))
+ {
+ throw new phpbb_extension_exception("Meta field '$name' is invalid.");
+ }
+ }
+ break;
+ }
+
+ return true;
+ }
+
+ /**
+ * Validates the contents of the authors field
+ *
+ * @return boolean True when passes validation, throws exception if invalid
+ */
+ public function validate_authors()
+ {
+ if (empty($this->metadata['authors']))
+ {
+ throw new phpbb_extension_exception("Required meta field 'authors' has not been set.");
+ }
+
+ foreach ($this->metadata['authors'] as $author)
+ {
+ if (!isset($author['name']))
+ {
+ throw new phpbb_extension_exception("Required meta field 'author name' has not been set.");
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * This array handles the verification that this extension can be enabled on this board
+ *
+ * @return bool True if validation succeeded, False if failed
+ */
+ public function validate_enable()
+ {
+ // Check for phpBB, PHP versions
+ if (!$this->validate_require_phpbb() || !$this->validate_require_php())
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Validates the contents of the phpbb requirement field
+ *
+ * @return boolean True when passes validation
+ */
+ public function validate_require_phpbb()
+ {
+ if (!isset($this->metadata['require']['phpbb']))
+ {
+ return true;
+ }
+
+ return $this->_validate_version($this->metadata['require']['phpbb'], $this->config['version']);
+ }
+
+ /**
+ * Validates the contents of the php requirement field
+ *
+ * @return boolean True when passes validation
+ */
+ public function validate_require_php()
+ {
+ if (!isset($this->metadata['require']['php']))
+ {
+ return true;
+ }
+
+ return $this->_validate_version($this->metadata['require']['php'], phpversion());
+ }
+
+ /**
+ * Version validation helper
+ *
+ * @param string $string The string for comparing to a version
+ * @param string $current_version The version to compare to
+ * @return bool True/False if meets version requirements
+ */
+ private function _validate_version($string, $current_version)
+ {
+ // Allow them to specify their own comparison operator (ex: <3.1.2, >=3.1.0)
+ $comparison_matches = false;
+ preg_match('#[=<>]+#', $string, $comparison_matches);
+
+ if (!empty($comparison_matches))
+ {
+ return version_compare($current_version, str_replace(array($comparison_matches[0], ' '), '', $string), $comparison_matches[0]);
+ }
+
+ return version_compare($current_version, $string, '>=');
+ }
+
+ /**
+ * Outputs the metadata into the template
+ *
+ * @return null
+ */
+ public function output_template_data()
+ {
+ $this->template->assign_vars(array(
+ 'META_NAME' => htmlspecialchars($this->metadata['name']),
+ 'META_TYPE' => htmlspecialchars($this->metadata['type']),
+ 'META_DESCRIPTION' => (isset($this->metadata['description'])) ? htmlspecialchars($this->metadata['description']) : '',
+ 'META_HOMEPAGE' => (isset($this->metadata['homepage'])) ? $this->metadata['homepage'] : '',
+ 'META_VERSION' => (isset($this->metadata['version'])) ? htmlspecialchars($this->metadata['version']) : '',
+ 'META_TIME' => (isset($this->metadata['time'])) ? htmlspecialchars($this->metadata['time']) : '',
+ 'META_LICENCE' => htmlspecialchars($this->metadata['licence']),
+
+ 'META_REQUIRE_PHP' => (isset($this->metadata['require']['php'])) ? htmlspecialchars($this->metadata['require']['php']) : '',
+ 'META_REQUIRE_PHP_FAIL' => !$this->validate_require_php(),
+
+ 'META_REQUIRE_PHPBB' => (isset($this->metadata['require']['phpbb'])) ? htmlspecialchars($this->metadata['require']['phpbb']) : '',
+ 'META_REQUIRE_PHPBB_FAIL' => !$this->validate_require_phpbb(),
+
+ 'META_DISPLAY_NAME' => (isset($this->metadata['extra']['display-name'])) ? htmlspecialchars($this->metadata['extra']['display-name']) : '',
+ ));
+
+ foreach ($this->metadata['authors'] as $author)
+ {
+ $this->template->assign_block_vars('meta_authors', array(
+ 'AUTHOR_NAME' => htmlspecialchars($author['name']),
+ 'AUTHOR_EMAIL' => (isset($author['email'])) ? $author['email'] : '',
+ 'AUTHOR_HOMEPAGE' => (isset($author['homepage'])) ? $author['homepage'] : '',
+ 'AUTHOR_ROLE' => (isset($author['role'])) ? htmlspecialchars($author['role']) : '',
+ ));
+ }
+ }
+}
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
index 502b3bb1a4..0b470ced26 100644
--- a/phpBB/install/database_update.php
+++ b/phpBB/install/database_update.php
@@ -683,12 +683,12 @@ function _write_result($no_updates, $errored, $error_ary)
function _add_modules($modules_to_install)
{
- global $phpbb_root_path, $phpEx, $db, $phpbb_extension_manager;
+ global $phpbb_root_path, $phpEx, $db, $phpbb_extension_manager, $config;
// modules require an extension manager
if (empty($phpbb_extension_manager))
{
- $phpbb_extension_manager = new phpbb_extension_manager($db, EXT_TABLE, $phpbb_root_path, ".$phpEx");
+ $phpbb_extension_manager = new phpbb_extension_manager($db, $config, EXT_TABLE, $phpbb_root_path, ".$phpEx");
}
include_once($phpbb_root_path . 'includes/acp/acp_modules.' . $phpEx);
diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php
index 23593ee51f..9162d5ab60 100644
--- a/phpBB/install/install_install.php
+++ b/phpBB/install/install_install.php
@@ -250,7 +250,7 @@ class install_install extends module
'S_EXPLAIN' => true,
'S_LEGEND' => false,
));
-
+
// Check for php json support
if (@extension_loaded('json'))
{
@@ -1481,12 +1481,12 @@ class install_install extends module
*/
function add_modules($mode, $sub)
{
- global $db, $lang, $phpbb_root_path, $phpEx, $phpbb_extension_manager;
+ global $db, $lang, $phpbb_root_path, $phpEx, $phpbb_extension_manager, $config;
// modules require an extension manager
if (empty($phpbb_extension_manager))
{
- $phpbb_extension_manager = new phpbb_extension_manager($db, EXT_TABLE, $phpbb_root_path, ".$phpEx");
+ $phpbb_extension_manager = new phpbb_extension_manager($db, $config, EXT_TABLE, $phpbb_root_path, ".$phpEx");
}
include_once($phpbb_root_path . 'includes/acp/acp_modules.' . $phpEx);
diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql
index ea7864bd4c..ae7b9fcba3 100644
--- a/phpBB/install/schemas/schema_data.sql
+++ b/phpBB/install/schemas/schema_data.sql
@@ -345,6 +345,7 @@ INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_board', 1);
INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_bots', 1);
INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_clearlogs', 1);
INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_email', 1);
+INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_extensions', 1);
INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_fauth', 1);
INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_forum', 1);
INSERT INTO phpbb_acl_options (auth_option, is_global) VALUES ('a_forumadd', 1);
diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php
index 04df897dba..5eb10d50b3 100644
--- a/phpBB/language/en/acp/common.php
+++ b/phpBB/language/en/acp/common.php
@@ -81,6 +81,7 @@ $lang = array_merge($lang, array(
'ACP_EMAIL_SETTINGS' => 'Email settings',
'ACP_EXTENSION_GROUPS' => 'Manage extension groups',
+ 'ACP_EXTENSIONS' => 'Manage board extensions',
'ACP_FORUM_BASED_PERMISSIONS' => 'Forum based permissions',
'ACP_FORUM_LOGS' => 'Forum logs',
diff --git a/phpBB/language/en/acp/extensions.php b/phpBB/language/en/acp/extensions.php
new file mode 100644
index 0000000000..0adaff10c8
--- /dev/null
+++ b/phpBB/language/en/acp/extensions.php
@@ -0,0 +1,103 @@
+<?php
+/**
+*
+* acp_extensions [English]
+*
+* @package language
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
+*
+*/
+/**
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* DO NOT CHANGE
+*/
+if (empty($lang) || !is_array($lang))
+{
+ $lang = array();
+}
+
+// DEVELOPERS PLEASE NOTE
+//
+// Placeholders can now contain order information, e.g. instead of
+// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows
+// translators to re-order the output of data while ensuring it remains correct
+//
+// You do not need this where single placeholders are used, e.g. 'Message %d' is fine
+// equally where a string contains only two placeholders which are used to wrap text
+// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine
+
+
+$lang = array_merge($lang, array(
+ 'EXTENSION' => 'Extension',
+ 'EXTENSIONS' => 'Extensions',
+ 'EXTENSIONS_ADMIN' => 'Extensions Manager',
+ 'EXTENSIONS_EXPLAIN' => 'The Extensions Manager is a tool in your phpBB Board which allows you to manage all of your extensions statuses and view information about them.',
+ 'EXTENSION_INVALID_LIST' => 'The "%s" extension is not valid.<br /><p>%s</p>',
+ 'EXTENSION_NOT_AVAILABLE' => 'The selected extension is not available for this board, please verify your phpBB and PHP versions are allowed (see the details page).',
+
+ 'DETAILS' => 'Details',
+
+ 'AVAILABLE' => 'Available',
+ 'ENABLED' => 'Enabled',
+ 'DISABLED' => 'Disabled',
+ 'PURGED' => 'Purged',
+ 'UPLOADED' => 'Uploaded',
+
+ 'ENABLE' => 'Enable',
+ 'DISABLE' => 'Disable',
+ 'PURGE' => 'Purge',
+
+ 'ENABLE_EXPLAIN' => 'Enabling an extension allows you to use it on your board.',
+ 'DISABLE_EXPLAIN' => 'Disabling an extension retains its files and settings but removes any functionality added by the extension.',
+ 'PURGE_EXPLAIN' => 'Purging an extension clears an extensions data while retaining its files.',
+ 'DELETE_EXPLAIN' => 'Deleting an extension removes all of its files and settings. Log entries will remain, although any language variables added by the extension will not be available.',
+
+ 'DISABLE_IN_PROGRESS' => 'The extension is currently being disabled, please do not leave this page or refresh until it is completed.',
+ 'ENABLE_IN_PROGRESS' => 'The extension is currently being installed, please do not leave this page or refresh until it is completed.',
+ 'PURGE_IN_PROGRESS' => 'The extension is currently being purged, please do not leave this page or refresh until it is completed.',
+ 'ENABLE_SUCCESS' => 'The extension was enabled successfully',
+ 'DISABLE_SUCCESS' => 'The extension was disabled successfully',
+ 'PURGE_SUCCESS' => 'The extension was purged successfully',
+
+ 'ENABLE_FAIL' => 'The extension could not be enabled',
+ 'DISABLE_FAIL' => 'The extension could not be disabled',
+ 'PURGE_FAIL' => 'The extension could not be purged',
+
+ 'EXTENSION_NAME' => 'Extension Name',
+ 'EXTENSION_ACTIONS' => 'Actions',
+ 'EXTENSION_OPTIONS' => 'Options',
+
+ 'ENABLE_CONFIRM' => 'Are you sure that you wish to enable this extension?',
+ 'DISABLE_CONFIRM' => 'Are you sure that you wish to disable this extension?',
+ 'PURGE_CONFIRM' => 'Are you sure that you wish to purge this extension&#39;s data? This will remove all settings stored for this extension and cannot be undone!',
+
+ 'WARNING' => 'Warning',
+ 'RETURN' => 'Return',
+
+ 'EXT_DETAILS' => 'Extension Details',
+ 'DISPLAY_NAME' => 'Display Name',
+ 'CLEAN_NAME' => 'Clean Name',
+ 'TYPE' => 'Type',
+ 'DESCRIPTION' => 'Description',
+ 'VERSION' => 'Version',
+ 'HOMEPAGE' => 'Homepage',
+ 'PATH' => 'File Path',
+ 'TIME' => 'Release Time',
+ 'LICENCE' => 'Licence',
+
+ 'REQUIREMENTS' => 'Requirements',
+ 'PHPBB_VERSION' => 'phpBB Version',
+ 'PHP_VERSION' => 'PHP Version',
+ 'AUTHOR_INFORMATION' => 'Author Information',
+ 'AUTHOR_NAME' => 'Name',
+ 'AUTHOR_EMAIL' => 'Email',
+ 'AUTHOR_HOMEPAGE' => 'Homepage',
+ 'AUTHOR_ROLE' => 'Role',
+));
diff --git a/phpBB/language/en/acp/permissions_phpbb.php b/phpBB/language/en/acp/permissions_phpbb.php
index 17649693fa..bb068e625f 100644
--- a/phpBB/language/en/acp/permissions_phpbb.php
+++ b/phpBB/language/en/acp/permissions_phpbb.php
@@ -226,6 +226,7 @@ $lang = array_merge($lang, array(
'acl_a_switchperm' => array('lang' => 'Can use others permissions', 'cat' => 'permissions'),
'acl_a_styles' => array('lang' => 'Can manage styles', 'cat' => 'misc'),
+ 'acl_a_extensions' => array('lang' => 'Can manage extensions', 'cat' => 'misc'),
'acl_a_viewlogs' => array('lang' => 'Can view logs', 'cat' => 'misc'),
'acl_a_clearlogs' => array('lang' => 'Can clear logs', 'cat' => 'misc'),
'acl_a_modules' => array('lang' => 'Can manage modules', 'cat' => 'misc'),