Passed
Push — master ( 2b7b1b...185c2b )
by Jean-Christophe
06:02
created

ArrayLoader::load()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 26
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 7.0572

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 26
ccs 17
cts 19
cp 0.8947
rs 8.8333
c 0
b 0
f 0
cc 7
nc 8
nop 2
crap 7.0572
1
<?php
2
3
namespace Ubiquity\translation\loader;
4
5
use Ubiquity\utils\base\UFileSystem;
6
use Ubiquity\utils\base\UArray;
7
use Ubiquity\log\Logger;
8
9
/**
10
 * ArrayLoader for TranslatorManager
11
 * Ubiquity\translation\loader$ArrayLoader
12
 * This class is part of Ubiquity
13
 *
14
 * @author jcheron <[email protected]>
15
 * @version 1.0.2
16
 *
17
 */
18
class ArrayLoader implements LoaderInterface {
19
	private $rootDir;
20
21 2
	private function getRootKey($locale = null, $domain = null) {
22 2
		return $this->rootDir . $locale ?? '' . $domain ?? '';
23
	}
24
25 2
	public function __construct($rootDir) {
26 2
		$this->rootDir = $rootDir;
27 2
	}
28
29 2
	public function load($locale, $domain = '*') {
30 2
		$key = $this->getRootKey ( $locale, $domain );
31 2
		if (self::hasAPC () && apc_exists ( $key )) {
1 ignored issue
show
Bug introduced by
$key of type string is incompatible with the type boolean|string[] expected by parameter $keys of apc_exists(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

31
		if (self::hasAPC () && apc_exists ( /** @scrutinizer ignore-type */ $key )) {
Loading history...
32
			Logger::info ( 'Translate', 'Loading ' . $locale . '.' . $domain . ' from apc_cache', 'load' );
33
			return apc_fetch ( $key );
34
		}
35 2
		$messages = [ ];
36 2
		$rootDirectory = $this->getRootDirectory ( $locale );
37 2
		if (file_exists ( $rootDirectory )) {
38 1
			$files = UFileSystem::glob_recursive ( $rootDirectory . $domain . '.php' );
39 1
			foreach ( $files as $file ) {
40 1
				if (file_exists ( $file )) {
41 1
					$name = basename ( $file, '.php' );
42 1
					Logger::info ( 'Translate', 'Loading ' . $locale . '.' . $domain . ' from file ' . $name, 'load', [ get_class () ] );
43 1
					$messages [$name] = $this->loadFile ( $file );
44
				}
45
			}
46 1
			$this->flatten ( $messages );
47 1
			if (self::hasAPC ()) {
48 1
				apc_store ( $key, $messages );
49
			}
50
		} else {
51 1
			return false;
52
		}
53
54 1
		return $messages;
55
	}
56
57 2
	private static function hasAPC() {
58 2
		return function_exists ( 'apc_exists' );
59
	}
60
61
	public function clearCache($locale = null, $domain = null) {
62
		if (self::hasAPC ()) {
63
			$iterator = new \APCIterator ( '/^' . $this->getRootKey ( $locale, $domain ) . '/' );
64
			foreach ( $iterator as $apc_cache ) {
65
				apc_delete ( $apc_cache ['key'] );
66
			}
67
		}
68
	}
69
70 1
	protected function loadFile($filename) {
71 1
		return include $filename;
72
	}
73
74 2
	private function getRootDirectory($locale) {
75 2
		return $this->rootDir . \DS . $locale . \DS;
76
	}
77
78
	private function getDirectory($domain, &$filename) {
79
		$parts = explode ( '.', $domain );
80
		$filename = array_pop ( $parts ) . ".php";
81
		return implode ( \DS, $parts );
82
	}
83
84
	/**
85
	 * Flattens an nested array of translations.
86
	 *
87
	 * The scheme used is:
88
	 * 'key' => array('key2' => array('key3' => 'value'))
89
	 * Becomes:
90
	 * 'key.key2.key3' => 'value'
91
	 *
92
	 * This function takes an array by reference and will modify it
93
	 *
94
	 * @param
95
	 *        	array &$messages The array that will be flattened
96
	 * @param array $subnode
97
	 *        	Current subnode being parsed, used internally for recursive calls
98
	 * @param string $path
99
	 *        	Current path being parsed, used internally for recursive calls
100
	 */
101 1
	private function flatten(array &$messages, array $subnode = null, $path = null) {
102 1
		if (null === $subnode) {
103 1
			$subnode = &$messages;
104
		}
105 1
		foreach ( $subnode as $key => $value ) {
106 1
			if (\is_array ( $value )) {
107 1
				$nodePath = $path ? $path . '.' . $key : $key;
108 1
				$this->flatten ( $messages, $value, $nodePath );
109 1
				if (null === $path) {
110 1
					unset ( $messages [$key] );
111
				}
112 1
			} elseif (null !== $path) {
113 1
				$messages [$path . '.' . $key] = $value;
114
			}
115
		}
116 1
	}
117
118
	public function save($messages, $locale, $domain) {
119
		$content = "<?php\nreturn " . UArray::asPhpArray ( $messages, 'array' ) . ';';
120
		$filename = "";
121
		$path = $this->getRootDirectory ( $locale ) . $this->getDirectory ( $domain, $filename );
122
		if (UFileSystem::safeMkdir ( $path )) {
123
			if (@\file_put_contents ( $path . \DS . $filename, $content, LOCK_EX ) === false) {
124
				throw new \Exception ( "Unable to write cache file: {$filename}" );
125
			}
126
		} else {
127
			throw new \Exception ( "Unable to create folder : {$path}" );
128
		}
129
	}
130
}
131