Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
PathResolver
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
5 / 5
10
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getLocalConfigPath
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
 getBaseConfigPath
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getConfigPath
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 buildPath
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3/**
4 * Configuration File Path Resolver
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2010.
9 * Copyright (C) The National Library of Finland 2022.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2,
13 * as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23 *
24 * @category VuFind
25 * @package  Config
26 * @author   Demian Katz <demian.katz@villanova.edu>
27 * @author   Ere Maijala <ere.maijala@helsinki.fi>
28 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
29 * @link     https://vufind.org Main Site
30 */
31
32namespace VuFind\Config;
33
34/**
35 * Configuration File Path Resolver
36 *
37 * @category VuFind
38 * @package  Config
39 * @author   Demian Katz <demian.katz@villanova.edu>
40 * @author   Ere Maijala <ere.maijala@helsinki.fi>
41 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
42 * @link     https://vufind.org Main Site
43 */
44class PathResolver
45{
46    /**
47     * Default configuration subdirectory.
48     *
49     * @var string
50     */
51    public const DEFAULT_CONFIG_SUBDIR = 'config/vufind';
52
53    /**
54     * Base directory
55     *
56     * Must contain the following keys:
57     *
58     * directory           - The base configuration directory
59     * defaultConfigSubdir - Default subdirectory under directory for configuration
60     *                       files
61     *
62     * @var array
63     */
64    protected $baseDirectorySpec;
65
66    /**
67     * Local configuration directory stack. Local configuration files are searched
68     * for in all directories until found, starting from the last entry.
69     *
70     * Each entry must contain the following keys:
71     *
72     * directory           - The local configuration directory
73     * defaultConfigSubdir - Default subdirectory under directory for configuration
74     *                       files
75     *
76     * @var array
77     */
78    protected $localConfigDirStack;
79
80    /**
81     * Constructor
82     *
83     * @param array $baseDirectorySpec   Base directory specification
84     * @param array $localConfigDirStack Local configuration directory specification
85     * stack
86     */
87    public function __construct(
88        array $baseDirectorySpec,
89        array $localConfigDirStack
90    ) {
91        $this->baseDirectorySpec = $baseDirectorySpec;
92        $this->localConfigDirStack = $localConfigDirStack;
93    }
94
95    /**
96     * Get the file path to the local configuration file (null if none found).
97     *
98     * @param string  $filename config file name
99     * @param ?string $path     path relative to VuFind base (optional; use null for
100     * default)
101     * @param bool    $force    force method to return path even if file does not
102     * exist (default = false, do not force)
103     *
104     * @return ?string
105     */
106    public function getLocalConfigPath(
107        string $filename,
108        ?string $path = null,
109        bool $force = false
110    ): ?string {
111        $fallbackResult = null;
112        foreach (array_reverse($this->localConfigDirStack) as $localDirSpec) {
113            $configPath = $this->buildPath($localDirSpec, $path, $filename);
114            if (file_exists($configPath)) {
115                return $configPath;
116            }
117            if ($force && null === $fallbackResult) {
118                $fallbackResult = $configPath;
119            }
120        }
121        return $fallbackResult;
122    }
123
124    /**
125     * Get the file path to the base configuration file.
126     *
127     * @param string  $filename config file name
128     * @param ?string $path     path relative to VuFind base (optional; use null for
129     * default)
130     *
131     * @return string
132     */
133    public function getBaseConfigPath(string $filename, ?string $path = null): string
134    {
135        return $this->buildPath($this->baseDirectorySpec, $path, $filename);
136    }
137
138    /**
139     * Get the file path to a config file.
140     *
141     * @param string  $filename Config file name
142     * @param ?string $path     Path relative to VuFind base (optional; use null for
143     * default)
144     *
145     * @return string
146     */
147    public function getConfigPath(string $filename, ?string $path = null): ?string
148    {
149        // Check if config exists in local dir:
150        $local = $this->getLocalConfigPath($filename, $path);
151        if (!empty($local)) {
152            return $local;
153        }
154
155        // Return base version:
156        return $this->getBaseConfigPath($filename, $path);
157    }
158
159    /**
160     * Build a complete file path from a directory specification, optional
161     * configuration file sub-directory and a filename.
162     *
163     * @param array   $directorySpec Directory specification
164     * @param ?string $configSubdir  Optional configuration file subdirectory
165     * @param string  $filename      Filename
166     *
167     * @return string
168     */
169    protected function buildPath(
170        array $directorySpec,
171        ?string $configSubdir,
172        string $filename
173    ): string {
174        return $directorySpec['directory']
175            . '/' . ($configSubdir ?? $directorySpec['defaultConfigSubdir'])
176            . "/$filename";
177    }
178}