Elgg  Version 1.11
DiContainer.php
Go to the documentation of this file.
1 <?php
2 namespace Elgg\Di;
3 
28 class DiContainer {
29 
33  protected $factories = array();
34 
38  protected $cache = array();
39 
40  const CLASS_NAME_PATTERN_53 = '/^(\\\\?[a-z_\x7f-\xff][a-z0-9_\x7f-\xff]*)+$/i';
41 
49  public function __get($name) {
50  if (array_key_exists($name, $this->cache)) {
51  return $this->cache[$name];
52  }
53  if (!isset($this->factories[$name])) {
54  throw new \Elgg\Di\MissingValueException("Value or factory was not set for: $name");
55  }
56  $value = $this->build($this->factories[$name]['callable'], $name);
57 
58  // Why check existence of factory here? A: the builder function may have set the value
59  // directly, in which case the factory will no longer exist.
60  if (!empty($this->factories[$name]) && $this->factories[$name]['shared']) {
61  $this->cache[$name] = $value;
62  }
63  return $value;
64  }
65 
74  protected function build($factory, $name) {
75  if (is_callable($factory)) {
76  return call_user_func($factory, $this);
77  }
78  $msg = "Factory for '$name' was uncallable";
79  if (is_string($factory)) {
80  $msg .= ": '$factory'";
81  } elseif (is_array($factory)) {
82  if (is_string($factory[0])) {
83  $msg .= ": '{$factory[0]}::{$factory[1]}'";
84  } else {
85  $msg .= ": " . get_class($factory[0]) . "->{$factory[1]}";
86  }
87  }
88  throw new \Elgg\Di\FactoryUncallableException($msg);
89  }
90 
99  public function setValue($name, $value) {
100  $this->remove($name);
101  $this->cache[$name] = $value;
102  return $this;
103  }
104 
114  public function setFactory($name, $callable, $shared = true) {
115  if (!is_callable($callable, true)) {
116  throw new \InvalidArgumentException('$factory must appear callable');
117  }
118  $this->remove($name);
119  $this->factories[$name] = array(
120  'callable' => $callable,
121  'shared' => $shared
122  );
123  return $this;
124  }
125 
135  public function setClassName($name, $class_name, $shared = true) {
136  $classname_pattern = self::CLASS_NAME_PATTERN_53;
137  if (!is_string($class_name) || !preg_match($classname_pattern, $class_name)) {
138  throw new \InvalidArgumentException('Class names must be valid PHP class names');
139  }
140  $func = function () use ($class_name) {
141  return new $class_name();
142  };
143  return $this->setFactory($name, $func, $shared);
144  }
145 
152  public function remove($name) {
153  unset($this->cache[$name]);
154  unset($this->factories[$name]);
155  return $this;
156  }
157 
164  public function has($name) {
165  return isset($this->factories[$name]) || array_key_exists($name, $this->cache);
166  }
167 }
168 
__get($name)
Fetch a value.
Definition: DiContainer.php:49
if($guid==elgg_get_logged_in_user_guid()) $name
Definition: delete.php:21
$value
Definition: longtext.php:26
has($name)
Does the container have this value.
setClassName($name, $class_name, $shared=true)
Set a factory based on instantiating a class with no arguments.
setValue($name, $value)
Set a value to be returned without modification.
Definition: DiContainer.php:99
build($factory, $name)
Build a value.
Definition: DiContainer.php:74
setFactory($name, $callable, $shared=true)
Set a factory to generate a value when the container is read.