/** * __call() implementation. * @param object * @param string * @param array * @return mixed * @throws MemberAccessException */ public static function call($_this, $name, $args) { $class = get_class($_this); $isProp = self::hasProperty($class, $name); if ($name === '') { throw new MemberAccessException("Call to class '$class' method without name."); } elseif ($isProp === 'event') { // calling event handlers if (is_array($_this->$name) || $_this->$name instanceof Traversable) { foreach ($_this->$name as $handler) { NCallback::create($handler)->invokeArgs($args); } } elseif ($_this->$name !== NULL) { throw new UnexpectedValueException("Property $class::$$name must be array or NULL, " . gettype($_this->$name) ." given."); } } elseif ($cb = NClassReflection::from($_this)->getExtensionMethod($name)) { // extension methods array_unshift($args, $_this); return $cb->invokeArgs($args); } else { throw new MemberAccessException("Call to undefined method $class::$name()."); } }
/** * Sets a variable in this session section. * @param string name * @param mixed value * @return void */ public function __set($name, $value) { $this->start(); $this->data[$name] = $value; if (is_object($value)) { $this->meta[$name]['V'] = NClassReflection::from($value)->getAnnotation('serializationVersion'); } }
public function generateCode($className, $parentName) { foreach ($this->extensions as $extension) { $extension->beforeCompile(); $this->container->addDependency(NClassReflection::from($extension)->getFileName()); } $classes[] = $class = $this->container->generateClass($parentName); $class->setName($className) ->addMethod('initialize'); foreach ($this->extensions as $extension) { $extension->afterCompile($class); } $defs = $this->container->getDefinitions(); ksort($defs); $list = array_keys($defs); foreach (array_reverse($defs, TRUE) as $name => $def) { if ($def->class === 'NDINestedAccessor' && ($found = preg_grep('#^'.$name.'\.#i', $list))) { $list = array_diff($list, $found); $def->class = $className . '_' . preg_replace('#\W+#', '_', $name); $class->documents = preg_replace("#\\S+(?= \\$$name\\z)#", $def->class, $class->documents); $classes[] = $accessor = new NPhpClassType($def->class); foreach ($found as $item) { if ($defs[$item]->internal) { continue; } $short = substr($item, strlen($name) + 1); $accessor->addDocument($defs[$item]->shared ? "@property {$defs[$item]->class} \$$short" : "@method {$defs[$item]->class} create" . ucfirst("$short()")); } } } return implode("\n\n\n", $classes); }
/** * Returns array of persistent components. * This default implementation detects components by class-level annotation @persistent(cmp1, cmp2). * @return array */ public static function getPersistentComponents() { return (array) NClassReflection::from(func_get_arg(0)) ->getAnnotation('persistent'); }
/** * Creates new instance using autowiring. * @param string class * @param array arguments * @return object * @throws InvalidArgumentException */ public function createInstance($class, array $args = array()) { $rc = NClassReflection::from($class); if (!$rc->isInstantiable()) { throw new InvalidArgumentException("Class $class is not instantiable."); } elseif ($constructor = $rc->getConstructor()) { return $rc->newInstanceArgs(NDIHelpers::autowireArguments($constructor, $args, $this)); } elseif ($args) { throw new InvalidArgumentException("Unable to pass arguments, class $class has no constructor."); } return new $class; }
private function getContainerProperty($name) { $prop = NClassReflection::from('NDIContainer')->getProperty($name); $prop->setAccessible(TRUE); return $prop->getValue($this->container); }
/** * Returns annotations. * @param ReflectionClass|ReflectionMethod|ReflectionProperty * @return array */ public static function getAll(Reflector $r) { if ($r instanceof ReflectionClass) { $type = $r->getName(); $member = ''; } elseif ($r instanceof ReflectionMethod) { $type = $r->getDeclaringClass()->getName(); $member = $r->getName(); } else { $type = $r->getDeclaringClass()->getName(); $member = '$' . $r->getName(); } if (!self::$useReflection) { // auto-expire cache $file = $r instanceof ReflectionClass ? $r->getFileName() : $r->getDeclaringClass()->getFileName(); // will be used later if ($file && isset(self::$timestamps[$file]) && self::$timestamps[$file] !== filemtime($file)) { unset(self::$cache[$type]); } unset(self::$timestamps[$file]); } if (isset(self::$cache[$type][$member])) { // is value cached? return self::$cache[$type][$member]; } if (self::$useReflection === NULL) { // detects whether is reflection available self::$useReflection = (bool) NClassReflection::from(__CLASS__)->getDocComment(); } if (self::$useReflection) { $annotations = self::parseComment($r->getDocComment()); } else { if (!self::$cacheStorage) { // trigger_error('Set a cache storage for annotations parser via NAnnotationParser::setCacheStorage().', E_USER_WARNING); self::$cacheStorage = new NDevNullStorage; } $outerCache = new NCache(self::$cacheStorage, 'Nette.Reflection.Annotations'); if (self::$cache === NULL) { self::$cache = (array) $outerCache->offsetGet('list'); self::$timestamps = isset(self::$cache['*']) ? self::$cache['*'] : array(); } if (!isset(self::$cache[$type]) && $file) { self::$cache['*'][$file] = filemtime($file); self::parseScript($file); $outerCache->save('list', self::$cache); } if (isset(self::$cache[$type][$member])) { $annotations = self::$cache[$type][$member]; } else { $annotations = array(); } } if ($r instanceof ReflectionMethod && !$r->isPrivate() && (!$r->isConstructor() || !empty($annotations['inheritdoc'][0]))) { try { $inherited = self::getAll(new ReflectionMethod(get_parent_class($type), $member)); } catch (ReflectionException $e) { try { $inherited = self::getAll($r->getPrototype()); } catch (ReflectionException $e) { $inherited = array(); } } $annotations += array_intersect_key($inherited, array_flip(self::$inherited)); } return self::$cache[$type][$member] = $annotations; }
/** * Checks object @serializationVersion label. * @param string * @param mixed * @return bool */ private static function checkSerializationVersion($class, $value) { return NClassReflection::from($class)->getAnnotation('serializationVersion') === $value; }
/** * Starts and initializes session data. * @throws InvalidStateException * @return void */ public function start() { if (self::$started) { return; } $this->configure($this->options); NDebugger::tryError(); session_start(); if (NDebugger::catchError($e)) { @session_write_close(); // this is needed throw new InvalidStateException('session_start(): ' . $e->getMessage(), 0, $e); } self::$started = TRUE; /* structure: __NF: Counter, BrowserKey, Data, Meta, Time DATA: section->variable = data META: section->variable = Timestamp, Browser, Version */ unset($_SESSION['__NT'], $_SESSION['__NS'], $_SESSION['__NM']); // old unused structures // initialize structures $nf = & $_SESSION['__NF']; if (empty($nf)) { // new session $nf = array('C' => 0); } else { $nf['C']++; } // session regenerate every 30 minutes $nfTime = & $nf['Time']; $time = time(); if ($time - $nfTime > self::REGENERATE_INTERVAL) { $nfTime = $time; $this->regenerationNeeded = TRUE; } // browser closing detection $browserKey = $this->request->getCookie('nette-browser'); if (!$browserKey) { $browserKey = NStrings::random(); } $browserClosed = !isset($nf['B']) || $nf['B'] !== $browserKey; $nf['B'] = $browserKey; // resend cookie $this->sendCookie(); // process meta metadata if (isset($nf['META'])) { $now = time(); // expire section variables foreach ($nf['META'] as $section => $metadata) { if (is_array($metadata)) { foreach ($metadata as $variable => $value) { if ((!empty($value['B']) && $browserClosed) || (!empty($value['T']) && $now > $value['T']) // whenBrowserIsClosed || Time || ($variable !== '' && is_object($nf['DATA'][$section][$variable]) && (isset($value['V']) ? $value['V'] : NULL) // Version !== NClassReflection::from($nf['DATA'][$section][$variable])->getAnnotation('serializationVersion')) ) { if ($variable === '') { // expire whole section unset($nf['META'][$section], $nf['DATA'][$section]); continue 2; } unset($nf['META'][$section][$variable], $nf['DATA'][$section][$variable]); } } } } } if ($this->regenerationNeeded) { session_regenerate_id(TRUE); $this->regenerationNeeded = FALSE; } register_shutdown_function(array($this, 'clean')); }
/** * Starts and initializes session data. * @throws InvalidStateException * @return void */ public function start() { if (self::$started) { return; } $this->configure($this->options); $id = & $_COOKIE[session_name()]; if (!is_string($id) || !preg_match('#^[0-9a-zA-Z,-]{22,128}\z#i', $id)) { unset($_COOKIE[session_name()]); } set_error_handler(create_function('$severity, $message', 'extract($GLOBALS[0]['.array_push($GLOBALS[0], array('error'=>& $error)).'-1], EXTR_REFS); // session_start returns FALSE on failure since PHP 5.3.0. if (($severity & error_reporting()) === $severity) { $error = $message; restore_error_handler(); } ')); session_start(); if (!$error) { restore_error_handler(); } $this->response->removeDuplicateCookies(); if ($error && !session_id()) { @session_write_close(); // this is needed throw new InvalidStateException("session_start(): $error"); } self::$started = TRUE; /* structure: __NF: Counter, BrowserKey, Data, Meta, Time DATA: section->variable = data META: section->variable = Timestamp, Browser, Version */ unset($_SESSION['__NT'], $_SESSION['__NS'], $_SESSION['__NM']); // old unused structures // initialize structures $nf = & $_SESSION['__NF']; @$nf['C']++; // regenerate empty session if (empty($nf['Time'])) { $nf['Time'] = time(); $this->regenerated = TRUE; } // browser closing detection $browserKey = $this->request->getCookie('nette-browser'); if (!$browserKey) { $browserKey = NStrings::random(); } $browserClosed = !isset($nf['B']) || $nf['B'] !== $browserKey; $nf['B'] = $browserKey; // resend cookie $this->sendCookie(); // process meta metadata if (isset($nf['META'])) { $now = time(); // expire section variables foreach ($nf['META'] as $section => $metadata) { if (is_array($metadata)) { foreach ($metadata as $variable => $value) { if ((!empty($value['B']) && $browserClosed) || (!empty($value['T']) && $now > $value['T']) // whenBrowserIsClosed || Time || (isset($nf['DATA'][$section][$variable]) && is_object($nf['DATA'][$section][$variable]) && (isset($value['V']) ? $value['V'] : NULL) // Version != NClassReflection::from($nf['DATA'][$section][$variable])->getAnnotation('serializationVersion')) // intentionally != ) { if ($variable === '') { // expire whole section unset($nf['META'][$section], $nf['DATA'][$section]); continue 2; } unset($nf['META'][$section][$variable], $nf['DATA'][$section][$variable]); } } } } } if ($this->regenerated) { $this->regenerated = FALSE; $this->regenerateId(); } register_shutdown_function(array($this, 'clean')); }
/** * Formats PHP code for class instantiating, function calling or property setting in PHP. * @return string * @internal */ public function formatStatement(NDIStatement $statement, $self = NULL) { $entity = $this->normalizeEntity($statement->entity); $arguments = (array) $statement->arguments; if (is_string($entity) && NStrings::contains($entity, '?')) { // PHP literal return $this->formatPhp($entity, $arguments, $self); } elseif ($service = $this->getServiceName($entity)) { // factory calling or service retrieving if ($this->definitions[$service]->shared) { if ($arguments) { throw new NServiceCreationException("Unable to call service '$entity'."); } return $this->formatPhp('$this->?', array($this->sanitizeName($service))); } $params = array(); foreach ($this->definitions[$service]->parameters as $k => $v) { $params[] = preg_replace('#\w+$#', '\$$0', (is_int($k) ? $v : $k)) . (is_int($k) ? '' : ' = ' . NPhpHelpers::dump($v)); } $rm = new ReflectionFunction(create_function(implode(', ', $params), '')); $arguments = NDIHelpers::autowireArguments($rm, $arguments, $this); return $this->formatPhp('$this->?(?*)', array('create' . ucfirst($service), $arguments), $self); } elseif ($entity === 'not') { // operator return $this->formatPhp('!?', array($arguments[0])); } elseif (is_string($entity)) { // class name if ($constructor = NClassReflection::from($entity)->getConstructor()) { $this->addDependency($constructor->getFileName()); $arguments = NDIHelpers::autowireArguments($constructor, $arguments, $this); } elseif ($arguments) { throw new NServiceCreationException("Unable to pass arguments, class $entity has no constructor."); } return $this->formatPhp("new $entity" . ($arguments ? '(?*)' : ''), array($arguments)); } elseif (!NValidators::isList($entity) || count($entity) !== 2) { throw new InvalidStateException("Expected class, method or property, " . NPhpHelpers::dump($entity) . " given."); } elseif ($entity[0] === '') { // globalFunc return $this->formatPhp("$entity[1](?*)", array($arguments), $self); } elseif (NStrings::contains($entity[1], '$')) { // property setter if ($this->getServiceName($entity[0], $self)) { return $this->formatPhp('?->? = ?', array($entity[0], substr($entity[1], 1), $statement->arguments), $self); } else { return $this->formatPhp($entity[0] . '::$? = ?', array(substr($entity[1], 1), $statement->arguments), $self); } } elseif ($service = $this->getServiceName($entity[0], $self)) { // service method if ($this->definitions[$service]->class) { $arguments = $this->autowireArguments($this->definitions[$service]->class, $entity[1], $arguments); } return $this->formatPhp('?->?(?*)', array($entity[0], $entity[1], $arguments), $self); } else { // static method $arguments = $this->autowireArguments($entity[0], $entity[1], $arguments); return $this->formatPhp("$entity[0]::$entity[1](?*)", array($arguments), $self); } }