PluginProbe
Metricool – Social media and site statistics / 2.1.1
Metricool – Social media and site statistics v2.1.1
2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.27 trunk
metricool / app / Support / Helpers / Storages / GeneralConfig.php

GeneralConfig.php in Metricool – Social media and site statistics 2.1.1, at app/Support/Helpers/Storages/GeneralConfig.php

128 lines 4.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Metricool\Support\Helpers\Storages;
6
7 use Metricool\Support\Helpers\Storage;
8 use Metricool\Support\Helpers\DeferredObject;
9
10 /**
11 * General config helper used in DI container.
12 *
13 * @mixin Storage This class acts as a proxy to Storage. All method calls are
14 * resolved dynamically through {@see DeferredObject::__get()}
15 */
16 final class GeneralConfig extends DeferredObject
17 {
18 private array $filesToSkip = [
19 'env', // EnvironmentConfig
20 'middleware', // MiddlewareConfig
21 'user_settings', // UserSettingsConfig
22 'languages', // LanguagesConfig
23 ];
24
25 /**
26 * @inheritDoc
27 */
28 protected function deferredClassString(): string
29 {
30 return Storage::class;
31 }
32
33 /**
34 * @inheritDoc
35 */
36 protected function deferredConstructArguments(): array
37 {
38 return [
39 $this->storageFromPath(dirname(__FILE__, 5) . '/config', $this->filesToSkip, true),
40 ];
41 }
42
43 /**
44 * Return all config files as GeneralConfig. If path is a directory, it will
45 * merge all the files in the directory.
46 *
47 * @param bool $prefixWithFileName Can be used to prefix the keys with the
48 * filename when loading a directory. Can be useful to bundle the config
49 * data of a file under the filename which makes it easier to retrieve a
50 * single fields config.
51 *
52 * @throws \InvalidArgumentException
53 */
54 private function storageFromPath(string $path, array $skip = [], bool $prefixWithFileName = false): array
55 {
56 if (!file_exists($path)) {
57 throw new \InvalidArgumentException(
58 'Unloadable configuration file ' . esc_html($path) . ' provided.'
59 );
60 }
61
62 $data = [];
63
64 if (is_dir($path)) {
65 $root = rtrim((string) realpath($path), DIRECTORY_SEPARATOR);
66
67 // Also loads files in nested dirs.
68 $iterator = new \RecursiveIteratorIterator(
69 new \RecursiveDirectoryIterator($root, \FilesystemIterator::SKIP_DOTS)
70 );
71
72 /** @var \SplFileInfo $file */
73 foreach ($iterator as $file) {
74 if (!$file->isFile() || in_array($file->getBasename('.php'), $skip)) {
75 continue;
76 }
77
78 $pathname = $file->getPathname();
79 $extension = strtolower((string) pathinfo($pathname, PATHINFO_EXTENSION));
80
81 if ($extension !== 'php') {
82 continue;
83 }
84
85 $fileData = require $pathname;
86 if (!is_array($fileData)) {
87 continue;
88 }
89
90 $fileName = (string) pathinfo($pathname, PATHINFO_FILENAME);
91 $fileDirPath = $file->getPath();
92
93 // Compute the directory relative to the root and take the last
94 // segment as the prefix.
95 $relativeDir = ltrim(substr($fileDirPath, strlen($root)), DIRECTORY_SEPARATOR);
96 $dirKey = ($relativeDir !== '' ? basename($relativeDir) : null);
97
98 if ($prefixWithFileName) {
99 if ($dirKey !== null) {
100 // Group by immediate subdirectory, then filename. Deep
101 // merge so multiple files in the same subdir accumulate
102 $data[$dirKey] = array_replace_recursive(
103 $data[$dirKey] ?? [],
104 [$fileName => $fileData]
105 );
106 } else {
107 // Top-level files keyed by filename.
108 $data = array_replace_recursive($data, [
109 $fileName => $fileData
110 ]);
111 }
112 } else {
113 // No prefixing: merge raw file data (deep) to avoid losing
114 // previously merged keys.
115 $data = array_replace_recursive($data, $fileData);
116 }
117 }
118 } else {
119 $loaded = require $path;
120 if (is_array($loaded)) {
121 $data = $loaded;
122 }
123 }
124
125 return $data;
126 }
127 }
128