Erebot  latest
A modular IRC bot for PHP 7.0+
Proxy.php
1 <?php
2 /*
3  This file is part of Erebot, a modular IRC bot written in PHP.
4 
5  Copyright © 2010 François Poirotte
6 
7  Erebot is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  Erebot is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with Erebot. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 namespace Erebot\Config;
22 
37 class Proxy
38 {
40  protected $locale;
41 
43  protected $proxified;
44 
46  protected $modules;
47 
58  protected function __construct(
59  \Erebot\Interfaces\Config\Proxy $proxified,
60  \SimpleXMLElement $xml
61  ) {
62  $this->proxified = $proxified;
63  $this->modules = array();
64 
65  if (isset($xml['language'])) {
66  $this->locale = (string) $xml['language'];
67  } else {
68  $this->locale = null;
69  }
70 
71  if (!isset($xml->modules->module)) {
72  return;
73  }
74 
75  foreach ($xml->modules->module as $module) {
77  $instance = new \Erebot\Config\Module($module);
78  $this->modules[$instance->getName()] = $instance;
79  }
80  }
81 
86  public function __destruct()
87  {
88  unset(
89  $this->modules,
90  $this->proxified
91  );
92  }
93 
97  public function __clone()
98  {
99  throw new \Exception("Cloning forbidden!");
100  }
101 
102  protected static function getBaseDir($component)
103  {
104  $reflector = new \ReflectionClass($component);
105  $parts = explode(DIRECTORY_SEPARATOR, $reflector->getFileName());
106  do {
107  $last = array_pop($parts);
108  } while ($last !== 'src' && count($parts));
109  $parts[] = 'data';
110  $parts[] = 'i18n';
111  $base = implode(DIRECTORY_SEPARATOR, $parts);
112  return $base;
113  }
114 
116  public function getTranslator($component)
117  {
118  if (isset($this->locale)) {
119  $domain = str_replace('\\', '_', ltrim($component, '\\'));
120  $localedir = static::getBaseDir($component);
121  return \Erebot\Intl\GettextFactory::translation($domain, $localedir, array($this->locale));
122  }
123 
124  if ($this->proxified === $this) {
125  throw new \Erebot\NotFoundException('No translator associated');
126  }
127 
128  return $this->proxified->getTranslator($component);
129  }
130 
132  public function getMainCfg()
133  {
134  if ($this->proxified === $this) {
135  return $this;
136  }
137  return $this->proxified->getMainCfg();
138  }
139 
141  public function getModules($recursive)
142  {
143  if (!is_bool($recursive)) {
144  throw new \Erebot\InvalidValueException(
145  'Invalid value for recursion'
146  );
147  }
148 
149  if ($recursive && $this->proxified !== $this) {
150  $inherited = $this->proxified->getModules(true);
151  } else {
152  $inherited = array();
153  }
154 
155  $added = array();
156  $removed = array();
157  foreach ($this->modules as $name => $module) {
158  if ($module->isActive()) {
159  $added[] = $name;
160  } else {
161  $removed[] = $name;
162  }
163  }
164 
165  $inherited = array_diff($inherited, $removed);
166  return array_merge($added, $inherited);
167  }
168 
170  public function getModule($moduleName)
171  {
172  $moduleName = '\\' . ltrim($moduleName, '\\');
173  if (!isset($this->modules[$moduleName])) {
174  if ($this->proxified !== $this) {
175  return $this->proxified->getModule($moduleName);
176  }
177  throw new \Erebot\NotFoundException('No such module "' .
178  $moduleName . '"');
179  }
180  return $this->modules[$moduleName];
181  }
182 
203  public static function parseBoolHelper($value)
204  {
205  $value = strtolower($value);
206  if (in_array($value, array('true', '1', 'on', 'yes'), true)) {
207  return true;
208  }
209  if (in_array($value, array('false', '0', 'off', 'no'), true)) {
210  return false;
211  }
212  return null;
213  }
214 
228  public static function parseIntHelper($value)
229  {
230  if ($value == '') {
231  return null;
232  }
233 
234  if (is_int($value)) {
235  return $value;
236  }
237 
238  if (ctype_digit($value)) {
239  return (int) $value;
240  }
241 
242  if (strpos('+-', $value[0]) !== false && ctype_digit(substr($value, 1))) {
243  return (int) $value;
244  }
245 
246  return null;
247  }
248 
262  public static function parseRealHelper($value)
263  {
264  if (!is_numeric($value)) {
265  return null;
266  }
267 
268  return (double) $value;
269  }
270 
313  protected function parseSomething(
314  $module,
315  $param,
316  $default,
317  callable $parser,
318  $origin,
319  callable $checker
320  ) {
321  try {
322  if (!isset($this->modules[$module])) {
323  throw new \Erebot\NotFoundException('No such module');
324  }
325  $value = $this->modules[$module]->getParam($param);
326  $value = $parser($value);
327  if ($value !== null) {
328  return $value;
329  }
330  throw new \Erebot\InvalidValueException(
331  'Bad value in configuration'
332  );
333  } catch (\Erebot\NotFoundException $e) {
334  if ($this->proxified !== $this) {
335  return $this->proxified->$origin($module, $param, $default);
336  }
337 
338  if ($default === null) {
339  throw new \Erebot\NotFoundException('No such parameter "' .
340  $param . '" for module "' .
341  $module . '"');
342  }
343 
344  if ($checker($default)) {
345  return $default;
346  }
347  throw new \Erebot\InvalidValueException('Bad default value');
348  }
349  }
350 
352  public function parseBool($module, $param, $default = null)
353  {
354  return $this->parseSomething(
355  $module,
356  $param,
357  $default,
358  array($this, 'parseBoolHelper'),
359  __FUNCTION__,
360  'is_bool'
361  );
362  }
363 
365  public function parseString($module, $param, $default = null)
366  {
367  return $this->parseSomething(
368  $module,
369  $param,
370  $default,
371  'strval',
372  __FUNCTION__,
373  'is_string'
374  );
375  }
376 
378  public function parseInt($module, $param, $default = null)
379  {
380  return $this->parseSomething(
381  $module,
382  $param,
383  $default,
384  array($this, 'parseIntHelper'),
385  __FUNCTION__,
386  'is_int'
387  );
388  }
389 
391  public function parseReal($module, $param, $default = null)
392  {
393  return $this->parseSomething(
394  $module,
395  $param,
396  $default,
397  array($this, 'parseRealHelper'),
398  __FUNCTION__,
399  'is_real'
400  );
401  }
402 }
parseReal($module, $param, $default=null)
Definition: Proxy.php:391
getModules($recursive)
Definition: Proxy.php:141
$locale
The current locale.
Definition: Proxy.php:40
parseSomething($module, $param, $default, callable $parser, $origin, callable $checker)
Definition: Proxy.php:313
parseBool($module, $param, $default=null)
Definition: Proxy.php:352
static parseBoolHelper($value)
Definition: Proxy.php:203
getTranslator($component)
Definition: Proxy.php:116
__construct(\Erebot\Interfaces\Config\Proxy $proxified,\SimpleXMLElement $xml)
Definition: Proxy.php:58
static parseRealHelper($value)
Definition: Proxy.php:262
$proxified
Reference to a proxified object.
Definition: Proxy.php:43
parseInt($module, $param, $default=null)
Definition: Proxy.php:378
parseString($module, $param, $default=null)
Definition: Proxy.php:365
static parseIntHelper($value)
Definition: Proxy.php:228
getModule($moduleName)
Definition: Proxy.php:170
A configuration proxy which cascades settings.
Definition: Proxy.php:37
$modules
Array of modules loaded at this particular configuration level.
Definition: Proxy.php:46