Elgg  Version 2.2
 All Classes Namespaces Files Functions Variables Pages
DiContainer.php
Go to the documentation of this file.
1 <?php
2 namespace Elgg\Di;
3 
28 class DiContainer {
29 
33  private $factories_ = array();
34 
35  const CLASS_NAME_PATTERN_53 = '/^(\\\\?[a-z_\x7f-\xff][a-z0-9_\x7f-\xff]*)+$/i';
36 
44  public function __get($name) {
45  if (!isset($this->factories_[$name])) {
46  throw new \Elgg\Di\MissingValueException("Value or factory was not set for: $name");
47  }
48  $value = $this->build($this->factories_[$name]['callable'], $name);
49 
50  // Why check existence of factory here? A: the builder function may have set the value
51  // directly, in which case the factory will no longer exist.
52  if (!empty($this->factories_[$name]) && $this->factories_[$name]['shared']) {
53  $this->{$name} = $value;
54  }
55  return $value;
56  }
57 
66  private function build($factory, $name) {
67  if (is_callable($factory)) {
68  return call_user_func($factory, $this);
69  }
70  $msg = "Factory for '$name' was uncallable";
71  if (is_string($factory)) {
72  $msg .= ": '$factory'";
73  } elseif (is_array($factory)) {
74  if (is_string($factory[0])) {
75  $msg .= ": '{$factory[0]}::{$factory[1]}'";
76  } else {
77  $msg .= ": " . get_class($factory[0]) . "->{$factory[1]}";
78  }
79  }
80  throw new \Elgg\Di\FactoryUncallableException($msg);
81  }
82 
91  public function setValue($name, $value) {
92  if (substr($name, -1) === '_') {
93  throw new \InvalidArgumentException('$name cannot end with "_"');
94  }
95  $this->remove($name);
96  $this->{$name} = $value;
97  return $this;
98  }
99 
109  public function setFactory($name, $callable, $shared = true) {
110  if (substr($name, -1) === '_') {
111  throw new \InvalidArgumentException('$name cannot end with "_"');
112  }
113  if (!is_callable($callable, true)) {
114  throw new \InvalidArgumentException('$factory must appear callable');
115  }
116  $this->remove($name);
117  $this->factories_[$name] = array(
118  'callable' => $callable,
119  'shared' => $shared,
120  );
121  return $this;
122  }
123 
133  public function setClassName($name, $class_name, $shared = true) {
134  if (substr($name, -1) === '_') {
135  throw new \InvalidArgumentException('$name cannot end with "_"');
136  }
137  $classname_pattern = self::CLASS_NAME_PATTERN_53;
138  if (!is_string($class_name) || !preg_match($classname_pattern, $class_name)) {
139  throw new \InvalidArgumentException('Class names must be valid PHP class names');
140  }
141  $func = function () use ($class_name) {
142  return new $class_name();
143  };
144  return $this->setFactory($name, $func, $shared);
145  }
146 
153  public function remove($name) {
154  if (substr($name, -1) === '_') {
155  throw new \InvalidArgumentException('$name cannot end with "_"');
156  }
157  unset($this->{$name});
158  unset($this->factories_[$name]);
159  return $this;
160  }
161 
168  public function has($name) {
169  if (isset($this->factories_[$name])) {
170  return true;
171  }
172  if (substr($name, -1) === '_') {
173  return false;
174  }
175  return (bool)property_exists($this, $name);
176  }
177 
185  public function getNames() {
186  $names = [];
187 
188  $refl = new \ReflectionObject($this);
189  foreach ($refl->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
190  $names[] = $prop->name;
191  }
192  foreach (array_keys($this->factories_) as $name) {
193  $names[] = $name;
194  }
195 
196  sort($names);
197  return $names;
198  }
199 }
200 
__get($name)
Fetch a value.
Definition: DiContainer.php:44
if($guid==elgg_get_logged_in_user_guid()) $name
Definition: delete.php:21
getNames()
Get names for all values/factories.
$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:91
setFactory($name, $callable, $shared=true)
Set a factory to generate a value when the container is read.