Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
57.14% covered (warning)
57.14%
16 / 28
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
PhpSettingsSource
57.14% covered (warning)
57.14%
16 / 28
25.00% covered (danger)
25.00%
1 / 4
15.38
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 load
60.00% covered (warning)
60.00%
15 / 25
0.00% covered (danger)
0.00%
0 / 1
8.30
 __toString
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 locateInclude
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Settings\Source;
4
5use MediaWiki\Settings\SettingsBuilderException;
6use Stringable;
7use Wikimedia\AtEase\AtEase;
8
9/**
10 * Settings loaded from a PHP file path as an array structure.
11 *
12 * @since 1.38
13 */
14class PhpSettingsSource implements Stringable, SettingsSource, SettingsIncludeLocator {
15    /**
16     * Path to the PHP file.
17     * @var string
18     */
19    private $path;
20
21    /**
22     * @param string $path
23     */
24    public function __construct( string $path ) {
25        $this->path = $path;
26    }
27
28    /**
29     * Loads an array structure from a PHP file and return
30     * for using with merge strategies to apply on configs.
31     *
32     * @throws SettingsBuilderException
33     * @return array
34     */
35    public function load(): array {
36        // NOTE: try include first, for performance reasons. If all goes well, it will
37        //       use the opcode cache, and will not touch the file system at all.
38        //       So we should only go and look at the file system if the include fails.
39
40        $source = AtEase::quietCall( static function ( $path ) {
41            return include $path;
42        }, $this->path );
43
44        if ( $source === false ) {
45            if ( !file_exists( $this->path ) ) {
46                throw new SettingsBuilderException(
47                    "'File: {path}' does not exist",
48                    [ 'path' => $this->path ]
49                );
50            }
51
52            if ( !is_readable( $this->path ) ) {
53                throw new SettingsBuilderException(
54                    "File '{path}' is not readable",
55                    [ 'path' => $this->path ]
56                );
57            }
58
59            if ( is_dir( $this->path ) ) {
60                throw new SettingsBuilderException(
61                    "'{path}' is a directory, not a file",
62                    [ 'path' => $this->path ]
63                );
64            }
65        }
66
67        if ( !is_array( $source ) ) {
68            throw new SettingsBuilderException(
69                "File '{path}' did not return an array",
70                [ 'path' => $this->path ]
71            );
72        }
73
74        return $source;
75    }
76
77    /**
78     * Returns this file source as a string.
79     *
80     * @return string
81     */
82    public function __toString(): string {
83        return $this->path;
84    }
85
86    public function locateInclude( string $location ): string {
87        return SettingsFileUtils::resolveRelativeLocation( $location, dirname( $this->path ) );
88    }
89
90}