Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
50.00% covered (danger)
50.00%
5 / 10
CRAP
88.14% covered (warning)
88.14%
52 / 59
metadata_manager
0.00% covered (danger)
0.00%
0 / 1
50.00% covered (danger)
50.00%
5 / 10
35.93
88.14% covered (warning)
88.14%
52 / 59
 __construct
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
4 / 4
 get_metadata
0.00% covered (danger)
0.00%
0 / 1
7.23
83.33% covered (warning)
83.33%
10 / 12
 fetch_metadata_from_file
0.00% covered (danger)
0.00%
0 / 1
4.18
77.78% covered (warning)
77.78%
7 / 9
 sanitize_json
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 validate
0.00% covered (danger)
0.00%
0 / 1
7.01
93.75% covered (success)
93.75%
15 / 16
 validate_authors
100.00% covered (success)
100.00%
1 / 1
4
100.00% covered (success)
100.00%
6 / 6
 validate_enable
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
1 / 1
 validate_dir
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
3 / 3
 validate_require_phpbb
0.00% covered (danger)
0.00%
0 / 1
2.15
66.67% covered (warning)
66.67%
2 / 3
 validate_require_php
0.00% covered (danger)
0.00%
0 / 1
2.15
66.67% covered (warning)
66.67%
2 / 3
<?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, ENT_COMPAT);
    }
    /**
    * 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;
    }
}