/** * Build the object instance following current factory settings * * Errors are thrown by default but can be "gracefully" skipped using the flag `GRACEFULLY_FAILURE`. * In all cases, error messages are loaded in final parameter `$logs` passed by reference. * * @param string $name * @param array $parameters * @param int $flag One of the class constants flags * @param array $logs Passed by reference * @return object * @throws \RuntimeException if the class is not found * @throws \RuntimeException if the class doesn't implement or extend some required dependencies * @throws \RuntimeException if the class method for construction is not callable */ public function build($name, array $parameters = null, $flag = self::ERROR_ON_FAILURE, array &$logs = array()) { $this->flag($flag); $object = null; $builder_class_name = $this->findBuilder($name, $flag, $logs); if (!empty($builder_class_name)) { $reflection_obj = new ReflectionClass($builder_class_name); $is_static = $reflection_obj->hasMethod($this->call_method) && $reflection_obj->getMethod($this->call_method)->isStatic(); if (!$is_static || $this->call_method === '__construct') { if ($reflection_obj->hasMethod('__construct') && $reflection_obj->getConstructor()->isPublic()) { if ($this->call_method === '__construct') { $organized_parameters = CodeHelper::organizeArguments('__construct', $parameters, $builder_class_name); $_caller = call_user_func_array(array($reflection_obj, 'newInstance'), $organized_parameters); } else { $_caller = call_user_func(array($reflection_obj, 'newInstance')); } } else { try { if ($this->call_method === '__construct') { $_caller = new $builder_class_name($parameters); } else { $_caller = new $builder_class_name(); } } catch (\Exception $e) { $logs[] = $this->_getErrorMessage('Constructor method for class "%s" is not callable!', $builder_class_name); if ($flag & self::ERROR_ON_FAILURE) { throw new \RuntimeException(end($logs)); } } } } if (isset($_caller) && $this->call_method === '__construct') { $object = $_caller; } else { if ($reflection_obj->hasMethod($this->call_method) && $reflection_obj->getMethod($this->call_method)->isPublic()) { if ($reflection_obj->getMethod($this->call_method)->isStatic()) { $organized_parameters = CodeHelper::organizeArguments($this->call_method, $parameters, $builder_class_name); $object = call_user_func_array(array($builder_class_name, $this->call_method), $organized_parameters); } elseif (isset($_caller)) { $organized_parameters = CodeHelper::organizeArguments($this->call_method, $parameters, $_caller); $object = call_user_func_array(array($_caller, $this->call_method), $organized_parameters); } else { $logs[] = $this->_getErrorMessage('Error while trying to create "%s->%s" by factory builder!', $builder_class_name, $this->call_method); if ($flag & self::ERROR_ON_FAILURE) { throw new \RuntimeException(end($logs)); } } } else { $logs[] = $this->_getErrorMessage('Method "%s" for factory building of class "%s" is not callable!', $this->call_method, $builder_class_name); if ($flag & self::ERROR_ON_FAILURE) { throw new \RuntimeException(end($logs)); } } } } else { $logs[] = $this->_getErrorMessage('No matching class found for factory build "%s"!', $name); if ($flag & self::ERROR_ON_FAILURE) { throw new \RuntimeException(end($logs)); } } return $object; }