Elgg  Version 3.0
DiContainer.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Di;
4 
29 class DiContainer {
30 
34  private $factories_ = [];
35 
36  const CLASS_NAME_PATTERN_53 = '/^(\\\\?[a-z_\x7f-\xff][a-z0-9_\x7f-\xff]*)+$/i';
37 
45  public function __get($name) {
46  if (!isset($this->factories_[$name])) {
47  throw new \Elgg\Di\MissingValueException("Value or factory was not set for: $name");
48  }
49  $value = $this->build($this->factories_[$name]['callable'], $name);
50 
51  // Why check existence of factory here? A: the builder function may have set the value
52  // directly, in which case the factory will no longer exist.
53  if (!empty($this->factories_[$name]) && $this->factories_[$name]['shared']) {
54  $this->{$name} = $value;
55  }
56  return $value;
57  }
58 
67  private function build($factory, $name) {
68  if (is_callable($factory)) {
69  return call_user_func($factory, $this);
70  }
71  $msg = "Factory for '$name' was uncallable";
72  if (is_string($factory)) {
73  $msg .= ": '$factory'";
74  } elseif (is_array($factory)) {
75  if (is_string($factory[0])) {
76  $msg .= ": '{$factory[0]}::{$factory[1]}'";
77  } else {
78  $msg .= ": " . get_class($factory[0]) . "->{$factory[1]}";
79  }
80  }
81  throw new \Elgg\Di\FactoryUncallableException($msg);
82  }
83 
92  public function setValue($name, $value) {
93  if (substr($name, -1) === '_') {
94  throw new \InvalidArgumentException('$name cannot end with "_"');
95  }
96  $this->{$name} = $value;
97  return $this;
98  }
99 
106  public function reset($name) {
107  $this->{$name} = null;
108  unset($this->{$name});
109  }
110 
120  public function setFactory($name, $callable, $shared = true) {
121  if (substr($name, -1) === '_') {
122  throw new \InvalidArgumentException('$name cannot end with "_"');
123  }
124  if (!is_callable($callable, true)) {
125  throw new \InvalidArgumentException('$factory must appear callable');
126  }
127  $this->remove($name);
128  $this->factories_[$name] = [
129  'callable' => $callable,
130  'shared' => $shared,
131  ];
132  return $this;
133  }
134 
144  public function setClassName($name, $class_name, $shared = true) {
145  if (substr($name, -1) === '_') {
146  throw new \InvalidArgumentException('$name cannot end with "_"');
147  }
148  $classname_pattern = self::CLASS_NAME_PATTERN_53;
149  if (!is_string($class_name) || !preg_match($classname_pattern, $class_name)) {
150  throw new \InvalidArgumentException('Class names must be valid PHP class names');
151  }
152  $func = function () use ($class_name) {
153  return new $class_name();
154  };
155  return $this->setFactory($name, $func, $shared);
156  }
157 
164  public function remove($name) {
165  if (substr($name, -1) === '_') {
166  throw new \InvalidArgumentException('$name cannot end with "_"');
167  }
168  unset($this->{$name});
169  unset($this->factories_[$name]);
170  return $this;
171  }
172 
179  public function has($name) {
180  if (isset($this->factories_[$name])) {
181  return true;
182  }
183  if (substr($name, -1) === '_') {
184  return false;
185  }
186  return (bool) property_exists($this, $name);
187  }
188 
195  public function getNames() {
196  $names = [];
197 
198  $refl = new \ReflectionObject($this);
199  foreach ($refl->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
200  $names[] = $prop->name;
201  }
202  foreach (array_keys($this->factories_) as $name) {
203  $names[] = $name;
204  }
205 
206  sort($names);
207  return $names;
208  }
209 }
if(!$user||!$user->canDelete()) $name
Definition: delete.php:22
__get($name)
Fetch a value.
Definition: DiContainer.php:45
getNames()
Get names for all values/factories.
Container holding values which can be resolved upon reading and optionally stored and shared across r...
Definition: DiContainer.php:29
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:92
if($item instanceof\ElggEntity) elseif($item instanceof\ElggRiverItem) elseif(is_callable([$item, 'getType']))
Definition: item.php:39
$value
Definition: debugging.php:7
setFactory($name, $callable, $shared=true)
Set a factory to generate a value when the container is read.
reset($name)
Remove previously built service, so that it&#39;s rebuld from factory on next call.