public function __clone() { // TODO: Test this. Make sure cloning works properly. $newObject = clone $this->_hookObject; Hook::hookObject($newObject, get_class($newObject) . '->', false); return $newObject; }
/** * Hook an object. * * This hooks all (public) methods defined in the given object. * * @param object &$object The object to hook. * @param string $prefix The prefix used to call the object's methods. Usually something like "$object->". * @param bool $recursive Whether to hook objects recursively. * @return bool True on success, false on failure. */ public static function hookObject(&$object, $prefix = '', $recursive = true) { if ((object) $object === $object) { $isString = false; } else { $isString = true; } // Make sure we don't take over the hook object, or we'll end up // recursively calling ourself. Some system classes shouldn't be hooked. $className = str_replace('\\', '_', $isString ? $object : get_class($object)); global $_; if (isset($_) && in_array($className, array('\\SciActive\\Hook', 'depend', 'config', 'info'))) { return false; } if ($recursive && !$isString) { foreach ($object as $curName => &$curProperty) { if ((object) $curProperty === $curProperty) { Hook::hookObject($curProperty, $prefix . $curName . '->'); } } } if (!class_exists("\\SciActive\\HookOverride_{$className}")) { if ($isString) { $reflection = new \ReflectionClass($object); } else { $reflection = new \ReflectionObject($object); } $methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC); $code = ''; foreach ($methods as &$curMethod) { $fname = $curMethod->getName(); if (in_array($fname, array('__construct', '__destruct', '__get', '__set', '__isset', '__unset', '__toString', '__invoke', '__set_state', '__clone', '__sleep', 'jsonSerialize'))) { continue; } //$fprefix = $curMethod->isFinal() ? 'final ' : ''; $fprefix = $curMethod->isStatic() ? 'static ' : ''; $params = $curMethod->getParameters(); $paramArray = $paramNameArray = array(); foreach ($params as &$curParam) { $paramName = $curParam->getName(); $paramPrefix = $curParam->isPassedByReference() ? '&' : ''; if ($curParam->isDefaultValueAvailable()) { $paramSuffix = ' = ' . var_export($curParam->getDefaultValue(), true); } else { $paramSuffix = ''; } $paramArray[] = "{$paramPrefix}\${$paramName}{$paramSuffix}"; $paramNameArray[] = "{$paramPrefix}\${$paramName}"; } unset($curParam); $code .= $fprefix . "function {$fname}(" . implode(', ', $paramArray) . ") {\n" . (defined('HHVM_VERSION') ? " \$arguments = array();\n" . (count($paramNameArray) > 0 ? " \$arguments[] = " . implode('; $arguments[] = ', $paramNameArray) . ";\n" : '') . " \$real_arg_count = func_num_args();\n" . " \$arg_count = count(\$arguments);\n" . " if (\$real_arg_count > \$arg_count) {\n" . " for (\$i = \$arg_count; \$i < \$real_arg_count; \$i++)\n" . " \$arguments[] = func_get_arg(\$i);\n" . " }\n" : (version_compare(PHP_VERSION, '5.4.0') >= 0 ? " \$arguments = debug_backtrace(false, 1);\n" : " \$arguments = debug_backtrace(false);\n") . " \$arguments = \$arguments[0]['args'];\n") . " \$function = array(\$this->_hookObject, '{$fname}');\n" . " \$data = array();\n" . " \\SciActive\\Hook::runCallbacks(\$this->_hookPrefix.'{$fname}', \$arguments, 'before', \$this->_hookObject, \$function, \$data);\n" . " if (\$arguments !== false) {\n" . " \$return = call_user_func_array(\$function, \$arguments);\n" . " if ((object) \$return === \$return && get_class(\$return) === '{$className}')\n" . " \\SciActive\\Hook::hookObject(\$return, '{$prefix}', false);\n" . " \$return = array(\$return);\n" . " \\SciActive\\Hook::runCallbacks(\$this->_hookPrefix.'{$fname}', \$return, 'after', \$this->_hookObject, \$function, \$data);\n" . " if ((array) \$return === \$return)\n" . " return \$return[0];\n" . " }\n" . "}\n\n"; } unset($curMethod); // Build a HookOverride class. $include = str_replace(array('_NAMEHERE_', '//#CODEHERE#', '<?php', '?>'), array($className, $code, '', ''), Hook::$hookFile); eval($include); } eval('$object = new \\SciActive\\HookOverride_' . $className . ' ($object, $prefix);'); return true; }