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    public function __construct( string $path ) {
22        $this->path = $path;
23    }
24
25    /**
26     * Loads an array structure from a PHP file and return
27     * for using with merge strategies to apply on configs.
28     *
29     * @throws SettingsBuilderException
30     * @return array
31     */
32    public function load(): array {
33        // NOTE: try include first, for performance reasons. If all goes well, it will
34        //       use the opcode cache, and will not touch the file system at all.
35        //       So we should only go and look at the file system if the include fails.
36
37        $source = AtEase::quietCall( static function ( $path ) {
38            return include $path;
39        }, $this->path );
40
41        if ( $source === false ) {
42            if ( !file_exists( $this->path ) ) {
43                throw new SettingsBuilderException(
44                    "'File: {path}' does not exist",
45                    [ 'path' => $this->path ]
46                );
47            }
48
49            if ( !is_readable( $this->path ) ) {
50                throw new SettingsBuilderException(
51                    "File '{path}' is not readable",
52                    [ 'path' => $this->path ]
53                );
54            }
55
56            if ( is_dir( $this->path ) ) {
57                throw new SettingsBuilderException(
58                    "'{path}' is a directory, not a file",
59                    [ 'path' => $this->path ]
60                );
61            }
62        }
63
64        if ( !is_array( $source ) ) {
65            throw new SettingsBuilderException(
66                "File '{path}' did not return an array",
67                [ 'path' => $this->path ]
68            );
69        }
70
71        return $source;
72    }
73
74    /**
75     * Returns this file source as a string.
76     */
77    public function __toString(): string {
78        return $this->path;
79    }
80
81    public function locateInclude( string $location ): string {
82        return SettingsFileUtils::resolveRelativeLocation( $location, dirname( $this->path ) );
83    }
84
85}