Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
50.00% |
5 / 10 |
CRAP | |
90.12% |
73 / 81 |
| metadata_manager | |
0.00% |
0 / 1 |
|
50.00% |
5 / 10 |
35.11 | |
90.12% |
73 / 81 |
| __construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
| get_metadata | |
0.00% |
0 / 1 |
7.39 | |
80.00% |
12 / 15 |
|||
| fetch_metadata_from_file | |
0.00% |
0 / 1 |
4.07 | |
83.33% |
10 / 12 |
|||
| sanitize_json | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| validate | |
0.00% |
0 / 1 |
7 | |
96.15% |
25 / 26 |
|||
| validate_authors | |
100.00% |
1 / 1 |
4 | |
100.00% |
9 / 9 |
|||
| validate_enable | |
100.00% |
1 / 1 |
3 | |
100.00% |
1 / 1 |
|||
| validate_dir | |
100.00% |
1 / 1 |
3 | |
100.00% |
4 / 4 |
|||
| validate_require_phpbb | |
0.00% |
0 / 1 |
2.06 | |
75.00% |
3 / 4 |
|||
| validate_require_php | |
0.00% |
0 / 1 |
2.06 | |
75.00% |
3 / 4 |
|||
| <?php | |
| /** | |
| * | |
| * This file is part of the phpBB Forum Software package. | |
| * | |
| * @copyright (c) phpBB Limited <https://www.phpbb.com> | |
| * @license GNU General Public License, version 2 (GPL-2.0) | |
| * | |
| * For full copyright and license information, please see | |
| * the docs/CREDITS.txt file. | |
| * | |
| */ | |
| namespace phpbb\extension; | |
| /** | |
| * The extension metadata manager validates and gets meta-data for extensions | |
| */ | |
| class metadata_manager | |
| { | |
| /** | |
| * Name (including vendor) of the extension | |
| * @var string | |
| */ | |
| protected $ext_name; | |
| /** | |
| * Metadata from the composer.json file | |
| * @var array | |
| */ | |
| protected $metadata; | |
| /** | |
| * Link (including root path) to the metadata file | |
| * @var string | |
| */ | |
| protected $metadata_file; | |
| /** | |
| * Creates the metadata manager | |
| * | |
| * @param string $ext_name Name (including vendor) of the extension | |
| * @param string $ext_path Path to the extension directory including root path | |
| */ | |
| public function __construct($ext_name, $ext_path) | |
| { | |
| $this->ext_name = $ext_name; | |
| $this->metadata = array(); | |
| $this->metadata_file = $ext_path . 'composer.json'; | |
| } | |
| /** | |
| * 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') | |
| { | |
| // Fetch and clean the metadata if not done yet | |
| if ($this->metadata === array()) | |
| { | |
| $this->fetch_metadata_from_file(); | |
| } | |
| switch ($element) | |
| { | |
| case 'all': | |
| default: | |
| $this->validate(); | |
| return $this->metadata; | |
| break; | |
| case 'version': | |
| case 'name': | |
| $this->validate($element); | |
| return $this->metadata[$element]; | |
| break; | |
| case 'display-name': | |
| return (isset($this->metadata['extra']['display-name'])) ? $this->metadata['extra']['display-name'] : $this->get_metadata('name'); | |
| break; | |
| } | |
| } | |
| /** | |
| * Gets the metadata file contents and cleans loaded file | |
| * | |
| * @throws \phpbb\extension\exception | |
| */ | |
| private function fetch_metadata_from_file() | |
| { | |
| if (!file_exists($this->metadata_file)) | |
| { | |
| throw new \phpbb\extension\exception('FILE_NOT_FOUND', array($this->metadata_file)); | |
| } | |
| if (!($file_contents = file_get_contents($this->metadata_file))) | |
| { | |
| throw new \phpbb\extension\exception('FILE_CONTENT_ERR', array($this->metadata_file)); | |
| } | |
| if (($metadata = json_decode($file_contents, true)) === null) | |
| { | |
| throw new \phpbb\extension\exception('FILE_JSON_DECODE_ERR', array($this->metadata_file)); | |
| } | |
| array_walk_recursive($metadata, array($this, 'sanitize_json')); | |
| $this->metadata = $metadata; | |
| } | |
| /** | |
| * Sanitize input from JSON array using htmlspecialchars() | |
| * | |
| * @param mixed $value Value of array row | |
| * @param string $key Key of array row | |
| */ | |
| public function sanitize_json(&$value, $key) | |
| { | |
| $value = htmlspecialchars($value); | |
| } | |
| /** | |
| * 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 | |
| * @throws \phpbb\extension\exception | |
| */ | |
| 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' => '#^phpbb-extension$#', | |
| 'license' => '#.+#', | |
| 'version' => '#.+#', | |
| ); | |
| switch ($name) | |
| { | |
| case 'all': | |
| $this->validate_enable(); | |
| // no 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('META_FIELD_NOT_SET', array($name)); | |
| } | |
| if (!preg_match($fields[$name], $this->metadata[$name])) | |
| { | |
| throw new \phpbb\extension\exception('META_FIELD_INVALID', array($name)); | |
| } | |
| } | |
| break; | |
| } | |
| return true; | |
| } | |
| /** | |
| * Validates the contents of the authors field | |
| * | |
| * @return boolean True when passes validation, throws exception if invalid | |
| * @throws \phpbb\extension\exception | |
| */ | |
| public function validate_authors() | |
| { | |
| if (empty($this->metadata['authors'])) | |
| { | |
| throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array('authors')); | |
| } | |
| foreach ($this->metadata['authors'] as $author) | |
| { | |
| if (!isset($author['name'])) | |
| { | |
| throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array('author name')); | |
| } | |
| } | |
| return true; | |
| } | |
| /** | |
| * This array handles the verification that this extension can be enabled on this board | |
| * | |
| * @return bool True if validation succeeded, throws an exception if invalid | |
| * @throws \phpbb\extension\exception | |
| */ | |
| public function validate_enable() | |
| { | |
| // Check for valid directory & phpBB, PHP versions | |
| return $this->validate_dir() && $this->validate_require_phpbb() && $this->validate_require_php(); | |
| } | |
| /** | |
| * Validates the most basic directory structure to ensure it follows <vendor>/<ext> convention. | |
| * | |
| * @return boolean True when passes validation, throws an exception if invalid | |
| * @throws \phpbb\extension\exception | |
| */ | |
| public function validate_dir() | |
| { | |
| if (substr_count($this->ext_name, '/') !== 1 || $this->ext_name != $this->get_metadata('name')) | |
| { | |
| throw new \phpbb\extension\exception('EXTENSION_DIR_INVALID'); | |
| } | |
| return true; | |
| } | |
| /** | |
| * Validates the contents of the phpbb requirement field | |
| * | |
| * @return boolean True when passes validation, throws an exception if invalid | |
| * @throws \phpbb\extension\exception | |
| */ | |
| public function validate_require_phpbb() | |
| { | |
| if (!isset($this->metadata['extra']['soft-require']['phpbb/phpbb'])) | |
| { | |
| throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array('soft-require')); | |
| } | |
| return true; | |
| } | |
| /** | |
| * Validates the contents of the php requirement field | |
| * | |
| * @return boolean True when passes validation, throws an exception if invalid | |
| * @throws \phpbb\extension\exception | |
| */ | |
| public function validate_require_php() | |
| { | |
| if (!isset($this->metadata['require']['php'])) | |
| { | |
| throw new \phpbb\extension\exception('META_FIELD_NOT_SET', array('require php')); | |
| } | |
| return true; | |
| } | |
| } |