Example #1
0
 /**
  * Call to undefined method.
  *
  * @param  string  method name
  * @param  array   arguments
  * @return mixed
  * @throws MemberAccessException
  */
 public static function call($_this, $name, $args)
 {
     $class = new ClassReflection($_this);
     if ($name === '') {
         throw new MemberAccessException("Call to class '{$class->name}' method without name.");
     }
     // event functionality
     if ($class->hasEventProperty($name)) {
         if (is_array($list = $_this->{$name}) || $list instanceof Traversable) {
             foreach ($list as $handler) {
                 fixCallback($handler);
                 if (!is_callable($handler)) {
                     $able = is_callable($handler, TRUE, $textual);
                     throw new InvalidStateException("Event handler '{$textual}' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
                 }
                 call_user_func_array($handler, $args);
             }
         }
         return NULL;
     }
     // extension methods
     if ($cb = $class->getExtensionMethod($name)) {
         array_unshift($args, $_this);
         return call_user_func_array($cb, $args);
     }
     throw new MemberAccessException("Call to undefined method {$class->name}::{$name}().");
 }
Example #2
0
 /**
  * Appends input string filter callback.
  * @param  callback
  * @return TextBase  provides a fluent interface
  */
 public function addFilter($filter)
 {
     fixCallback($filter);
     if (!is_callable($filter)) {
         $able = is_callable($filter, TRUE, $textual);
         throw new InvalidArgumentException("Filter '{$textual}' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
     }
     $this->filters[] = $filter;
     return $this;
 }
Example #3
0
 /**
  * Adds a method to class.
  * @param  string  method name
  * @param  mixed   callback or closure
  * @return ClassReflection  provides a fluent interface
  */
 public function setExtensionMethod($name, $callback)
 {
     $l =& self::$extMethods[strtolower($name)];
     fixCallback($callback);
     if (!is_callable($callback)) {
         $able = is_callable($callback, TRUE, $textual);
         throw new InvalidArgumentException("Extension method handler '{$textual}' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
     }
     $l[strtolower($this->getName())] = $callback;
     $l[''] = NULL;
     return $this;
 }
 /**
  * Try to load the requested helper.
  * @param  string  helper name
  * @return callback
  */
 public static function loader($helper)
 {
     $callback = 'Nette\\Templates\\TemplateHelpers::' . $helper;
     fixCallback($callback);
     if (is_callable($callback)) {
         return $callback;
     }
     $callback = 'Nette\\String::' . $helper;
     fixCallback($callback);
     if (is_callable($callback)) {
         return $callback;
     }
 }
Example #5
0
 /**
  * Add custom descriptions.
  * @param  callback
  * @return void
  */
 public static function addColophon($callback)
 {
     fixCallback($callback);
     if (!is_callable($callback)) {
         $able = is_callable($callback, TRUE, $textual);
         throw new InvalidArgumentException("Colophon handler '{$textual}' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
     }
     if (!in_array($callback, self::$colophons, TRUE)) {
         self::$colophons[] = $callback;
     }
 }
Example #6
0
 /**
  * Registers callback as template run-time helpers loader.
  * @param  callback
  * @return void
  */
 public function registerHelperLoader($callback)
 {
     /**/
     fixCallback($callback);
     /**/
     if (!is_callable($callback)) {
         $able = is_callable($callback, TRUE, $textual);
         throw new InvalidArgumentException("Helper loader '{$textual}' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
     }
     $this->helperLoaders[] = $callback;
 }
 /**
  * Callback for self::macro().
  */
 private function cbMacro($m)
 {
     list($var, $modifiers) = $this->_cbMacro;
     if ($m[1]) {
         $callback = $m[1][0] === ':' ? array($this, substr($m[1], 1)) : $m[1];
         fixCallback($callback);
         if (!is_callable($callback)) {
             $able = is_callable($callback, TRUE, $textual);
             throw new InvalidStateException("CurlyBrackets macro handler '{$textual}' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
         }
         return call_user_func($callback, $var, $modifiers);
     } else {
         return $var;
     }
 }
Example #8
0
 /**
  * Starts and initializes session data.
  * @throws \InvalidStateException
  * @return void
  */
 public function start()
 {
     if (self::$started) {
         throw new InvalidStateException('Session has already been started.');
     } elseif (self::$started === NULL && defined('SID')) {
         throw new InvalidStateException('A session had already been started by session.auto-start or session_start().');
     }
     // additional protection against Session Hijacking & Fixation
     if ($this->verificationKeyGenerator) {
         /**/
         fixCallback($this->verificationKeyGenerator);
         /**/
         if (!is_callable($this->verificationKeyGenerator)) {
             $able = is_callable($this->verificationKeyGenerator, TRUE, $textual);
             throw new InvalidStateException("Verification key generator '{$textual}' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
         }
     }
     // start session
     $this->configure(self::$defaultConfig, FALSE);
     /*Nette\*/
     Tools::tryError();
     session_start();
     if (Tools::catchError($msg)) {
         @session_write_close();
         // this is needed
         throw new InvalidStateException($msg);
     }
     self::$started = TRUE;
     if ($this->regenerationNeeded) {
         session_regenerate_id(TRUE);
         $this->regenerationNeeded = FALSE;
     }
     /* structure:
     			nette: __NT
     			data:  __NS->namespace->variable = data
     			meta:  __NM->namespace->EXP->variable = timestamp
     		*/
     // initialize structures
     $verKey = $this->verificationKeyGenerator ? (string) call_user_func($this->verificationKeyGenerator) : '';
     if (!isset($_SESSION['__NT']['V'])) {
         // new session
         $_SESSION['__NT'] = array();
         $_SESSION['__NT']['C'] = 0;
         $_SESSION['__NT']['V'] = $verKey;
     } else {
         $saved =& $_SESSION['__NT']['V'];
         if ($saved === $verKey) {
             // verified
             $_SESSION['__NT']['C']++;
         } else {
             // session attack?
             session_regenerate_id(TRUE);
             $_SESSION = array();
             $_SESSION['__NT']['C'] = 0;
             $_SESSION['__NT']['V'] = $verKey;
         }
     }
     // browser closing detection
     $browserKey = $this->getHttpRequest()->getCookie('nette-browser');
     if (!$browserKey) {
         $browserKey = (string) lcg_value();
     }
     $browserClosed = !isset($_SESSION['__NT']['B']) || $_SESSION['__NT']['B'] !== $browserKey;
     $_SESSION['__NT']['B'] = $browserKey;
     // resend cookie
     $this->sendCookie();
     // process meta metadata
     if (isset($_SESSION['__NM'])) {
         $now = time();
         // expire namespace variables
         foreach ($_SESSION['__NM'] as $namespace => $metadata) {
             if (isset($metadata['EXP'])) {
                 foreach ($metadata['EXP'] as $variable => $value) {
                     if (!is_array($value)) {
                         $value = array($value, !$value);
                     }
                     // back compatibility
                     list($time, $whenBrowserIsClosed) = $value;
                     if ($whenBrowserIsClosed && $browserClosed || $time && $now > $time) {
                         if ($variable === '') {
                             // expire whole namespace
                             unset($_SESSION['__NM'][$namespace], $_SESSION['__NS'][$namespace]);
                             continue 2;
                         }
                         unset($_SESSION['__NS'][$namespace][$variable], $_SESSION['__NM'][$namespace]['EXP'][$variable]);
                     }
                 }
             }
         }
     }
     register_shutdown_function(array($this, 'clean'));
 }
Example #9
0
 /**
  * Gets the service object of the specified type.
  * @param  string service name
  * @param  array  options in case service is not singleton
  * @return mixed
  */
 public function getService($name, array $options = NULL)
 {
     if (!is_string($name) || $name === '') {
         throw new InvalidArgumentException("Service name must be a non-empty string, " . gettype($name) . " given.");
     }
     $lower = strtolower($name);
     if (isset($this->registry[$lower])) {
         // instantiated singleton
         if ($options) {
             throw new InvalidArgumentException("Service named '{$name}' is singleton and therefore can not have options.");
         }
         return $this->registry[$lower];
     } elseif (isset($this->factories[$lower])) {
         list($factory, $singleton, $defOptions) = $this->factories[$lower];
         if ($singleton && $options) {
             throw new InvalidArgumentException("Service named '{$name}' is singleton and therefore can not have options.");
         } elseif ($defOptions) {
             $options = $options ? $options + $defOptions : $defOptions;
         }
         if (is_string($factory) && strpos($factory, ':') === FALSE) {
             // class name
             /**/
             fixNamespace($factory);
             /**/
             if (!class_exists($factory)) {
                 throw new AmbiguousServiceException("Cannot instantiate service '{$name}', class '{$factory}' not found.");
             }
             $service = new $factory();
             if ($options && method_exists($service, 'setOptions')) {
                 $service->setOptions($options);
                 // TODO: better!
             }
         } else {
             // factory callback
             /**/
             fixCallback($factory);
             /**/
             if (!is_callable($factory)) {
                 $able = is_callable($factory, TRUE, $textual);
                 throw new AmbiguousServiceException("Cannot instantiate service '{$name}', handler '{$textual}' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
             }
             $service = call_user_func($factory, $options);
             if (!is_object($service)) {
                 $able = is_callable($factory, TRUE, $textual);
                 throw new AmbiguousServiceException("Cannot instantiate service '{$name}', value returned by '{$textual}' is not object.");
             }
         }
         if ($singleton) {
             $this->registry[$lower] = $service;
             unset($this->factories[$lower]);
         }
         return $service;
     }
     if ($this->parent !== NULL) {
         return $this->parent->getService($name, $options);
     } else {
         throw new InvalidStateException("Service '{$name}' not found.");
     }
 }
Example #10
0
 private function getCallback($rule)
 {
     $op = $rule->operation;
     if (is_string($op) && strncmp($op, ':', 1) === 0) {
         return array(get_class($rule->control), self::VALIDATE_PREFIX . ltrim($op, ':'));
     } else {
         fixCallback($op);
         return $op;
     }
 }
Example #11
0
 /**
  * Adding method to class.
  *
  * @param  string  class name
  * @param  string  method name
  * @param  mixed   callback or closure
  * @return mixed
  */
 public static function extensionMethod($class, $name, $callback = NULL)
 {
     /**/
     if (self::$extMethods === NULL || $name === NULL) {
         // for backwards compatibility
         $list = get_defined_functions();
         foreach ($list['user'] as $fce) {
             $pair = explode('_prototype_', $fce);
             if (count($pair) === 2) {
                 self::$extMethods[$pair[1]][$pair[0]] = $fce;
                 self::$extMethods[$pair[1]][''] = NULL;
             }
         }
         if ($name === NULL) {
             return NULL;
         }
     }
     /**/
     $class = strtolower($class);
     $l =& self::$extMethods[strtolower($name)];
     if ($callback !== NULL) {
         // works as setter
         /**/
         fixCallback($callback);
         /**/
         if (!is_callable($callback)) {
             $able = is_callable($callback, TRUE, $textual);
             throw new InvalidArgumentException("Extension method handler '{$textual}' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
         }
         $l[$class] = $callback;
         $l[''] = NULL;
         return NULL;
     }
     // works as getter
     if (empty($l)) {
         return FALSE;
     } elseif (isset($l[''][$class])) {
         // cached value
         return $l[''][$class];
     }
     $cl = $class;
     do {
         $cl = strtolower($cl);
         if (isset($l[$cl])) {
             return $l[''][$class] = $l[$cl];
         }
     } while (($cl = get_parent_class($cl)) !== FALSE);
     foreach (class_implements($class) as $cl) {
         $cl = strtolower($cl);
         if (isset($l[$cl])) {
             return $l[''][$class] = $l[$cl];
         }
     }
     return $l[''][$class] = FALSE;
 }
Example #12
0
 /**
  * Gets the service object of the specified type.
  * @param  string service name
  * @param  bool   throw exception if service doesn't exist?
  * @return mixed
  */
 public function getService($name, $need = TRUE)
 {
     if (!is_string($name) || $name === '') {
         throw new InvalidArgumentException("Service name must be a non-empty string, " . gettype($name) . " given.");
     }
     $lower = strtolower($name);
     if (isset($this->registry[$lower])) {
         return $this->registry[$lower];
     } elseif (isset($this->factories[$lower])) {
         $service = $this->factories[$lower];
         if (is_string($service)) {
             if (substr($service, -2) === '()') {
                 // trick to pass callback as string
                 $service = substr($service, 0, -2);
             } else {
                 fixNamespace($service);
                 if (!class_exists($service)) {
                     throw new AmbiguousServiceException("Cannot instantiate service '{$name}', class '{$service}' not found.");
                 }
                 return $this->registry[$lower] = new $service();
             }
         }
         fixCallback($service);
         if (!is_callable($service)) {
             $able = is_callable($service, TRUE, $textual);
             throw new AmbiguousServiceException("Cannot instantiate service '{$name}', handler '{$textual}' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
         }
         return $this->registry[$lower] = call_user_func($service);
     }
     if ($this->parent !== NULL) {
         return $this->parent->getService($name, $need);
     } elseif ($need) {
         throw new InvalidStateException("Service '{$name}' not found.");
     } else {
         return NULL;
     }
 }
Example #13
0
 /**
  * Starts and initializes session data.
  * @throws InvalidStateException
  * @return void
  */
 public function start()
 {
     if (self::$started) {
         throw new InvalidStateException('Session has already been started.');
     } elseif (self::$started === NULL && defined('SID')) {
         throw new InvalidStateException('A session had already been started by session.auto-start or session_start().');
     }
     // additional protection against Session Hijacking & Fixation
     if ($this->verificationKeyGenerator) {
         fixCallback($this->verificationKeyGenerator);
         if (!is_callable($this->verificationKeyGenerator)) {
             $able = is_callable($this->verificationKeyGenerator, TRUE, $textual);
             throw new InvalidStateException("Verification key generator '{$textual}' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
         }
     }
     // start session
     try {
         $this->configure($this->options);
     } catch (NotSupportedException $e) {
         // ignore?
     }
     Tools::tryError();
     session_start();
     if (Tools::catchError($msg)) {
         @session_write_close();
         // this is needed
         throw new InvalidStateException($msg);
     }
     self::$started = TRUE;
     if ($this->regenerationNeeded) {
         session_regenerate_id(TRUE);
         $this->regenerationNeeded = FALSE;
     }
     /* structure:
     			__NF: VerificationKey, Counter, BrowserKey, Data, Meta
     				DATA: namespace->variable = data
     				META: namespace->variable = Timestamp, Browser, Version
     		*/
     // initialize structures
     $verKey = $this->verificationKeyGenerator ? (string) call_user_func($this->verificationKeyGenerator) : NULL;
     if (!isset($_SESSION['__NF']['V'])) {
         // new session
         $_SESSION['__NF'] = array();
         $_SESSION['__NF']['C'] = 0;
         $_SESSION['__NF']['V'] = $verKey;
     } else {
         $saved =& $_SESSION['__NF']['V'];
         if (!$this->verificationKeyGenerator || $verKey === $saved) {
             // ignored or verified
             $_SESSION['__NF']['C']++;
         } else {
             // session attack?
             session_regenerate_id(TRUE);
             $_SESSION = array();
             $_SESSION['__NF']['C'] = 0;
             $_SESSION['__NF']['V'] = $verKey;
         }
     }
     $nf =& $_SESSION['__NF'];
     unset($_SESSION['__NT'], $_SESSION['__NS'], $_SESSION['__NM']);
     // old structures
     // browser closing detection
     $browserKey = $this->getHttpRequest()->getCookie('nette-browser');
     if (!$browserKey) {
         $browserKey = (string) lcg_value();
     }
     $browserClosed = !isset($nf['B']) || $nf['B'] !== $browserKey;
     $nf['B'] = $browserKey;
     // resend cookie
     $this->sendCookie();
     // process meta metadata
     if (isset($nf['META'])) {
         $now = time();
         // expire namespace variables
         foreach ($nf['META'] as $namespace => $metadata) {
             if (is_array($metadata)) {
                 foreach ($metadata as $variable => $value) {
                     if (!empty($value['B']) && $browserClosed || !empty($value['T']) && $now > $value['T'] || $variable !== '' && is_object($nf['DATA'][$namespace][$variable]) && (isset($value['V']) ? $value['V'] : NULL) !== ClassReflection::from($nf['DATA'][$namespace][$variable])->getAnnotation('serializationVersion')) {
                         if ($variable === '') {
                             // expire whole namespace
                             unset($nf['META'][$namespace], $nf['DATA'][$namespace]);
                             continue 2;
                         }
                         unset($nf['META'][$namespace][$variable], $nf['DATA'][$namespace][$variable]);
                     }
                 }
             }
         }
     }
     register_shutdown_function(array($this, 'clean'));
 }
Example #14
0
 /**
  * Callback for self::macro().
  */
 private function cbMacro($m)
 {
     list($content, $modifiers) = $this->current;
     if ($m[1]) {
         $callback = $m[1][0] === ':' ? array($this, substr($m[1], 1)) : $m[1];
         /**/
         fixCallback($callback);
         /**/
         if (!is_callable($callback)) {
             $able = is_callable($callback, TRUE, $textual);
             throw new InvalidStateException("Latte macro handler '{$textual}' is not " . ($able ? 'callable.' : 'valid PHP callback.'));
         }
         return call_user_func($callback, $content, $modifiers);
     } else {
         return $content;
     }
 }