/** * Checks if the given method is "magic". If so it adds automatically parameter-types (if not * already set). * * @param string $classname the class-name * @param PC_Obj_Method $method the method * @return bool true if handled */ private function handle_magic($classname, $method) { // the magic-methods: // public void __set ( string $name , mixed $value ) // public mixed __get ( string $name ) // public bool __isset ( string $name ) // public void __unset ( string $name ) // public mixed __call ( string $name , array $arguments ) // public mixed __callStatic ( string $name , array $arguments ) // * array __sleep( void ) // * void__wakeup( void ) // public string __toString( void ) // public void __invoke( ... ) // public static object __set_state( array $props ) // * void __clone( void ) $ismagic = true; $visibility = PC_Obj_Visible::V_PUBLIC; $static = false; $expected = null; switch (strtolower($method->get_name())) { case '__set': $expected = array(new PC_Obj_Parameter('name', PC_Obj_MultiType::create_string()), new PC_Obj_Parameter('value', new PC_Obj_MultiType())); break; case '__isset': case '__unset': case '__get': $expected = array(new PC_Obj_Parameter('name', PC_Obj_MultiType::create_string())); break; case '__call': case '__callstatic': $expected = array(new PC_Obj_Parameter('name', PC_Obj_MultiType::create_string()), new PC_Obj_Parameter('arguments', PC_Obj_MultiType::create_array())); break; case '__tostring': $expected = array(); break; case '__sleep': case '__wakeup': case '__clone': $visibility = null; // may be private or protected $expected = array(); break; case '__invoke': $static = true; break; case '__set_state': $expected = array(new PC_Obj_Parameter('props', PC_Obj_MultiType::create_array())); break; default: $ismagic = false; break; } if (!$ismagic) { return false; } if ($visibility !== null && $method->get_visibility() != $visibility) { $this->report($method, 'The magic method "#' . $classname . '#::' . $method->get_name() . '" should be public', PC_Obj_Error::E_T_MAGIC_NOT_PUBLIC); } if ($static && !$method->is_static()) { $this->report($method, 'The magic method "#' . $classname . '#::' . $method->get_name() . '" should be static', PC_Obj_Error::E_T_MAGIC_NOT_STATIC); } else { if (!$static && $method->is_static()) { $this->report($method, 'The magic method "#' . $classname . '#::' . $method->get_name() . '" should not be static', PC_Obj_Error::E_T_MAGIC_IS_STATIC); } } if ($expected !== null) { $changed = false; if ($this->check_params($classname, $method, $expected, $method->get_params())) { // set parameter-descriptions $i = 0; foreach ($method->get_params() as $param) { $param->set_mtype($expected[$i++]->get_mtype()); $param->set_has_doc(true); $changed = true; } } $return = new PC_Obj_MultiType(); switch (strtolower($method->get_name())) { case '__set': case '__unset': case '__wakeup': case '__clone': $return = PC_Obj_MultiType::create_void(); break; case '__set_state': $return = PC_Obj_MultiType::create_object(); break; case '__isset': $return = PC_Obj_MultiType::create_bool(); break; case '__sleep': $return = PC_Obj_MultiType::create_array(); break; case '__tostring': $return = PC_Obj_MultiType::create_string(); break; } if ($method->has_return_doc() && !$this->env->get_types()->is_type_conforming($method->get_return_type(), $return)) { // its ok to specify a more specific return-value if the expected one is "mixed" if (!$return->is_unknown()) { $this->report($method, 'The return-type of the magic-method "#' . $classname . '#::' . $method->get_name() . '" is invalid ' . '(expected="' . $return . '", found="' . $method->get_return_type() . '")', PC_Obj_Error::E_T_MAGIC_METHOD_RET_INVALID); } } if ($return !== null && !$method->has_return_doc()) { $method->set_return_type($return); $method->set_has_return_doc(true); $changed = true; } if ($changed) { $this->env->get_storage()->update_function($method, $method->get_class()); } } return true; }
/** * Builds the fields to insert / update in the db * * @param PC_Obj_Method $function the function/method * @param int $class the id of the class the function belongs to * @param int $pid the project-id (default = current) * @return array all fields */ private function get_fields($function, $class, $pid = PC_Project::CURRENT_ID) { $params = serialize($function->get_params()); return array('project_id' => PC_UTils::get_project_id($pid), 'file' => $function->get_file(), 'line' => $function->get_line(), 'class' => $class, 'name' => $function->get_name(), 'abstract' => $function->is_abstract() ? 1 : 0, 'final' => $function->is_final() ? 1 : 0, 'static' => $function->is_static() ? 1 : 0, 'anonymous' => $function->is_anonymous() ? 1 : 0, 'visibility' => $function->get_visibility(), 'return_type' => serialize(array($function->has_return_doc(), $function->get_return_type())), 'throws' => serialize($function->get_throws()), 'params' => $params, 'min_version' => serialize($function->get_version()->get_min()), 'max_version' => serialize($function->get_version()->get_max())); }