- * Autoloader::alias_to_namespace('Foo\\Bar');
- * Autoloader::alias_to_namespace('Foo\\Bar', '\\Baz');
- *
- *
- * @param string $class the class name
- * @param string $namespace the namespace to alias to
- */
- public static function alias_to_namespace($class, $namespace = '')
- {
- empty($namespace) or $namespace = rtrim($namespace, '\\').'\\';
- $parts = explode('\\', $class);
- $root_class = $namespace.array_pop($parts);
- class_alias($class, $root_class);
- }
-
- /**
- * Register's the autoloader to the SPL autoload stack.
- *
- * @return void
- */
- public static function register()
- {
- spl_autoload_register('Autoloader::load', true, true);
- }
-
- /**
- * Returns the class with namespace prefix when available
- *
- * @param string $class
- * @return bool|string
- */
- protected static function find_core_class($class)
- {
- foreach (static::$core_namespaces as $ns)
- {
- if (array_key_exists(strtolower($ns_class = $ns.'\\'.$class), static::$classes))
- {
- return $ns_class;
- }
- }
-
- return false;
- }
-
- /**
- * Add a namespace for which classes may be used without the namespace prefix and
- * will be auto-aliased to the global namespace.
- * Prefixing the classes will overwrite core classes and previously added namespaces.
- *
- * @param string $namespace
- * @param bool $prefix
- * @return void
- */
- public static function add_core_namespace($namespace, $prefix = true)
- {
- if ($prefix)
- {
- array_unshift(static::$core_namespaces, $namespace);
- }
- else
- {
- static::$core_namespaces[] = $namespace;
- }
- }
-
- /**
- * Loads a class.
- *
- * @param string $class Class to load
- * @return bool If it loaded the class
- */
- public static function load($class)
- {
- // deal with funny is_callable('static::classname') side-effect
- if (strpos($class, 'static::') === 0)
- {
- // is called from within the class, so it's already loaded
- return true;
- }
-
- $loaded = false;
- $class = ltrim($class, '\\');
- $pos = strripos($class, '\\');
-
- if (empty(static::$auto_initialize))
- {
- static::$auto_initialize = $class;
- }
-
- if (isset(static::$classes[strtolower($class)]))
- {
- static::init_class($class, str_replace('/', DS, static::$classes[strtolower($class)]));
- $loaded = true;
- }
- elseif ($full_class = static::find_core_class($class))
- {
- if ( ! class_exists($full_class, false) and ! interface_exists($full_class, false))
- {
- include static::prep_path(static::$classes[strtolower($full_class)]);
- }
- if ( ! class_exists($class, false))
- {
- class_alias($full_class, $class);
- }
- static::init_class($class);
- $loaded = true;
- }
- else
- {
- $full_ns = substr($class, 0, $pos);
-
- if ($full_ns)
- {
- foreach (static::$namespaces as $ns => $path)
- {
- $ns = ltrim($ns, '\\');
- if (stripos($full_ns, $ns) === 0)
- {
- $path .= static::class_to_path(
- substr($class, strlen($ns) + 1),
- array_key_exists($ns, static::$psr_namespaces)
- );
- if (is_file($path))
- {
- static::init_class($class, $path);
- $loaded = true;
- break;
- }
- }
- }
- }
-
- if ( ! $loaded)
- {
- $path = APPPATH.'classes'.DS.static::class_to_path($class);
-
- if (is_file($path))
- {
- static::init_class($class, $path);
- $loaded = true;
- }
- }
- }
-
- // Prevent failed load from keeping other classes from initializing
- if (static::$auto_initialize == $class)
- {
- static::$auto_initialize = null;
- }
-
- return $loaded;
- }
-
- /**
- * Reset the auto initialize state after an autoloader exception.
- * This method is called by the exception handler, and is considered an
- * internal method!
- *
- * @access protected
- */
- public static function _reset()
- {
- static::$auto_initialize = null;
- }
-
- /**
- * Takes a class name and turns it into a path. It follows the PSR-0
- * standard, except for makes the entire path lower case, unless you
- * tell it otherwise.
- *
- * Note: This does not check if the file exists...just gets the path
- *
- * @param string $class Class name
- * @param bool $psr Whether this is a PSR-0 compliant class
- * @return string Path for the class
- */
- protected static function class_to_path($class, $psr = false)
- {
- $file = '';
- if ($last_ns_pos = strripos($class, '\\'))
- {
- $namespace = substr($class, 0, $last_ns_pos);
- $class = substr($class, $last_ns_pos + 1);
- $file = str_replace('\\', DS, $namespace).DS;
- }
- $file .= str_replace('_', DS, $class).'.php';
-
- if ( ! $psr)
- {
- $file = strtolower($file);
- }
-
- return $file;
- }
-
- /**
- * Prepares a given path by making sure the directory separators are correct.
- *
- * @param string $path Path to prepare
- * @return string Prepped path
- */
- protected static function prep_path($path)
- {
- return str_replace(array('/', '\\'), DS, $path);
- }
-
- /**
- * Checks to see if the given class has a static _init() method. If so then
- * it calls it.
- *
- * @param string $class the class name
- * @param string $file the file containing the class to include
- * @throws \Exception
- * @throws \FuelException
- */
- protected static function init_class($class, $file = null)
- {
- // include the file if needed
- if ($file)
- {
- include $file;
- }
-
- // if the loaded file contains a class...
- if (class_exists($class, false))
- {
- // call the classes static init if needed
- if (static::$auto_initialize === $class)
- {
- static::$auto_initialize = null;
- if (method_exists($class, '_init') and is_callable($class.'::_init'))
- {
- call_user_func($class.'::_init');
- }
- }
- }
-
- // or an interface...
- elseif (interface_exists($class, false))
- {
- // nothing to do here
- }
-
- // or a trait if you're not on 5.3 anymore...
- elseif (function_exists('trait_exists') and trait_exists($class, false))
- {
- // nothing to do here
- }
-
- // else something went wrong somewhere, barf and exit now
- elseif ($file)
- {
- throw new \Exception('File "'.\Fuel::clean_path($file).'" does not contain class "'.$class.'"');
- }
- else
- {
- throw new \FuelException('Class "'.$class.'" is not defined');
- }
- }
-}
diff --git a/fuel/core/classes/cache.php b/fuel/core/classes/cache.php
deleted file mode 100755
index 05dc079..0000000
--- a/fuel/core/classes/cache.php
+++ /dev/null
@@ -1,136 +0,0 @@
- $config);
- }
-
- // Overwrite default values with given config
- $config = array_merge($defaults, (array) $config);
-
- if (empty($config['driver']))
- {
- throw new \FuelException('No cache driver given or no default cache driver set.');
- }
-
- $class = '\\Cache_Storage_'.ucfirst($config['driver']);
-
- // Convert the name to a string when necessary
- $identifier = call_user_func($class.'::stringify_identifier', $identifier);
-
- // Return instance of the requested cache object
- return new $class($identifier, $config);
- }
-
- /**
- * Front for writing the cache, ensures interchangeability of storage drivers. Actual writing
- * is being done by the _set() method which needs to be extended.
- *
- * @param mixed $identifier The identifier of the cache, can be anything but empty
- * @param mixed $contents The content to be cached
- * @param bool $expiration The time in seconds until the cache will expire, =< 0 or null means no expiration
- * @param array $dependencies Contains the identifiers of caches this one will depend on (not supported by all drivers!)
- * @return Cache_Storage_Driver The new Cache object
- */
- public static function set($identifier, $contents = null, $expiration = false, $dependencies = array())
- {
- $contents = \Fuel::value($contents);
-
- $cache = static::forge($identifier);
- return $cache->set($contents, $expiration, $dependencies);
- }
-
- /**
- * Does get() & set() in one call that takes a callback and it's arguments to generate the contents
- *
- * @param mixed $identifier The identifier of the cache, can be anything but empty
- * @param string|array $callback Valid PHP callback
- * @param array $args Arguments for the above function/method
- * @param int $expiration Cache expiration in seconds
- * @param array $dependencies Contains the identifiers of caches this one will depend on (not supported by all drivers!)
- * @return mixed
- */
- public static function call($identifier, $callback, $args = array(), $expiration = null, $dependencies = array())
- {
- $cache = static::forge($identifier);
- return $cache->call($callback, $args, $expiration, $dependencies);
- }
-
- /**
- * Front for reading the cache, ensures interchangeability of storage drivers. Actual reading
- * is being done by the _get() method which needs to be extended.
- *
- * @param mixed $identifier The identifier of the cache, can be anything but empty
- * @param bool $use_expiration
- * @return mixed
- */
- public static function get($identifier, $use_expiration = true)
- {
- $cache = static::forge($identifier);
- return $cache->get($use_expiration);
- }
-
- /**
- * Frontend for deleting item from the cache, interchangeable storage methods. Actual operation
- * handled by delete() call on storage driver class
- *
- * @param mixed $identifier The identifier of the cache, can be anything but empty
- */
- public static function delete($identifier)
- {
- $cache = static::forge($identifier);
- return $cache->delete();
- }
-
- /**
- * Flushes the whole cache for a specific storage driver or just a part of it when $section is set
- * (might not work with all storage drivers), defaults to the default storage driver
- *
- * @param null|string
- * @param null|string
- * @return bool
- */
- public static function delete_all($section = null, $driver = null)
- {
- $cache = static::forge('__NOT_USED__', $driver);
- return $cache->delete_all($section);
- }
-}
diff --git a/fuel/core/classes/cache/handler/driver.php b/fuel/core/classes/cache/handler/driver.php
deleted file mode 100755
index 1c7f0f0..0000000
--- a/fuel/core/classes/cache/handler/driver.php
+++ /dev/null
@@ -1,31 +0,0 @@
-config = isset($config['apc']) ? $config['apc'] : array();
-
- // make sure we have an id
- $this->config['cache_id'] = $this->_validate_config('cache_id', isset($this->config['cache_id'])
- ? $this->config['cache_id'] : 'fuel');
-
- // check for an expiration override
- $this->expiration = $this->_validate_config('expiration', isset($this->config['expiration'])
- ? $this->config['expiration'] : $this->expiration);
-
- // do we have the PHP APC extension available
- if ( ! function_exists('apc_store') )
- {
- throw new \FuelException('Your PHP installation doesn\'t have APC loaded.');
- }
- }
-
- // ---------------------------------------------------------------------
-
- /**
- * Check if other caches or files have been changed since cache creation
- *
- * @param array
- * @return bool
- */
- public function check_dependencies(array $dependencies)
- {
- foreach($dependencies as $dep)
- {
- // get the section name and identifier
- $sections = explode('.', $dep);
- if (count($sections) > 1)
- {
- $identifier = array_pop($sections);
- $sections = '.'.implode('.', $sections);
-
- }
- else
- {
- $identifier = $dep;
- $sections = '';
- }
-
- // get the cache index
- $index = apc_fetch($this->config['cache_id'].$sections);
-
- // get the key from the index
- $key = isset($index[$identifier][0]) ? $index[$identifier] : false;
-
- // key found and newer?
- if ($key === false or $key[1] > $this->created)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Delete Cache
- */
- public function delete()
- {
- // get the APC key for the cache identifier
- $key = $this->_get_key(true);
-
- // delete the key from the apc store
- $key and apc_delete($key);
-
- $this->reset();
- }
-
- /**
- * Purge all caches
- *
- * @param string $section limit purge to subsection
- * @return bool
- */
- public function delete_all($section)
- {
- // determine the section index name
- $section = $this->config['cache_id'].(empty($section) ? '' : '.'.$section);
-
- // get the directory index
- $index = apc_fetch($this->config['cache_id'].'__DIR__');
-
- if (is_array($index))
- {
- // limit the delete if we have a valid section
- if ( ! empty($section))
- {
- $dirs = in_array($section, $index) ? array($section) : array();
- }
- else
- {
- $dirs = $index;
- }
-
- // loop through the indexes, delete all stored keys, then delete the indexes
- foreach ($dirs as $dir)
- {
- $list = apc_fetch($dir);
- foreach ($list as $item)
- {
- apc_delete($item[0]);
- }
- apc_delete($dir);
- }
-
- // update the directory index
- $index = array_diff($index, $dirs);
- apc_store($this->config['cache_id'].'__DIR__', $index);
- }
- }
-
- // ---------------------------------------------------------------------
-
- /**
- * Prepend the cache properties
- *
- * @return string
- */
- protected function prep_contents()
- {
- $properties = array(
- 'created' => $this->created,
- 'expiration' => $this->expiration,
- 'dependencies' => $this->dependencies,
- 'content_handler' => $this->content_handler,
- );
- $properties = '{{'.static::PROPS_TAG.'}}'.json_encode($properties).'{{/'.static::PROPS_TAG.'}}';
-
- return $properties.$this->contents;
- }
-
- /**
- * Remove the prepended cache properties and save them in class properties
- *
- * @param string
- * @throws UnexpectedValueException
- */
- protected function unprep_contents($payload)
- {
- $properties_end = strpos($payload, '{{/'.static::PROPS_TAG.'}}');
- if ($properties_end === FALSE)
- {
- throw new \UnexpectedValueException('Cache has bad formatting');
- }
-
- $this->contents = substr($payload, $properties_end + strlen('{{/'.static::PROPS_TAG.'}}'));
- $props = substr(substr($payload, 0, $properties_end), strlen('{{'.static::PROPS_TAG.'}}'));
- $props = json_decode($props, true);
- if ($props === NULL)
- {
- throw new \UnexpectedValueException('Cache properties retrieval failed');
- }
-
- $this->created = $props['created'];
- $this->expiration = is_null($props['expiration']) ? null : (int) ($props['expiration'] - time());
- $this->dependencies = $props['dependencies'];
- $this->content_handler = $props['content_handler'];
- }
-
- /**
- * Save a cache, this does the generic pre-processing
- *
- * @return bool success
- */
- protected function _set()
- {
- // get the apc key for the cache identifier
- $key = $this->_get_key();
-
- $payload = $this->prep_contents();
-
- // adjust the expiration, apc uses a TTL instead of a timestamp
- $expiration = is_null($this->expiration) ? 0 : (int) ($this->expiration - $this->created);
-
- // write it to the apc store
- if (apc_store($key, $payload, $expiration) === false)
- {
- throw new \RuntimeException('APC returned failed to write. Check your configuration.');
- }
-
- // update the index
- $this->_update_index($key);
-
- return true;
- }
-
- /**
- * Load a cache, this does the generic post-processing
- *
- * @return bool success
- */
- protected function _get()
- {
- // get the apc key for the cache identifier
- $key = $this->_get_key();
-
- // fetch the cached data from the apc store
- $payload = apc_fetch($key);
-
- try
- {
- $this->unprep_contents($payload);
- }
- catch (\UnexpectedValueException $e)
- {
- return false;
- }
-
- return true;
- }
-
- /**
- * validate a driver config value
- *
- * @param string name of the config variable to validate
- * @param mixed value
- * @return mixed
- */
- private function _validate_config($name, $value)
- {
- switch ($name)
- {
- case 'cache_id':
- if (empty($value) or ! is_string($value))
- {
- $value = 'fuel';
- }
- break;
-
- case 'expiration':
- if (empty($value) or ! is_numeric($value))
- {
- $value = null;
- }
- break;
-
- default:
- break;
- }
-
- return $value;
- }
-
- /**
- * get's the apc key belonging to the cache identifier
- *
- * @param bool if true, remove the key retrieved from the index
- * @return string
- */
- protected function _get_key($remove = false)
- {
- // get the current index information
- list($identifier, $sections, $index) = $this->_get_index();
-
- // get the key from the index
- $key = isset($index[$identifier][0]) ? $index[$identifier][0] : false;
-
- if ($remove === true)
- {
- if ( $key !== false )
- {
- unset($index[$identifier]);
- apc_store($this->config['cache_id'].$sections, $index);
- }
- }
- else
- {
- // create a new key if needed
- $key === false and $key = $this->_new_key();
- }
-
- return $key;
- }
-
- /**
- * generate a new unique key for the current identifier
- *
- * @return string
- */
- protected function _new_key()
- {
- $key = '';
- while (strlen($key) < 32)
- {
- $key .= mt_rand(0, mt_getrandmax());
- }
- return md5($this->config['cache_id'].'_'.uniqid($key, TRUE));
- }
-
- /**
- * Get the section index
- *
- * @return array containing the identifier, the sections, and the section index
- */
- protected function _get_index()
- {
- // get the section name and identifier
- $sections = explode('.', $this->identifier);
- if (count($sections) > 1)
- {
- $identifier = array_pop($sections);
- $sections = '.'.implode('.', $sections);
- }
- else
- {
- $identifier = $this->identifier;
- $sections = '';
- }
-
- // get the cache index and return it
- return array($identifier, $sections, apc_fetch($this->config['cache_id'].$sections));
- }
-
- /**
- * Update the section index
- *
- * @param string cache key
- */
- protected function _update_index($key)
- {
- // get the current index information
- list($identifier, $sections, $index) = $this->_get_index();
-
- // store the key in the index and write the index back
- $index[$identifier] = array($key, $this->created);
- apc_store($this->config['cache_id'].$sections, array_merge($index, array($identifier => array($key, $this->created))), 0);
-
- // get the directory index
- $index = apc_fetch($this->config['cache_id'].'__DIR__');
-
- if (is_array($index))
- {
- if (!in_array($this->config['cache_id'].$sections, $index))
- {
- $index[] = $this->config['cache_id'].$sections;
- }
- }
- else
- {
- $index = array($this->config['cache_id'].$sections);
- }
-
- // update the directory index
- apc_store($this->config['cache_id'].'__DIR__', $index, 0);
- }
-}
diff --git a/fuel/core/classes/cache/storage/driver.php b/fuel/core/classes/cache/storage/driver.php
deleted file mode 100755
index d4e6f2b..0000000
--- a/fuel/core/classes/cache/storage/driver.php
+++ /dev/null
@@ -1,426 +0,0 @@
-identifier = $identifier;
-
- // fetch options from config and set them
- $this->expiration = array_key_exists('expiration', $config) ? $config['expiration'] : \Config::get('cache.expiration', null);
- $this->dependencies = array_key_exists('dependencies', $config) ? $config['dependencies'] : array();
- $this->content_handler = array_key_exists('content_handler', $config) ? new $config['content_handler']() : null;
- $this->driver = array_key_exists('driver', $config) ? $config['driver'] : 'file';
- }
-
- /**
- * Allows for default getting and setting
- *
- * @param string
- * @param array
- * @return void|mixed
- */
- public function __call($method, $args = array())
- {
- // Allow getting any properties set in static::$_gettable
- if (substr($method, 0, 3) == 'get')
- {
- $name = substr($method, 4);
- if (in_array($name, static::$_gettable))
- {
- return $this->{$name};
- }
- else
- {
- throw new \BadMethodCallException('This property doesn\'t exist or can\'t be read.');
- }
- }
- // Allow setting any properties set in static::$_settable
- elseif (substr($method, 0, 3) == 'set')
- {
- $name = substr($method, 4);
- if (in_array($name, static::$_settable))
- {
- $this->{$name} = @$args[0];
- }
- else
- {
- throw new \BadMethodCallException('This property doesn\'t exist or can\'t be set.');
- }
- return $this;
- }
- else
- {
- throw new \BadMethodCallException('Illegal method call: ' . $method);
- }
- }
-
- /**
- * Converts the identifier to a string when necessary:
- * A int is just converted to a string, all others are serialized and then md5'd
- *
- * @param mixed $identifier
- * @return string
- * @throws \FuelException
- */
- public static function stringify_identifier($identifier)
- {
- // Identifier may not be empty, but can be false or 0
- if ($identifier === '' || $identifier === null)
- {
- throw new \FuelException('The identifier cannot be empty, must contain a value of any kind other than null or an empty string.');
- }
-
- // In case of string or int just return it as a string
- if (is_string($identifier) || is_int($identifier))
- {
- // cleanup to only allow alphanumeric chars, dashes, dots & underscores
- if (preg_match('/^([a-z0-9_\.\-]*)$/iuD', $identifier) === 0)
- {
- throw new \FuelException('Cache identifier can only contain alphanumeric characters, underscores, dashes & dots.');
- }
-
- return (string) $identifier;
- }
- // In case of array, bool or object return the md5 of the $identifier's serialization
- else
- {
- return '_hashes.'.md5(serialize($identifier));
- }
- }
-
- /**
- * Resets all properties except for the identifier, should be run by default when a delete() is triggered
- */
- public function reset()
- {
- $this->contents = null;
- $this->created = null;
- $this->expiration = null;
- $this->dependencies = array();
- $this->content_handler = null;
- $this->handler_object = null;
- }
-
- /**
- * Front for writing the cache, ensures interchangeability of storage engines. Actual writing
- * is being done by the _set() method which needs to be extended.
- *
- * @param mixed $contents The content to be cached
- * @param bool $expiration The time in seconds until the cache will expire, =< 0 or null means no expiration
- * @param array $dependencies array of names on which this cache depends for
- */
- final public function set($contents = null, $expiration = false, $dependencies = array())
- {
- $contents = \Fuel::value($contents);
- // save the current expiration
- $current_expiration = $this->expiration;
-
- // Use either the given value or the class property
- if ( ! is_null($contents))
- {
- $this->set_contents($contents);
- }
- $this->expiration = ($expiration !== false) ? $expiration : $this->expiration;
- $this->dependencies = ( ! empty($dependencies)) ? $dependencies : $this->dependencies;
-
- $this->created = time();
-
- // Create expiration timestamp when other then null
- if ( ! is_null($this->expiration))
- {
- if ( ! is_numeric($this->expiration))
- {
- throw new \InvalidArgumentException('Expiration must be a valid number.');
- }
- $this->expiration = $this->created + intval($this->expiration);
- }
-
- // Convert dependency identifiers to string when set
- $this->dependencies = ( ! is_array($this->dependencies)) ? array($this->dependencies) : $this->dependencies;
- if ( ! empty( $this->dependencies ) )
- {
- foreach($this->dependencies as $key => $id)
- {
- $this->dependencies[$key] = $this->stringify_identifier($id);
- }
- }
-
- // Turn everything over to the storage specific method
- $this->_set();
-
- // restore the expiration
- $this->expiration = $current_expiration;
- }
-
- /**
- * Front for reading the cache, ensures interchangeability of storage engines. Actual reading
- * is being done by the _get() method which needs to be extended.
- *
- * @param bool $use_expiration
- * @return Cache_Storage_Driver
- * @throws \CacheExpiredException
- * @throws \CacheNotFoundException
- */
- final public function get($use_expiration = true)
- {
- if ( ! $this->_get())
- {
- throw new \CacheNotFoundException('not found');
- }
-
- if ($use_expiration)
- {
- if ( ! is_null($this->expiration) and $this->expiration < 0)
- {
- $this->delete();
- throw new \CacheExpiredException('expired');
- }
-
- // Check dependencies and handle as expired on failure
- if ( ! $this->check_dependencies($this->dependencies))
- {
- $this->delete();
- throw new \CacheExpiredException('expired');
- }
- }
-
- return $this->get_contents();
- }
-
- /**
- * Does get() & set() in one call that takes a callback and it's arguments to generate the contents
- *
- * @param string|array $callback Valid PHP callback
- * @param array $args Arguments for the above function/method
- * @param int|null $expiration Cache expiration in seconds
- * @param array $dependencies Contains the identifiers of caches this one will depend on
- * @return mixed
- */
- final public function call($callback, $args = array(), $expiration = null, $dependencies = array())
- {
- try
- {
- $this->get();
- }
- catch (\CacheNotFoundException $e)
- {
- // Create the contents
- $contents = call_fuel_func_array($callback, $args);
-
- $this->set($contents, $expiration, $dependencies);
- }
-
- return $this->get_contents();
- }
-
- /**
- * Set the contents with optional handler instead of the default
- *
- * @param mixed
- * @param string
- * @return Cache_Storage_Driver
- */
- public function set_contents($contents, $handler = NULL)
- {
- $this->contents = $contents;
- $this->set_content_handler($handler);
- $this->contents = $this->handle_writing($contents);
- return $this;
- }
-
- /**
- * Fetches contents
- *
- * @return mixed
- */
- public function get_contents()
- {
- return $this->handle_reading($this->contents);
- }
-
- /**
- * Decides a content handler that makes it possible to write non-strings to a file
- *
- * @param string
- * @return Cache_Storage_Driver
- */
- protected function set_content_handler($handler)
- {
- $this->handler_object = null;
- $this->content_handler = (string) $handler;
- return $this;
- }
-
- /**
- * Gets a specific content handler
- *
- * @param string
- * @return Cache_Handler_Driver
- */
- public function get_content_handler($handler = null)
- {
- if ( ! empty($this->handler_object))
- {
- return $this->handler_object;
- }
-
- // When not yet set, use $handler or detect the preferred handler (string = string, otherwise serialize)
- if (empty($this->content_handler) && empty($handler))
- {
- if ( ! empty($handler))
- {
- $this->content_handler = $handler;
- }
- if (is_string($this->contents))
- {
- $this->content_handler = \Config::get('cache.string_handler', 'string');
- }
- else
- {
- $type = is_object($this->contents) ? get_class($this->contents) : gettype($this->contents);
- $this->content_handler = \Config::get('cache.'.$type.'_handler', 'serialized');
- }
- }
-
- $class = '\\Cache_Handler_'.ucfirst($this->content_handler);
- $this->handler_object = new $class();
-
- return $this->handler_object;
- }
-
- /**
- * Converts the contents the cachable format
- *
- * @param $contents
- * @return string
- */
- protected function handle_writing($contents)
- {
- return $this->get_content_handler()->writable($contents);
- }
-
- /**
- * Converts the cachable format to the original value
- *
- * @param $contents
- * @return mixed
- */
- protected function handle_reading($contents)
- {
- return $this->get_content_handler()->readable($contents);
- }
-}
diff --git a/fuel/core/classes/cache/storage/file.php b/fuel/core/classes/cache/storage/file.php
deleted file mode 100755
index bf744bd..0000000
--- a/fuel/core/classes/cache/storage/file.php
+++ /dev/null
@@ -1,389 +0,0 @@
-config = isset($config['file']) ? $config['file'] : array();
-
- // check for an expiration override
- $this->expiration = $this->_validate_config('expiration', isset($this->config['expiration'])
- ? $this->config['expiration'] : $this->expiration);
-
- // determine the file cache path
- static::$path = !empty($this->config['path'])
- ? $this->config['path'] : \Config::get('cache_dir', APPPATH.'cache'.DS);
-
- if ( ! is_dir(static::$path) || ! is_writable(static::$path))
- {
- throw new \FuelException('Cache directory does not exist or is not writable.');
- }
- }
-
- /**
- * Check if other caches or files have been changed since cache creation
- *
- * @param array
- * @return bool
- */
- public function check_dependencies(array $dependencies)
- {
- foreach($dependencies as $dep)
- {
- if (is_file($file = static::$path.str_replace('.', DS, $dep).'.cache'))
- {
- $filemtime = filemtime($file);
- if ($filemtime === false || $filemtime > $this->created)
- {
- return false;
- }
- }
- elseif (is_file($dep))
- {
- $filemtime = filemtime($dep);
- if ($filemtime === false || $filemtime > $this->created)
- {
- return false;
- }
- }
- else
- {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Delete Cache
- */
- public function delete()
- {
- if (is_file($file = static::$path.$this->identifier_to_path($this->identifier).'.cache'))
- {
- unlink($file);
- $this->reset();
- }
- }
-
- /**
- * Purge all caches
- *
- * @param string $section limit purge to subsection
- * @return bool
- */
- public function delete_all($section)
- {
- // get the cache root path and prep the requested section
- $path = rtrim(static::$path, '\\/').DS;
- $section = $section === null ? '' : static::identifier_to_path($section).DS;
-
- // if the path does not exist, bail out immediately
- if ( ! is_dir($path.$section))
- {
- return true;
- }
-
- // get all files in this section
- $files = \File::read_dir($path.$section, -1, array('\.cache$' => 'file'));
-
- // closure to recusively delete the files
- $delete = function($folder, $files) use(&$delete, $path)
- {
- $folder = rtrim($folder, '\\/').DS;
-
- foreach ($files as $dir => $file)
- {
- if (is_numeric($dir))
- {
- if ( ! $result = \File::delete($folder.$file))
- {
- return $result;
- }
- }
- else
- {
- if ( ! $result = ($delete($folder.$dir, $file)))
- {
- return $result;
- }
- }
- }
-
- // if we're processing a sub directory
- if ($folder != $path)
- {
- // remove the folder if no more files are left
- $files = \File::read_dir($folder);
- empty($files) and rmdir($folder);
- }
-
- return true;
- };
-
- return $delete($path.$section, $files);
- }
-
- // ---------------------------------------------------------------------
-
- /**
- * Translates a given identifier to a valid path
- *
- * @param string
- * @return string
- */
- protected function identifier_to_path($identifier)
- {
- // replace dots with dashes
- $identifier = str_replace('.', DS, $identifier);
-
- return $identifier;
- }
-
- /**
- * Prepend the cache properties
- *
- * @return string
- */
- protected function prep_contents()
- {
- $properties = array(
- 'created' => $this->created,
- 'expiration' => $this->expiration,
- 'dependencies' => $this->dependencies,
- 'content_handler' => $this->content_handler,
- );
- $properties = '{{'.self::PROPS_TAG.'}}'.json_encode($properties).'{{/'.self::PROPS_TAG.'}}';
-
- return $properties.$this->contents;
- }
-
- /**
- * Remove the prepended cache properties and save them in class properties
- *
- * @param string
- * @throws \UnexpectedValueException
- */
- protected function unprep_contents($payload)
- {
- $properties_end = strpos($payload, '{{/'.self::PROPS_TAG.'}}');
- if ($properties_end === false)
- {
- throw new \UnexpectedValueException('Cache has bad formatting');
- }
-
- $this->contents = substr($payload, $properties_end + strlen('{{/'.self::PROPS_TAG.'}}'));
- $props = substr(substr($payload, 0, $properties_end), strlen('{{'.self::PROPS_TAG.'}}'));
- $props = json_decode($props, true);
- if ($props === null)
- {
- throw new \UnexpectedValueException('Cache properties retrieval failed');
- }
-
- $this->created = $props['created'];
- $this->expiration = is_null($props['expiration']) ? null : (int) ($props['expiration'] - time());
- $this->dependencies = $props['dependencies'];
- $this->content_handler = $props['content_handler'];
- }
-
- /**
- * Save a cache, this does the generic pre-processing
- *
- * @return bool success
- */
- protected function _set()
- {
- $payload = $this->prep_contents();
- $id_path = $this->identifier_to_path($this->identifier);
-
- // create directory if necessary
- $subdirs = explode(DS, $id_path);
- if (count($subdirs) > 1)
- {
- array_pop($subdirs);
-
- // check if specified subdir exists
- if ( ! @is_dir(static::$path.implode(DS, $subdirs)))
- {
- // recursively create the directory. we can't use mkdir permissions or recursive
- // due to the fact that mkdir is restricted by the current users umask
- $basepath = rtrim(static::$path, DS);
- $chmod = \Config::get('file.chmod.folders', 0775);
- foreach ($subdirs as $dir)
- {
- $basepath .= DS.$dir;
- if ( ! is_dir($basepath))
- {
- try
- {
- if ( ! mkdir($basepath))
- {
- return false;
- }
- chmod($basepath, $chmod);
- }
- catch (\PHPErrorException $e)
- {
- return false;
- }
- }
- }
- }
- }
-
- // write the cache
- $file = static::$path.$id_path.'.cache';
-
- $handle = fopen($file, 'c');
-
- if ( ! $handle)
- {
- return false;
- }
-
- // wait for a lock
- while ( ! flock($handle, LOCK_EX));
-
- // truncate the file
- ftruncate($handle, 0);
-
- // write the cache data
- fwrite($handle, $payload);
-
- // flush any pending output
- fflush($handle);
-
- //release the lock
- flock($handle, LOCK_UN);
-
- // close the file
- fclose($handle);
-
- // set the correct rights on the file
- chmod($file, \Config::get('file.chmod.files', 0666));
-
- return true;
- }
-
- /**
- * Load a cache, this does the generic post-processing
- *
- * @return bool success
- */
- protected function _get()
- {
- $payload = false;
-
- $id_path = $this->identifier_to_path( $this->identifier );
- $file = static::$path.$id_path.'.cache';
-
- // normalize the file
- $file = realpath($file);
-
- // make sure it exists
- if (is_file($file))
- {
- $handle = fopen($file, 'r');
- if ($handle)
- {
- // wait for a lock
- while( ! flock($handle, LOCK_SH));
-
- // read the cache data
- $payload = file_get_contents($file);
-
- //release the lock
- flock($handle, LOCK_UN);
-
- // close the file
- fclose($handle);
-
- }
- }
-
- try
- {
- $this->unprep_contents($payload);
- }
- catch (\UnexpectedValueException $e)
- {
- return false;
- }
-
- return true;
- }
-
- /**
- * validate a driver config value
- *
- * @param string $name name of the config variable to validate
- * @param mixed $value
- * @return mixed
- */
- protected function _validate_config($name, $value)
- {
- switch ($name)
- {
- case 'cache_id':
- if (empty($value) or ! is_string($value))
- {
- $value = 'fuel';
- }
- break;
-
- case 'expiration':
- if (empty($value) or ! is_numeric($value))
- {
- $value = null;
- }
- break;
- }
-
- return $value;
- }
-}
diff --git a/fuel/core/classes/cache/storage/memcached.php b/fuel/core/classes/cache/storage/memcached.php
deleted file mode 100755
index 1ca3495..0000000
--- a/fuel/core/classes/cache/storage/memcached.php
+++ /dev/null
@@ -1,454 +0,0 @@
-config = isset($config['memcached']) ? $config['memcached'] : array();
-
- // make sure we have a memcache id
- $this->config['cache_id'] = $this->_validate_config('cache_id', isset($this->config['cache_id'])
- ? $this->config['cache_id'] : 'fuel');
-
- // check for an expiration override
- $this->expiration = $this->_validate_config('expiration', isset($this->config['expiration'])
- ? $this->config['expiration'] : $this->expiration);
-
- if (static::$memcached === false)
- {
- // make sure we have memcached servers configured
- $this->config['servers'] = $this->_validate_config('servers', $this->config['servers']);
-
- // do we have the PHP memcached extension available
- if ( ! class_exists('Memcached') )
- {
- throw new \FuelException('Memcached cache are configured, but your PHP installation doesn\'t have the Memcached extension loaded.');
- }
-
- // instantiate the memcached object
- static::$memcached = new \Memcached();
-
- // add the configured servers
- static::$memcached->addServers($this->config['servers']);
-
- // check if we can connect to all the server(s)
- $added = static::$memcached->getStats();
- foreach ($this->config['servers'] as $server)
- {
- $server = $server['host'].':'.$server['port'];
- if ( ! isset($added[$server]) or $added[$server]['pid'] == -1)
- {
- throw new \FuelException('Memcached cache is configured, but there is no connection possible. Check your configuration.');
- }
- }
- }
- }
-
- // ---------------------------------------------------------------------
-
- /**
- * Check if other caches or files have been changed since cache creation
- *
- * @param array
- * @return bool
- */
- public function check_dependencies(array $dependencies)
- {
- foreach($dependencies as $dep)
- {
- // get the section name and identifier
- $sections = explode('.', $dep);
- if (count($sections) > 1)
- {
- $identifier = array_pop($sections);
- $sections = '.'.implode('.', $sections);
-
- }
- else
- {
- $identifier = $dep;
- $sections = '';
- }
-
- // get the cache index
- $index = static::$memcached->get($this->config['cache_id'].$sections);
-
- // get the key from the index
- $key = isset($index[$identifier][0]) ? $index[$identifier] : false;
-
- // key found and newer?
- if ($key === false or $key[1] > $this->created)
- {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Delete Cache
- */
- public function delete()
- {
- // get the memcached key for the cache identifier
- $key = $this->_get_key(true);
-
- // delete the key from the memcached server
- if ($key and static::$memcached->delete($key) === false)
- {
- if (static::$memcached->getResultCode() !== \Memcached::RES_NOTFOUND)
- {
- throw new \FuelException('Memcached returned error code "'.static::$memcached->getResultCode().'" on delete. Check your configuration.');
- }
- }
-
- $this->reset();
- }
-
- /**
- * Purge all caches
- *
- * @param string $section limit purge to subsection
- * @return bool
- */
- public function delete_all($section)
- {
- // determine the section index name
- $section = $this->config['cache_id'].(empty($section) ? '' : '.'.$section);
-
- // get the directory index
- $index = static::$memcached->get($this->config['cache_id'].'__DIR__');
-
- if (is_array($index))
- {
- // limit the delete if we have a valid section
- if ( ! empty($section))
- {
- $dirs = in_array($section, $index) ? array($section) : array();
- }
- else
- {
- $dirs = $index;
- }
-
- // loop through the indexes, delete all stored keys, then delete the indexes
- foreach ($dirs as $dir)
- {
- $list = static::$memcached->get($dir);
- foreach ($list as $item)
- {
- static::$memcached->delete($item[0]);
- }
- static::$memcached->delete($dir);
- }
-
- // update the directory index
- $index = array_diff($index, $dirs);
- static::$memcached->set($this->config['cache_id'].'__DIR__', $index);
- }
- }
-
- // ---------------------------------------------------------------------
-
- /**
- * Prepend the cache properties
- *
- * @return string
- */
- protected function prep_contents()
- {
- $properties = array(
- 'created' => $this->created,
- 'expiration' => $this->expiration,
- 'dependencies' => $this->dependencies,
- 'content_handler' => $this->content_handler,
- );
- $properties = '{{'.static::PROPS_TAG.'}}'.json_encode($properties).'{{/'.static::PROPS_TAG.'}}';
-
- return $properties.$this->contents;
- }
-
- /**
- * Remove the prepended cache properties and save them in class properties
- *
- * @param string
- * @throws \UnexpectedValueException
- */
- protected function unprep_contents($payload)
- {
- $properties_end = strpos($payload, '{{/'.static::PROPS_TAG.'}}');
- if ($properties_end === FALSE)
- {
- throw new \UnexpectedValueException('Cache has bad formatting');
- }
-
- $this->contents = substr($payload, $properties_end + strlen('{{/'.static::PROPS_TAG.'}}'));
- $props = substr(substr($payload, 0, $properties_end), strlen('{{'.static::PROPS_TAG.'}}'));
- $props = json_decode($props, true);
- if ($props === NULL)
- {
- throw new \UnexpectedValueException('Cache properties retrieval failed');
- }
-
- $this->created = $props['created'];
- $this->expiration = is_null($props['expiration']) ? null : (int) ($props['expiration'] - time());
- $this->dependencies = $props['dependencies'];
- $this->content_handler = $props['content_handler'];
- }
-
- /**
- * Save a cache, this does the generic pre-processing
- *
- * @return bool success
- * @throws \FuelException
- */
- protected function _set()
- {
- // get the memcached key for the cache identifier
- $key = $this->_get_key();
-
- $payload = $this->prep_contents();
-
- // calculate relative expiration time (eg. 60s)
- $expiration = !is_null($this->expiration) ? $this->expiration - time() : 0;
-
- // if expiration value is less than 30 days, use relative value, otherwise use unix timestamp:
- $expiration = $expiration <= 2592000 ? (int) $expiration : (int) $this->expiration;
-
- // write it to the memcached server
- if (static::$memcached->set($key, $payload, $expiration) === false)
- {
- throw new \FuelException('Memcached returned error code "'.static::$memcached->getResultCode().'" on write. Check your configuration.');
- }
-
- // update the index
- $this->_update_index($key);
-
- return true;
- }
-
- /**
- * Load a cache, this does the generic post-processing
- *
- * @return bool success
- */
- protected function _get()
- {
- // get the memcached key for the cache identifier
- $key = $this->_get_key();
-
- // fetch the cached data from the Memcached server
- $payload = static::$memcached->get($key);
-
- try
- {
- $this->unprep_contents($payload);
- }
- catch (\UnexpectedValueException $e)
- {
- return false;
- }
-
- return true;
- }
-
- /**
- * validate a driver config value
- *
- * @param string $name name of the config variable to validate
- * @param mixed $value
- * @return mixed
- * @throws \FuelException
- */
- protected function _validate_config($name, $value)
- {
- switch ($name)
- {
- case 'cache_id':
- if (empty($value) or ! is_string($value))
- {
- $value = 'fuel';
- }
- break;
-
- case 'expiration':
- if (empty($value) or ! is_numeric($value))
- {
- $value = null;
- }
- break;
-
- case 'servers':
- // do we have a servers config
- if ( empty($value) OR ! is_array($value))
- {
- $value = array('default' => array('host' => '127.0.0.1', 'port' => '11211'));
- }
-
- // validate the servers
- foreach ($value as $key => $server)
- {
- // do we have a host?
- if ( ! isset($server['host']) OR ! is_string($server['host']))
- {
- throw new \FuelException('Invalid Memcached server definition in the cache configuration.');
- }
- // do we have a port number?
- if ( ! isset($server['port']) OR ! is_numeric($server['port']) OR $server['port'] < 1025 OR $server['port'] > 65535)
- {
- throw new \FuelException('Invalid Memcached server definition in the cache configuration.');
- }
- // do we have a relative server weight?
- if ( ! isset($server['weight']) OR ! is_numeric($server['weight']) OR $server['weight'] < 0)
- {
- // set a default
- $value[$key]['weight'] = 0;
- }
- }
- break;
-
- default:
- break;
- }
-
- return $value;
- }
-
- /**
- * Get's the memcached key belonging to the cache identifier
- *
- * @param bool $remove if true, remove the key retrieved from the index
- * @return string
- */
- protected function _get_key($remove = false)
- {
- // get the current index information
- list($identifier, $sections, $index) = $this->_get_index();
-
- // get the key from the index
- $key = isset($index[$identifier][0]) ? $index[$identifier][0] : false;
-
- if ($remove === true)
- {
- if ( $key !== false )
- {
- unset($index[$identifier]);
- static::$memcached->set($this->config['cache_id'].$sections, $index);
- }
- }
- else
- {
- // create a new key if needed
- $key === false and $key = $this->_new_key();
- }
- return $key;
- }
-
- /**
- * Generate a new unique key for the current identifier
- *
- * @return string
- */
- protected function _new_key()
- {
- $key = '';
- while (strlen($key) < 32)
- {
- $key .= mt_rand(0, mt_getrandmax());
- }
- return md5($this->config['cache_id'].'_'.uniqid($key, TRUE));
- }
-
- /**
- * Get the section index
- *
- * @return array containing the identifier, the sections, and the section index
- */
- protected function _get_index()
- {
- // get the section name and identifier
- $sections = explode('.', $this->identifier);
- if (count($sections) > 1)
- {
- $identifier = array_pop($sections);
- $sections = '.'.implode('.', $sections);
-
- }
- else
- {
- $identifier = $this->identifier;
- $sections = '';
- }
-
- // get the cache index and return it
- return array($identifier, $sections, static::$memcached->get($this->config['cache_id'].$sections));
- }
-
- /**
- * Update the section index
- *
- * @param string cache key
- */
- protected function _update_index($key)
- {
- // get the current index information
- list($identifier, $sections, $index) = $this->_get_index();
-
- // create a new index and store the key
- is_array($index) or $index = array();
-
- // store the key in the index and write the index back
- $index[$identifier] = array($key, $this->created);
- static::$memcached->set($this->config['cache_id'].$sections, $index, 0);
-
- // get the directory index
- $index = static::$memcached->get($this->config['cache_id'].'__DIR__');
-
- if (is_array($index))
- {
- if (!in_array($this->config['cache_id'].$sections, $index))
- {
- $index[] = $this->config['cache_id'].$sections;
- }
- }
- else
- {
- $index = array($this->config['cache_id'].$sections);
- }
-
- // update the directory index
- static::$memcached->set($this->config['cache_id'].'__DIR__', $index, 0);
- }
-}
diff --git a/fuel/core/classes/cache/storage/redis.php b/fuel/core/classes/cache/storage/redis.php
deleted file mode 100755
index c397bd4..0000000
--- a/fuel/core/classes/cache/storage/redis.php
+++ /dev/null
@@ -1,509 +0,0 @@
-config = isset($config['redis']) ? $config['redis'] : array();
-
- // make sure we have a redis id
- $this->config['cache_id'] = $this->_validate_config('cache_id', isset($this->config['cache_id'])
- ? $this->config['cache_id'] : 'fuel');
-
- // check for an expiration override
- $this->expiration = $this->_validate_config('expiration', isset($this->config['expiration'])
- ? $this->config['expiration'] : $this->expiration);
-
- // make sure we have a redis database configured
- $this->config['database'] = $this->_validate_config('database', isset($this->config['database'])
- ? $this->config['database'] : 'default');
-
- if (static::$redis === false)
- {
- // get the redis database instance
- try
- {
- static::$redis = \Redis_Db::instance($this->config['database']);
- }
- catch (\Exception $e)
- {
- throw new \FuelException('Can not connect to the Redis engine. The error message says "'.$e->getMessage().'".');
- }
-
- // get the redis version
- preg_match('/redis_version:(.*?)\n/', static::$redis->info(), $info);
- if (version_compare(trim($info[1]), '1.2') < 0)
- {
- throw new \FuelException('Version 1.2 or higher of the Redis NoSQL engine is required to use the redis cache driver.');
- }
- }
- }
-
- // ---------------------------------------------------------------------
-
- /**
- * Check if other caches or files have been changed since cache creation
- *
- * @param array
- * @return bool
- */
- public function check_dependencies(array $dependencies)
- {
- foreach($dependencies as $dep)
- {
- // get the section name and identifier
- $sections = explode('.', $dep);
- if (count($sections) > 1)
- {
- $identifier = array_pop($sections);
- $sections = '.'.implode('.', $sections);
-
- }
- else
- {
- $identifier = $dep;
- $sections = '';
- }
-
- // get the cache index
- $index = static::$redis->get($this->config['cache_id'].':index:'.$sections);
- is_null($index) or $index = $this->_unserialize($index);
-
- // get the key from the index
- $key = isset($index[$identifier][0]) ? $index[$identifier] : false;
-
- // key found and newer?
- if ($key === false or $key[1] > $this->created)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Delete Cache
- */
- public function delete()
- {
- // get the key for the cache identifier
- $key = $this->_get_key(true);
-
- // delete the key from the redis server
- if ($key and static::$redis->del($key) === false)
- {
- // do something here?
- }
-
- $this->reset();
- }
-
- /**
- * Purge all caches
- *
- * @param string $section limit purge to subsection
- * @return bool
- */
- public function delete_all($section)
- {
- // determine the section index name
- $section = empty($section) ? '' : '.'.$section;
-
- // get the directory index
- $index = static::$redis->get($this->config['cache_id'].':dir:');
- is_null($index) or $index = $this->_unserialize($index);
-
- if (is_array($index))
- {
- if (!empty($section))
- {
- // limit the delete if we have a valid section
- $dirs = array();
- foreach ($index as $entry)
- {
- if ($entry == $section or strpos($entry, $section.'.') === 0)
- {
- $dirs[] = $entry;
- }
- }
- }
- else
- {
- // else delete the entire contents of the cache
- $dirs = $index;
- }
-
- // loop through the selected indexes
- foreach ($dirs as $dir)
- {
- // get the stored cache entries for this index
- $list = static::$redis->get($this->config['cache_id'].':index:'.$dir);
- if (is_null($list))
- {
- $list = array();
- }
- else
- {
- $list = $this->_unserialize($list);
- }
-
- // delete all stored keys
- foreach($list as $item)
- {
- static::$redis->del($item[0]);
- }
-
- // and delete the index itself
- static::$redis->del($this->config['cache_id'].':index:'.$dir);
- }
-
- // update the directory index
- static::$redis->set($this->config['cache_id'].':dir:', $this->_serialize(array_diff($index, $dirs)));
- }
- }
-
- // ---------------------------------------------------------------------
-
- /**
- * Translates a given identifier to a valid redis key
- *
- * @param string
- * @return string
- */
- protected function identifier_to_key( $identifier )
- {
- return $this->config['cache_id'].':'.$identifier;
- }
-
- /**
- * Prepend the cache properties
- *
- * @return string
- */
- protected function prep_contents()
- {
- $properties = array(
- 'created' => $this->created,
- 'expiration' => $this->expiration,
- 'dependencies' => $this->dependencies,
- 'content_handler' => $this->content_handler,
- );
- $properties = '{{'.static::PROPS_TAG.'}}'.json_encode($properties).'{{/'.static::PROPS_TAG.'}}';
-
- return $properties.$this->contents;
- }
-
- /**
- * Remove the prepended cache properties and save them in class properties
- *
- * @param string
- * @throws \UnexpectedValueException
- */
- protected function unprep_contents($payload)
- {
- $properties_end = strpos($payload, '{{/'.static::PROPS_TAG.'}}');
- if ($properties_end === FALSE)
- {
- throw new \UnexpectedValueException('Cache has bad formatting');
- }
-
- $this->contents = substr($payload, $properties_end + strlen('{{/'.static::PROPS_TAG.'}}'));
- $props = substr(substr($payload, 0, $properties_end), strlen('{{'.static::PROPS_TAG.'}}'));
- $props = json_decode($props, true);
- if ($props === NULL)
- {
- throw new \UnexpectedValueException('Cache properties retrieval failed');
- }
-
- $this->created = $props['created'];
- $this->expiration = is_null($props['expiration']) ? null : (int) ($props['expiration'] - time());
- $this->dependencies = $props['dependencies'];
- $this->content_handler = $props['content_handler'];
- }
-
- /**
- * Save a cache, this does the generic pre-processing
- *
- * @return bool success
- */
- protected function _set()
- {
- // get the key for the cache identifier
- $key = $this->_get_key();
-
- // write the cache
- static::$redis->set($key, $this->prep_contents());
- if ( ! empty($this->expiration))
- {
- static::$redis->expireat($key, $this->expiration);
- }
-
- // update the index
- $this->_update_index($key);
-
- return true;
- }
-
- /**
- * Load a cache, this does the generic post-processing
- *
- * @return bool success
- */
- protected function _get()
- {
- // get the key for the cache identifier
- $key = $this->_get_key();
-
- // fetch the cache data from the redis server
- $payload = static::$redis->get($key);
- try
- {
- $this->unprep_contents($payload);
- }
- catch (\UnexpectedValueException $e)
- {
- return false;
- }
-
- return true;
- }
-
- /**
- * validate a driver config value
- *
- * @param string $name name of the config variable to validate
- * @param mixed $value value
- * @return mixed
- */
- protected function _validate_config($name, $value)
- {
- switch ($name)
- {
- case 'database':
- // do we have a database config
- if (empty($value) or ! is_string($value))
- {
- $value = 'default';
- }
- break;
-
- case 'cache_id':
- if (empty($value) or ! is_string($value))
- {
- $value = 'fuel';
- }
- break;
-
- case 'expiration':
- if (empty($value) or ! is_numeric($value))
- {
- $value = null;
- }
- break;
-
- default:
- break;
- }
-
- return $value;
- }
-
- /**
- * get's the redis key belonging to the cache identifier
- *
- * @param bool $remove if true, remove the key retrieved from the index
- * @return string
- */
- protected function _get_key($remove = false)
- {
- // get the current index information
- list($identifier, $sections, $index) = $this->_get_index();
- $index = $index === null ? array() : $index = $this->_unserialize($index);
-
- // get the key from the index
- $key = isset($index[$identifier][0]) ? $index[$identifier][0] : false;
-
- if ($remove === true)
- {
- if ( $key !== false )
- {
- unset($index[$identifier]);
- static::$redis->set($this->config['cache_id'].':index:'.$sections, $this->_serialize($index));
- }
- }
- else
- {
- // create a new key if needed
- $key === false and $key = $this->_new_key();
- }
-
- return $key;
- }
-
- /**
- * generate a new unique key for the current identifier
- *
- * @return string
- */
- protected function _new_key()
- {
- $key = '';
- while (strlen($key) < 32)
- {
- $key .= mt_rand(0, mt_getrandmax());
- }
- return md5($this->config['cache_id'].'_'.uniqid($key, TRUE));
- }
-
- /**
- * Get the section index
- *
- * @return array containing the identifier, the sections, and the section index
- */
- protected function _get_index()
- {
- // get the section name and identifier
- $sections = explode('.', $this->identifier);
- if (count($sections) > 1)
- {
- $identifier = array_pop($sections);
- $sections = '.'.implode('.', $sections);
- }
- else
- {
- $identifier = $this->identifier;
- $sections = '';
- }
-
- // get the cache index and return it
- return array($identifier, $sections, static::$redis->get($this->config['cache_id'].':index:'.$sections));
- }
-
- /**
- * Update the section index
- *
- * @param string cache key
- */
- protected function _update_index($key)
- {
- // get the current index information
- list($identifier, $sections, $index) = $this->_get_index();
- $index = $index === null ? array() : $index = $this->_unserialize($index);
-
- // store the key in the index and write the index back
- $index[$identifier] = array($key, $this->created);
-
- static::$redis->set($this->config['cache_id'].':index:'.$sections, $this->_serialize($index));
-
- // get the directory index
- $index = static::$redis->get($this->config['cache_id'].':dir:');
- $index = $index === null ? array() : $index = $this->_unserialize($index);
-
- if (is_array($index))
- {
- if ( ! in_array($sections, $index))
- {
- $index[] = $sections;
- }
- }
- else
- {
- $index = array($sections);
- }
-
- // update the directory index
- static::$redis->set($this->config['cache_id'].':dir:', $this->_serialize($index));
- }
-
- /**
- * Serialize an array
- *
- * This function first converts any slashes found in the array to a temporary
- * marker, so when it gets unserialized the slashes will be preserved
- *
- * @param array
- * @return string
- */
- protected function _serialize($data)
- {
- if (is_array($data))
- {
- foreach ($data as $key => $val)
- {
- if (is_string($val))
- {
- $data[$key] = str_replace('\\', '{{slash}}', $val);
- }
- }
- }
- else
- {
- if (is_string($data))
- {
- $data = str_replace('\\', '{{slash}}', $data);
- }
- }
-
- return serialize($data);
- }
-
- /**
- * Unserialize
- *
- * This function unserializes a data string, then converts any
- * temporary slash markers back to actual slashes
- *
- * @param array
- * @return string
- */
- protected function _unserialize($data)
- {
- $data = @unserialize(stripslashes($data));
-
- if (is_array($data))
- {
- foreach ($data as $key => $val)
- {
- if (is_string($val))
- {
- $data[$key] = str_replace('{{slash}}', '\\', $val);
- }
- }
-
- return $data;
- }
-
- return (is_string($data)) ? str_replace('{{slash}}', '\\', $data) : $data;
- }
-}
diff --git a/fuel/core/classes/cache/storage/xcache.php b/fuel/core/classes/cache/storage/xcache.php
deleted file mode 100755
index 39edc89..0000000
--- a/fuel/core/classes/cache/storage/xcache.php
+++ /dev/null
@@ -1,375 +0,0 @@
-config = isset($config['xcache']) ? $config['xcache'] : array();
-
- // make sure we have an id
- $this->config['cache_id'] = $this->_validate_config('cache_id', isset($this->config['cache_id'])
- ? $this->config['cache_id'] : 'fuel');
-
- // check for an expiration override
- $this->expiration = $this->_validate_config('expiration', isset($this->config['expiration'])
- ? $this->config['expiration'] : $this->expiration);
-
- // do we have the PHP XCache extension available
- if ( ! function_exists('xcache_set') )
- {
- throw new \FuelException('Your PHP installation doesn\'t have XCache loaded.');
- }
- }
-
- // ---------------------------------------------------------------------
-
- /**
- * Check if other caches or files have been changed since cache creation
- *
- * @param array
- * @return bool
- */
- public function check_dependencies(array $dependencies)
- {
- foreach($dependencies as $dep)
- {
- // get the section name and identifier
- $sections = explode('.', $dep);
- if (count($sections) > 1)
- {
- $identifier = array_pop($sections);
- $sections = '.'.implode('.', $sections);
-
- }
- else
- {
- $identifier = $dep;
- $sections = '';
- }
-
- // get the cache index
- $index = xcache_get($this->config['cache_id'].$sections);
-
- // get the key from the index
- $key = isset($index[$identifier][0]) ? $index[$identifier] : false;
-
- // key found and newer?
- if ($key === false or $key[1] > $this->created)
- {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Delete Cache
- */
- public function delete()
- {
- // get the XCache key for the cache identifier
- $key = $this->_get_key(true);
-
- // delete the key from the xcache store
- $key and xcache_unset($key);
-
- $this->reset();
- }
-
- /**
- * Purge all caches
- *
- * @param string $section limit purge to subsection
- * @return bool
- */
- public function delete_all($section)
- {
- // determine the section index name
- $section = $this->config['cache_id'].(empty($section) ? '' : '.'.$section);
-
- // get the directory index
- $index = xcache_get($this->config['cache_id'].'__DIR__');
-
- if (is_array($index))
- {
- $dirs = array();
- foreach ($index as $dir)
- {
- if (strpos($dir, $section) === 0)
- {
- $dirs[] = $dir;
- $list = xcache_get($dir);
- foreach ($list as $item)
- {
- xcache_unset($item[0]);
- }
- xcache_unset($dir);
- }
- }
-
- // update the directory index
- $dirs and xcache_set($this->config['cache_id'].'__DIR__', array_diff($index, $dirs));
- }
- }
-
- // ---------------------------------------------------------------------
-
- /**
- * Prepend the cache properties
- *
- * @return string
- */
- protected function prep_contents()
- {
- $properties = array(
- 'created' => $this->created,
- 'expiration' => $this->expiration,
- 'dependencies' => $this->dependencies,
- 'content_handler' => $this->content_handler,
- );
- $properties = '{{'.static::PROPS_TAG.'}}'.json_encode($properties).'{{/'.static::PROPS_TAG.'}}';
-
- return $properties.$this->contents;
- }
-
- /**
- * Remove the prepended cache properties and save them in class properties
- *
- * @param string $payload
- * @throws \UnexpectedValueException
- */
- protected function unprep_contents($payload)
- {
- $properties_end = strpos($payload, '{{/'.static::PROPS_TAG.'}}');
- if ($properties_end === FALSE)
- {
- throw new \UnexpectedValueException('Cache has bad formatting');
- }
-
- $this->contents = substr($payload, $properties_end + strlen('{{/'.static::PROPS_TAG.'}}'));
- $props = substr(substr($payload, 0, $properties_end), strlen('{{'.static::PROPS_TAG.'}}'));
- $props = json_decode($props, true);
- if ($props === NULL)
- {
- throw new \UnexpectedValueException('Cache properties retrieval failed');
- }
-
- $this->created = $props['created'];
- $this->expiration = is_null($props['expiration']) ? null : (int) ($props['expiration'] - time());
- $this->dependencies = $props['dependencies'];
- $this->content_handler = $props['content_handler'];
- }
-
- /**
- * Save a cache, this does the generic pre-processing
- *
- * @return bool success
- */
- protected function _set()
- {
- // get the xcache key for the cache identifier
- $key = $this->_get_key();
-
- $payload = $this->prep_contents();
-
- // adjust the expiration, xcache uses a TTL instead of a timestamp
- $expiration = is_null($this->expiration) ? 0 : (int) ($this->expiration - $this->created);
-
- // write it to the xcache store
- if (xcache_set($key, $payload, $expiration) === false)
- {
- throw new \RuntimeException('Xcache returned failed to write. Check your configuration.');
- }
-
- // update the index
- $this->_update_index($key);
-
- return true;
- }
-
- /**
- * Load a cache, this does the generic post-processing
- *
- * @return bool success
- */
- protected function _get()
- {
- // get the xcache key for the cache identifier
- $key = $this->_get_key();
-
- // fetch the cached data from the xcache store
- $payload = xcache_get($key);
-
- try
- {
- $this->unprep_contents($payload);
- }
- catch (\UnexpectedValueException $e)
- {
- return false;
- }
-
- return true;
- }
-
- /**
- * validate a driver config value
- *
- * @param string $name name of the config variable to validate
- * @param mixed $value
- * @return mixed
- */
- private function _validate_config($name, $value)
- {
- switch ($name)
- {
- case 'cache_id':
- if (empty($value) or ! is_string($value))
- {
- $value = 'fuel';
- }
- break;
-
- case 'expiration':
- if (empty($value) or ! is_numeric($value))
- {
- $value = null;
- }
- break;
-
- default:
- break;
- }
-
- return $value;
- }
-
- /**
- * get's the xcache key belonging to the cache identifier
- *
- * @param bool $remove if true, remove the key retrieved from the index
- * @return string
- */
- protected function _get_key($remove = false)
- {
- // get the current index information
- list($identifier, $sections, $index) = $this->_get_index();
-
- // get the key from the index
- $key = isset($index[$identifier][0]) ? $index[$identifier][0] : false;
-
- if ($remove === true)
- {
- if ( $key !== false )
- {
- unset($index[$identifier]);
- xcache_set($this->config['cache_id'].$sections, $index);
- }
- }
- else
- {
- // create a new key if needed
- $key === false and $key = $this->_new_key();
- }
-
- return $key;
- }
-
- /**
- * generate a new unique key for the current identifier
- *
- * @return string
- */
- protected function _new_key()
- {
- $key = '';
- while (strlen($key) < 32)
- {
- $key .= mt_rand(0, mt_getrandmax());
- }
- return md5($this->config['cache_id'].'_'.uniqid($key, TRUE));
- }
-
- /**
- * Get the section index
- *
- * @return array containing the identifier, the sections, and the section index
- */
- protected function _get_index()
- {
- // get the section name and identifier
- $sections = explode('.', $this->identifier);
- if (count($sections) > 1)
- {
- $identifier = array_pop($sections);
- $sections = '.'.implode('.', $sections);
- }
- else
- {
- $identifier = $this->identifier;
- $sections = '';
- }
-
- // get the cache index and return it
- return array($identifier, $sections, xcache_get($this->config['cache_id'].$sections));
- }
-
- /**
- * Update the section index
- *
- * @param string cache key
- */
- protected function _update_index($key)
- {
- // get the current index information
- list($identifier, $sections, $index) = $this->_get_index();
-
- // store the key in the index and write the index back
- $index[$identifier] = array($key, $this->created);
- xcache_set($this->config['cache_id'].$sections, array_merge($index, array($identifier => array($key, $this->created))));
-
- // get the directory index
- $index = xcache_get($this->config['cache_id'].'__DIR__');
-
- if (is_array($index))
- {
- if (!in_array($this->config['cache_id'].$sections, $index))
- {
- $index[] = $this->config['cache_id'].$sections;
- }
- }
- else
- {
- $index = array($this->config['cache_id'].$sections);
- }
-
- // update the directory index
- xcache_set($this->config['cache_id'].'__DIR__', $index, 0);
- }
-}
diff --git a/fuel/core/classes/cli.php b/fuel/core/classes/cli.php
deleted file mode 100755
index 185b605..0000000
--- a/fuel/core/classes/cli.php
+++ /dev/null
@@ -1,532 +0,0 @@
- '0;30',
- 'dark_gray' => '1;30',
- 'blue' => '0;34',
- 'dark_blue' => '1;34',
- 'light_blue' => '1;34',
- 'green' => '0;32',
- 'light_green' => '1;32',
- 'cyan' => '0;36',
- 'light_cyan' => '1;36',
- 'red' => '0;31',
- 'light_red' => '1;31',
- 'purple' => '0;35',
- 'light_purple' => '1;35',
- 'light_yellow' => '0;33',
- 'yellow' => '1;33',
- 'light_gray' => '0;37',
- 'white' => '1;37',
- );
-
- protected static $background_colors = array(
- 'black' => '40',
- 'red' => '41',
- 'green' => '42',
- 'yellow' => '43',
- 'blue' => '44',
- 'magenta' => '45',
- 'cyan' => '46',
- 'light_gray' => '47',
- );
-
- protected static $STDOUT;
- protected static $STDERR;
-
- /**
- * Static constructor. Parses all the CLI params.
- */
- public static function _init()
- {
- if ( ! \Fuel::$is_cli)
- {
- throw new \Exception('Cli class cannot be used outside of the command line.');
- }
- for ($i = 1; $i < $_SERVER['argc']; $i++)
- {
- $arg = explode('=', $_SERVER['argv'][$i]);
-
- static::$args[$i] = $arg[0];
-
- if (count($arg) > 1 || strncmp($arg[0], '-', 1) === 0)
- {
- static::$args[ltrim($arg[0], '-')] = isset($arg[1]) ? $arg[1] : true;
- }
- }
-
- // Readline is an extension for PHP that makes interactive with PHP much more bash-like
- // http://www.php.net/manual/en/readline.installation.php
- static::$readline_support = extension_loaded('readline');
-
- static::$STDERR = STDERR;
- static::$STDOUT = STDOUT;
- }
-
- /**
- * Returns the option with the given name. You can also give the option
- * number.
- *
- * Named options must be in the following formats:
- * php index.php user -v --v -name=John --name=John
- *
- * @param string|int $name the name of the option (int if unnamed)
- * @param mixed $default value to return if the option is not defined
- * @return mixed
- */
- public static function option($name, $default = null)
- {
- if ( ! isset(static::$args[$name]))
- {
- return \Fuel::value($default);
- }
- return static::$args[$name];
- }
-
- /**
- * Allows you to set a commandline option from code
- *
- * @param string|int $name the name of the option (int if unnamed)
- * @param mixed|null $value value to set, or null to delete the option
- * @return mixed
- */
- public static function set_option($name, $value = null)
- {
- if ($value === null)
- {
- if (isset(static::$args[$name]))
- {
- unset(static::$args[$name]);
- }
- }
- else
- {
- static::$args[$name] = $value;
- }
- }
-
- /**
- * Get input from the shell, using readline or the standard STDIN
- *
- * Named options must be in the following formats:
- * php index.php user -v --v -name=John --name=John
- *
- * @param string|int $prefix the name of the option (int if unnamed)
- * @return string
- */
- public static function input($prefix = '')
- {
- if (static::$readline_support)
- {
- return readline($prefix);
- }
-
- echo $prefix;
- return fgets(STDIN);
- }
-
- /**
- * Asks the user for input. This can have either 1 or 2 arguments.
- *
- * Usage:
- *
- * // Waits for any key press
- * CLI::prompt();
- *
- * // Takes any input
- * $color = CLI::prompt('What is your favorite color?');
- *
- * // Takes any input, but offers default
- * $color = CLI::prompt('What is your favourite color?', 'white');
- *
- * // Will only accept the options in the array
- * $ready = CLI::prompt('Are you ready?', array('y','n'));
- *
- * @return string the user input
- */
- public static function prompt()
- {
- $args = func_get_args();
-
- $options = array();
- $output = '';
- $default = null;
-
- // How many we got
- $arg_count = count($args);
-
- // Is the last argument a boolean? True means required
- $required = end($args) === true;
-
- // Reduce the argument count if required was passed, we don't care about that anymore
- $required === true and --$arg_count;
-
- // This method can take a few crazy combinations of arguments, so lets work it out
- switch ($arg_count)
- {
- case 2:
-
- // E.g: $ready = CLI::prompt('Are you ready?', array('y','n'));
- if (is_array($args[1]))
- {
- list($output, $options)=$args;
- }
-
- // E.g: $color = CLI::prompt('What is your favourite color?', 'white');
- elseif (is_string($args[1]))
- {
- list($output, $default)=$args;
- }
-
- break;
-
- case 1:
-
- // No question (probably been asked already) so just show options
- // E.g: $ready = CLI::prompt(array('y','n'));
- if (is_array($args[0]))
- {
- $options = $args[0];
- }
-
- // Question without options
- // E.g: $ready = CLI::prompt('What did you do today?');
- elseif (is_string($args[0]))
- {
- $output = $args[0];
- }
-
- break;
- }
-
- // If a question has been asked with the read
- if ($output !== '')
- {
- $extra_output = '';
-
- if ($default !== null)
- {
- $extra_output = ' [ Default: "'.$default.'" ]';
- }
-
- elseif ($options !== array())
- {
- $extra_output = ' [ '.implode(', ', $options).' ]';
- }
-
- fwrite(static::$STDOUT, $output.$extra_output.': ');
- }
-
- // Read the input from keyboard.
- $input = trim(static::input()) ?: $default;
-
- // No input provided and we require one (default will stop this being called)
- if (empty($input) and $required === true)
- {
- static::write('This is required.');
- static::new_line();
-
- $input = forward_static_call_array(array(__CLASS__, 'prompt'), $args);
- }
-
- // If options are provided and the choice is not in the array, tell them to try again
- if ( ! empty($options) and ! in_array($input, $options))
- {
- static::write('This is not a valid option. Please try again.');
- static::new_line();
-
- $input = forward_static_call_array(array(__CLASS__, 'prompt'), $args);
- }
-
- return $input;
- }
-
- /**
- * Outputs a string to the cli. If you send an array it will implode them
- * with a line break.
- *
- * @param string|array $text the text to output, or array of lines
- * @param string $foreground the foreground color
- * @param string $background the foreground color
- * @throws \FuelException
- */
- public static function write($text = '', $foreground = null, $background = null)
- {
- if (is_array($text))
- {
- $text = implode(PHP_EOL, $text);
- }
-
- if ($foreground or $background)
- {
- $text = static::color($text, $foreground, $background);
- }
-
- fwrite(static::$STDOUT, $text.PHP_EOL);
- }
-
- /**
- * Outputs an error to the CLI using STDERR instead of STDOUT
- *
- * @param string|array $text the text to output, or array of errors
- * @param string $foreground the foreground color
- * @param string $background the foreground color
- * @throws \FuelException
- */
- public static function error($text = '', $foreground = 'light_red', $background = null)
- {
- if (is_array($text))
- {
- $text = implode(PHP_EOL, $text);
- }
-
- if ($foreground OR $background)
- {
- $text = static::color($text, $foreground, $background);
- }
-
- fwrite(static::$STDERR, $text.PHP_EOL);
- }
-
- /**
- * Beeps a certain number of times.
- *
- * @param int $num the number of times to beep
- */
- public static function beep($num = 1)
- {
- echo str_repeat("\x07", $num);
- }
-
- /**
- * Waits a certain number of seconds, optionally showing a wait message and
- * waiting for a key press.
- *
- * @param int $seconds number of seconds
- * @param bool $countdown show a countdown or not
- */
- public static function wait($seconds = 0, $countdown = false)
- {
- if ($countdown === true)
- {
- $time = $seconds;
-
- while ($time > 0)
- {
- fwrite(static::$STDOUT, $time.'... ');
- sleep(1);
- $time--;
- }
- static::write();
- }
-
- else
- {
- if ($seconds > 0)
- {
- sleep($seconds);
- }
- else
- {
- static::write(static::$wait_msg);
- static::input();
- }
- }
- }
-
- /**
- * if operating system === windows
- */
- public static function is_windows()
- {
- return 'win' === strtolower(substr(php_uname("s"), 0, 3));
- }
-
- /**
- * Enter a number of empty lines
- *
- * @param integer Number of lines to output
- * @return void
- */
- public static function new_line($num = 1)
- {
- // Do it once or more, write with empty string gives us a new line
- for($i = 0; $i < $num; $i++)
- {
- static::write();
- }
- }
-
- /**
- * Clears the screen of output
- *
- * @return void
- */
- public static function clear_screen()
- {
- static::is_windows()
-
- // Windows is a bit crap at this, but their terminal is tiny so shove this in
- ? static::new_line(40)
-
- // Anything with a flair of Unix will handle these magic characters
- : fwrite(static::$STDOUT, chr(27)."[H".chr(27)."[2J");
- }
-
- /**
- * Returns the given text with the correct color codes for a foreground and
- * optionally a background color.
- *
- * @param string $text the text to color
- * @param string $foreground the foreground color
- * @param string $background the background color
- * @param string $format other formatting to apply. Currently only 'underline' is understood
- * @return string the color coded string
- * @throws \FuelException
- */
- public static function color($text, $foreground, $background = null, $format=null)
- {
- if (static::is_windows() and ! \Input::server('ANSICON'))
- {
- return $text;
- }
-
- if (static::$nocolor)
- {
- return $text;
- }
-
- if ( ! array_key_exists($foreground, static::$foreground_colors))
- {
- throw new \FuelException('Invalid CLI foreground color: '.$foreground);
- }
-
- if ( $background !== null and ! array_key_exists($background, static::$background_colors))
- {
- throw new \FuelException('Invalid CLI background color: '.$background);
- }
-
- $string = "\033[".static::$foreground_colors[$foreground]."m";
-
- if ($background !== null)
- {
- $string .= "\033[".static::$background_colors[$background]."m";
- }
-
- if ($format === 'underline')
- {
- $string .= "\033[4m";
- }
-
- $string .= $text."\033[0m";
-
- return $string;
- }
-
- /**
- * Spawn Background Process
- *
- * Launches a background process (note, provides no security itself, $call must be sanitised prior to use)
- * @param string $call the system call to make
- * @param string $output
- * @return void
- * @author raccettura
- * @link http://robert.accettura.com/blog/2006/09/14/asynchronous-processing-with-php/
- */
- public static function spawn($call, $output = '/dev/null')
- {
- // Windows
- if(static::is_windows())
- {
- pclose(popen('start /b '.$call, 'r'));
- }
-
- // Some sort of UNIX
- else
- {
- pclose(popen($call.' > '.$output.' &', 'r'));
- }
- }
-
- /**
- * Redirect STDERR writes to this file or fh
- *
- * Call with no argument to retrieve the current filehandle.
- *
- * Is not smart about opening the file if it's a string. Existing files will be truncated.
- *
- * @param resource|string $fh Opened filehandle or string filename.
- *
- * @return resource
- */
- public static function stderr($fh = null)
- {
- $orig = static::$STDERR;
-
- if (! is_null($fh)) {
- if (is_string($fh)) {
- $fh = fopen($fh, "w");
- }
- static::$STDERR = $fh;
- }
-
- return $orig;
- }
-
- /**
- * Redirect STDOUT writes to this file or fh
- *
- * Call with no argument to retrieve the current filehandle.
- *
- * Is not smart about opening the file if it's a string. Existing files will be truncated.
- *
- * @param resource|string|null $fh Opened filehandle or string filename.
- *
- * @return resource
- */
- public static function stdout($fh = null)
- {
- $orig = static::$STDOUT;
-
- if (! is_null($fh)) {
- if (is_string($fh)) {
- $fh = fopen($fh, "w");
- }
- static::$STDOUT = $fh;
- }
-
- return $orig;
- }
-}
diff --git a/fuel/core/classes/config.php b/fuel/core/classes/config.php
deleted file mode 100755
index 68440ab..0000000
--- a/fuel/core/classes/config.php
+++ /dev/null
@@ -1,231 +0,0 @@
-load($overwrite, ! $reload);
- }
- catch (\ConfigException $e)
- {
- $config = array();
- }
- $group = $group === true ? $file->group() : $group;
- }
-
- if ($group === null)
- {
- static::$items = $reload ? $config : ($overwrite ? array_merge(static::$items, $config) : \Arr::merge(static::$items, $config));
- static::$itemcache = array();
- }
- else
- {
- $group = ($group === true) ? $file : $group;
- if ( ! isset(static::$items[$group]) or $reload)
- {
- static::$items[$group] = array();
- }
- static::$items[$group] = $overwrite ? array_merge(static::$items[$group], $config) : \Arr::merge(static::$items[$group], $config);
- $group .= '.';
- foreach (static::$itemcache as $key => $value)
- {
- if (strpos($key, $group) === 0)
- {
- unset(static::$itemcache[$key]);
- }
- }
- }
-
- return $config;
- }
-
- /**
- * Save a config array to disc.
- *
- * @param string $file desired file name
- * @param string|array $config master config array key or config array
- * @return bool false when config is empty or invalid else \File::update result
- * @throws \FuelException
- */
- public static function save($file, $config)
- {
- if ( ! is_array($config))
- {
- if ( ! isset(static::$items[$config]))
- {
- return false;
- }
- $config = static::$items[$config];
- }
-
- $info = pathinfo($file);
- $type = 'php';
-
- if (isset($info['extension']))
- {
- $type = $info['extension'];
- // Keep extension when it's an absolute path, because the finder won't add it
- if ($file[0] !== '/' and $file[1] !== ':')
- {
- $file = substr($file, 0, -(strlen($type) + 1));
- }
- }
-
- $class = '\\Config_'.ucfirst($type);
-
- if ( ! class_exists($class))
- {
- throw new \FuelException(sprintf('Invalid config type "%s".', $type));
- }
-
- $driver = new $class($file);
-
- return $driver->save($config);
- }
-
- /**
- * Returns a (dot notated) config setting
- *
- * @param string $item name of the config item, can be dot notated
- * @param mixed $default the return value if the item isn't found
- * @return mixed the config setting or default if not found
- */
- public static function get($item, $default = null)
- {
- if (array_key_exists($item, static::$items))
- {
- return static::$items[$item];
- }
- elseif ( ! array_key_exists($item, static::$itemcache))
- {
- // cook up something unique
- $miss = new \stdClass();
-
- $val = \Arr::get(static::$items, $item, $miss);
-
- // so we can detect a miss here...
- if ($val === $miss)
- {
- return $default;
- }
-
- static::$itemcache[$item] = $val;
- }
-
- return \Fuel::value(static::$itemcache[$item]);
- }
-
- /**
- * Sets a (dot notated) config item
- *
- * @param string $item a (dot notated) config key
- * @param mixed $value the config value
- */
- public static function set($item, $value)
- {
- strpos($item, '.') === false or static::$itemcache[$item] = $value;
- \Arr::set(static::$items, $item, $value);
- }
-
- /**
- * Deletes a (dot notated) config item
- *
- * @param string $item a (dot notated) config key
- * @return array|bool the \Arr::delete result, success boolean or array of success booleans
- */
- public static function delete($item)
- {
- if (isset(static::$itemcache[$item]))
- {
- unset(static::$itemcache[$item]);
- }
- return \Arr::delete(static::$items, $item);
- }
-}
diff --git a/fuel/core/classes/config/db.php b/fuel/core/classes/config/db.php
deleted file mode 100755
index beef80d..0000000
--- a/fuel/core/classes/config/db.php
+++ /dev/null
@@ -1,158 +0,0 @@
-identifier = $identifier;
-
- $this->vars = array(
- 'APPPATH' => APPPATH,
- 'COREPATH' => COREPATH,
- 'PKGPATH' => PKGPATH,
- 'DOCROOT' => DOCROOT,
- ) + $vars;
-
- $this->database = \Config::get('config.database', null);
- $this->table = \Config::get('config.table_name', 'config');
- }
-
- /**
- * Loads the config file(s).
- *
- * @param bool $overwrite Whether to overwrite existing values
- * @param bool $cache This parameter will ignore in this implement.
- * @return array the config array
- * @throws \Database_Exception
- */
- public function load($overwrite = false, $cache = true)
- {
- $config = array();
-
- // try to retrieve the config from the database
- try
- {
- $result = \DB::select('config')->from($this->table)->where('identifier', '=', $this->identifier)->execute($this->database);
- }
- catch (Database_Exception $e)
- {
- // strip the actual query from the message
- $msg = $e->getMessage();
- $msg = substr($msg, 0, strlen($msg) - strlen(strrchr($msg, ':')));
-
- // and rethrow it
- throw new \Database_Exception($msg);
- }
-
- // did we succeed?
- if ($result->count())
- {
- empty($result[0]['config']) or $config = unserialize($this->parse_vars($result[0]['config']));
- }
-
- return $config;
- }
-
- /**
- * Gets the default group name.
- *
- * @return string
- */
- public function group()
- {
- return $this->identifier;
- }
-
- /**
- * Parses a string using all of the previously set variables. Allows you to
- * use something like %APPPATH% in non-PHP files.
- *
- * @param string $string String to parse
- * @return string
- */
- protected function parse_vars($string)
- {
- foreach ($this->vars as $var => $val)
- {
- $string = str_replace("%$var%", $val, $string);
- }
-
- return $string;
- }
-
- /**
- * Replaces FuelPHP's path constants to their string counterparts.
- *
- * @param array $array array to be prepped
- * @return array prepped array
- */
- protected function prep_vars(&$array)
- {
- static $replacements = false;
-
- if ($replacements === false)
- {
- foreach ($this->vars as $i => $v)
- {
- $replacements['#^('.preg_quote($v).'){1}(.*)?#'] = "%".$i."%$2";
- }
- }
-
- foreach ($array as $i => $value)
- {
- if (is_string($value))
- {
- $array[$i] = preg_replace(array_keys($replacements), array_values($replacements), $value);
- }
- elseif(is_array($value))
- {
- $this->prep_vars($array[$i]);
- }
- }
- }
-
- /**
- * Formats the output and saved it to disc.
- *
- * @param $contents $contents config array to save
- * @return bool DB result
- */
- public function save($contents)
- {
- // prep the contents
- $this->prep_vars($contents);
- $contents = serialize($contents);
-
- // update the config in the database
- $result = \DB::update($this->table)->set(array('config' => $contents, 'hash' => uniqid()))->where('identifier', '=', $this->identifier)->execute($this->database);
-
- // if there wasn't an update, do an insert
- if ($result === 0)
- {
- list($notused, $result) = \DB::insert($this->table)->set(array('identifier' => $this->identifier, 'config' => $contents, 'hash' => uniqid()))->execute($this->database);
- }
-
- return $result === 1;
- }
-}
diff --git a/fuel/core/classes/config/file.php b/fuel/core/classes/config/file.php
deleted file mode 100755
index 5dddf1d..0000000
--- a/fuel/core/classes/config/file.php
+++ /dev/null
@@ -1,227 +0,0 @@
-file = $file;
-
- $this->vars = array(
- 'APPPATH' => APPPATH,
- 'COREPATH' => COREPATH,
- 'PKGPATH' => PKGPATH,
- 'DOCROOT' => DOCROOT,
- ) + $vars;
- }
-
- /**
- * Loads the config file(s).
- *
- * @param bool $overwrite Whether to overwrite existing values
- * @param bool $cache Whether to cache this path or not
- * @return array the config array
- */
- public function load($overwrite = false, $cache = true)
- {
- $paths = $this->find_file($cache);
- $config = array();
-
- foreach ($paths as $path)
- {
- $config = $overwrite ?
- array_merge($config, $this->load_file($path)) :
- \Arr::merge($config, $this->load_file($path));
- }
-
- return $config;
- }
-
- /**
- * Gets the default group name.
- *
- * @return string
- */
- public function group()
- {
- return $this->file;
- }
-
- /**
- * Parses a string using all of the previously set variables. Allows you to
- * use something like %APPPATH% in non-PHP files.
- *
- * @param string $string String to parse
- * @return string
- */
- protected function parse_vars($string)
- {
- foreach ($this->vars as $var => $val)
- {
- $string = str_replace("%$var%", $val, $string);
- }
-
- return $string;
- }
-
- /**
- * Replaces FuelPHP's path constants to their string counterparts.
- *
- * @param array $array array to be prepped
- * @return array prepped array
- */
- protected function prep_vars(&$array)
- {
- static $replacements = false;
-
- if ($replacements === false)
- {
- foreach ($this->vars as $i => $v)
- {
- $replacements['#^('.preg_quote($v).'){1}(.*)?#'] = "%".$i."%$2";
- }
- }
-
- foreach ($array as $i => $value)
- {
- if (is_string($value))
- {
- $array[$i] = preg_replace(array_keys($replacements), array_values($replacements), $value);
- }
- elseif(is_array($value))
- {
- $this->prep_vars($array[$i]);
- }
- }
- }
-
- /**
- * Finds the given config files
- *
- * @param bool $cache Whether to cache this path or not
- * @return array
- * @throws \ConfigException
- */
- protected function find_file($cache = true)
- {
- if (($this->file[0] === '/' or (isset($this->file[1]) and $this->file[1] === ':')) and is_file($this->file))
- {
- $paths = array($this->file);
- }
- else
- {
- $paths = array_merge(
- \Finder::search('config/'.\Fuel::$env, $this->file, $this->ext, true, $cache),
- \Finder::search('config', $this->file, $this->ext, true, $cache)
- );
- }
-
- if (empty($paths))
- {
- throw new \ConfigException(sprintf('File "%s" does not exist.', $this->file));
- }
-
- return array_reverse($paths);
- }
-
- /**
- * Formats the output and saved it to disc.
- *
- * @param array $contents config array to save
- * @return bool \File::update result
- */
- public function save($contents)
- {
- // get the formatted output
- $output = $this->export_format($contents);
-
- if ( ! $output)
- {
- return false;
- }
-
- if ( ! $path = \Finder::search('config', $this->file, $this->ext))
- {
- if ($pos = strripos($this->file, '::'))
- {
- // get the namespace path
- if ($path = \Autoloader::namespace_path('\\'.ucfirst(substr($this->file, 0, $pos))))
- {
- // strip the namespace from the filename
- $this->file = substr($this->file, $pos+2);
-
- // strip the classes directory as we need the module root
- $path = substr($path, 0, -8).'config'.DS.$this->file.$this->ext;
- }
- else
- {
- // invalid namespace requested
- return false;
- }
- }
- }
-
- // absolute path requested?
- if ($this->file[0] === '/' or (isset($this->file[1]) and $this->file[1] === ':'))
- {
- $path = $this->file;
- }
-
- // make sure we have a fallback
- $path or $path = APPPATH.'config'.DS.$this->file.$this->ext;
-
- $path = pathinfo($path);
- if ( ! is_dir($path['dirname']))
- {
- mkdir($path['dirname'], 0777, true);
- }
-
- $return = \File::update($path['dirname'], $path['basename'], $output);
- if ($return)
- {
- try
- {
- \Config::load('file', true);
- chmod($path['dirname'].DS.$path['basename'], \Config::get('file.chmod.files', 0666));
- }
- catch (\PhpErrorException $e)
- {
- // if we get something else then a chmod error, bail out
- if (substr($e->getMessage(), 0, 8) !== 'chmod():')
- {
- throw new $e;
- }
- }
- }
- return $return;
- }
-
- /**
- * Must be implemented by child class. Gets called for each file to load.
- *
- * @param string $file the path to the file
- */
- abstract protected function load_file($file);
-
- /**
- * Must be implemented by child class. Gets called when saving a config file.
- *
- * @param array $contents config array to save
- * @return string formatted output
- */
- abstract protected function export_format($contents);
-}
diff --git a/fuel/core/classes/config/ini.php b/fuel/core/classes/config/ini.php
deleted file mode 100755
index e2b1004..0000000
--- a/fuel/core/classes/config/ini.php
+++ /dev/null
@@ -1,38 +0,0 @@
-parse_vars(file_get_contents($file));
- return parse_ini_string($contents, true);
- }
-
- /**
- * Returns the formatted config file contents.
- *
- * @param array $contents config array
- * @return string formatted config file contents
- * @throws \ConfigException
- */
- protected function export_format($contents)
- {
- throw new \ConfigException('Saving config to ini is not supported at this time');
- }
-}
diff --git a/fuel/core/classes/config/interface.php b/fuel/core/classes/config/interface.php
deleted file mode 100755
index 08dd0bc..0000000
--- a/fuel/core/classes/config/interface.php
+++ /dev/null
@@ -1,10 +0,0 @@
-parse_vars(file_get_contents($file));
- return json_decode($contents, true);
- }
-
- /**
- * Returns the formatted config file contents.
- *
- * @param array $contents config array
- * @return string formatted config file contents
- */
- protected function export_format($contents)
- {
- $this->prep_vars($contents);
- return \Format::forge()->to_json($contents, true);
- }
-}
diff --git a/fuel/core/classes/config/memcached.php b/fuel/core/classes/config/memcached.php
deleted file mode 100755
index 0bc8110..0000000
--- a/fuel/core/classes/config/memcached.php
+++ /dev/null
@@ -1,174 +0,0 @@
- 'config',
- 'servers' => array(
- array('host' => '127.0.0.1', 'port' => 11211, 'weight' => 100),
- ),
- );
-
- /**
- * @var \Memcached storage for the memcached object
- */
- protected static $memcached = false;
-
- /**
- * driver initialisation
- *
- * @throws \FuelException
- */
- public static function _init()
- {
- static::$config = array_merge(static::$config, \Config::get('config.memcached', array()));
-
- if (static::$memcached === false)
- {
- // do we have the PHP memcached extension available
- if ( ! class_exists('Memcached') )
- {
- throw new \FuelException('Memcached config storage is required, but your PHP installation doesn\'t have the Memcached extension loaded.');
- }
-
- // instantiate the memcached object
- static::$memcached = new \Memcached();
-
- // add the configured servers
- static::$memcached->addServers(static::$config['servers']);
-
- // check if we can connect to all the server(s)
- $added = static::$memcached->getStats();
- foreach (static::$config['servers'] as $server)
- {
- $server = $server['host'].':'.$server['port'];
- if ( ! isset($added[$server]) or $added[$server]['pid'] == -1)
- {
- throw new \FuelException('Memcached config storage is required, but there is no connection possible. Check your configuration.');
- }
- }
- }
- }
-
- // --------------------------------------------------------------------
-
- protected $identifier;
-
- protected $ext = '.mem';
-
- protected $vars = array();
-
- /**
- * Sets up the file to be parsed and variables
- *
- * @param string $identifier Config identifier name
- * @param array $vars Variables to parse in the data retrieved
- */
- public function __construct($identifier = null, $vars = array())
- {
- $this->identifier = $identifier;
-
- $this->vars = array(
- 'APPPATH' => APPPATH,
- 'COREPATH' => COREPATH,
- 'PKGPATH' => PKGPATH,
- 'DOCROOT' => DOCROOT,
- ) + $vars;
- }
-
- /**
- * Loads the config file(s).
- *
- * @param bool $overwrite Whether to overwrite existing values
- * @param bool $cache This parameter will ignore in this implement.
- * @return array the config array
- */
- public function load($overwrite = false, $cache = true)
- {
- // fetch the config data from the Memcached server
- $result = static::$memcached->get(static::$config['identifier'].'_'.$this->identifier);
-
- return $result === false ? array() : $result;
- }
-
- /**
- * Gets the default group name.
- *
- * @return string
- */
- public function group()
- {
- return $this->identifier;
- }
-
- /**
- * Parses a string using all of the previously set variables. Allows you to
- * use something like %APPPATH% in non-PHP files.
- *
- * @param string $string String to parse
- * @return string
- */
- protected function parse_vars($string)
- {
- foreach ($this->vars as $var => $val)
- {
- $string = str_replace("%$var%", $val, $string);
- }
-
- return $string;
- }
-
- /**
- * Replaces FuelPHP's path constants to their string counterparts.
- *
- * @param array $array array to be prepped
- * @return array prepped array
- */
- protected function prep_vars(&$array)
- {
- static $replacements = false;
-
- if ($replacements === false)
- {
- foreach ($this->vars as $i => $v)
- {
- $replacements['#^('.preg_quote($v).'){1}(.*)?#'] = "%".$i."%$2";
- }
- }
-
- foreach ($array as $i => $value)
- {
- if (is_string($value))
- {
- $array[$i] = preg_replace(array_keys($replacements), array_values($replacements), $value);
- }
- elseif(is_array($value))
- {
- $this->prep_vars($array[$i]);
- }
- }
- }
-
- /**
- * Formats the output and saved it to disc.
- *
- * @param $contents $contents config array to save
- * @throws \FuelException
- */
- public function save($contents)
- {
- // write it to the memcached server
- if (static::$memcached->set(static::$config['identifier'].'_'.$this->identifier, $contents, 0) === false)
- {
- throw new \FuelException('Memcached returned error code "'.static::$memcached->getResultCode().'" on write. Check your configuration.');
- }
- }
-}
diff --git a/fuel/core/classes/config/php.php b/fuel/core/classes/config/php.php
deleted file mode 100755
index 51c8ab0..0000000
--- a/fuel/core/classes/config/php.php
+++ /dev/null
@@ -1,105 +0,0 @@
-= 50500 and function_exists('opcache_invalidate'));
-
- // do we have APC active?
- static::$uses_apc = function_exists('apc_compile_file');
-
- // determine if we have an opcode cache active
- static::$flush_needed = static::$uses_opcache or static::$uses_apc;
- }
-
- /**
- * @var string the extension used by this config file parser
- */
- protected $ext = '.php';
-
- /**
- * Formats the output and saved it to disk.
- *
- * @param $contents $contents config array to save
- * @return bool \File::update result
- */
- public function save($contents)
- {
- // store the current filename
- $file = $this->file;
-
- // save it
- $return = parent::save($contents);
-
- // existing file? saved? and do we need to flush the opcode cache?
- if ($file == $this->file and $return and static::$flush_needed)
- {
- if ($this->file[0] !== '/' and ( ! isset($this->file[1]) or $this->file[1] !== ':'))
- {
- // locate the file
- $file = \Finder::search('config', $this->file, $this->ext);
- }
-
- // make sure we have a fallback
- $file or $file = APPPATH.'config'.DS.$this->file.$this->ext;
-
- // flush the opcode caches that are active
- static::$uses_opcache and opcache_invalidate($file, true);
- static::$uses_apc and apc_compile_file($file);
- }
-
- return $return;
- }
-
- /**
- * Loads in the given file and parses it.
- *
- * @param string $file File to load
- * @return array
- */
- protected function load_file($file)
- {
- return \Fuel::load($file);
- }
-
- /**
- * Returns the formatted config file contents.
- *
- * @param array $contents config array
- * @return string formatted config file contents
- */
- protected function export_format($contents)
- {
- $output = <<'; - - $count = count($arguments); - for ($i = 1; $i <= $count; $i++) - { - echo 'Variable #'.$i.':'.PHP_EOL; - echo static::format('', $arguments[$i - 1]); - echo PHP_EOL.PHP_EOL; - } - - echo ""; - echo "
'; - $i = 0; - foreach ($arguments as $argument) - { - echo ''.$label.' #'.(++$i).' of '.$total_arguments.':"; - echo "
'; - echo static::format('...', $argument); - echo '
'; - } - - echo "
', '
', '<?php ', "\n");
- $replace_with = array('', '', '', '');
-
- foreach ($debug_lines as & $line)
- {
- $line = str_replace($to_replace, $replace_with, highlight_string(' $frame)
- {
- $line = "#$i\t";
-
- if ( ! isset($frame['file']))
- {
- $line .= "[internal function]";
- }
- else
- {
- $line .= $frame['file'] . ":" . $frame['line'];
- }
-
- $line .= "\t";
-
- if (isset($frame['function']))
- {
- if (isset($frame['class']))
- {
- $line .= $frame['class'] . '::';
- }
-
- $line .= $frame['function'] . "()";
- }
-
- $str .= $line . "\n";
-
- }
-
- return $str;
- }
- else
- {
- return static::dump($trace);
- }
- }
-
- /**
- * Prints a list of all currently declared classes.
- *
- * @access public
- * @static
- */
- public static function classes()
- {
- return static::dump(get_declared_classes());
- }
-
- /**
- * Prints a list of all currently declared interfaces (PHP5 only).
- *
- * @access public
- * @static
- */
- public static function interfaces()
- {
- return static::dump(get_declared_interfaces());
- }
-
- /**
- * Prints a list of all currently included (or required) files.
- *
- * @access public
- * @static
- */
- public static function includes()
- {
- return static::dump(get_included_files());
- }
-
- /**
- * Prints a list of all currently declared functions.
- *
- * @access public
- * @static
- */
- public static function functions()
- {
- return static::dump(get_defined_functions());
- }
-
- /**
- * Prints a list of all currently declared constants.
- *
- * @access public
- * @static
- */
- public static function constants()
- {
- return static::dump(get_defined_constants());
- }
-
- /**
- * Prints a list of all currently loaded PHP extensions.
- *
- * @access public
- * @static
- */
- public static function extensions()
- {
- return static::dump(get_loaded_extensions());
- }
-
- /**
- * Prints a list of all HTTP request headers.
- *
- * @access public
- * @static
- */
- public static function headers()
- {
- // get the current request headers and dump them
- return static::dump(\Input::headers());
- }
-
- /**
- * Prints a list of the configuration settings read from php.ini
- *
- * @access public
- * @static
- */
- public static function phpini()
- {
- if ( ! is_readable(get_cfg_var('cfg_file_path')))
- {
- return false;
- }
-
- // render it
- return static::dump(parse_ini_file(get_cfg_var('cfg_file_path'), true));
- }
-
- /**
- * Benchmark anything that is callable
- *
- * @access public
- * @param callable $callable
- * @param array $params
- * @static
- * @return array
- */
- public static function benchmark($callable, array $params = array())
- {
- // get the before-benchmark time
- if (function_exists('getrusage'))
- {
- $dat = getrusage();
- $utime_before = $dat['ru_utime.tv_sec'] + round($dat['ru_utime.tv_usec']/1000000, 4);
- $stime_before = $dat['ru_stime.tv_sec'] + round($dat['ru_stime.tv_usec']/1000000, 4);
- }
- else
- {
- list($usec, $sec) = explode(" ", microtime());
- $utime_before = ((float) $usec + (float) $sec);
- $stime_before = 0;
- }
-
- // call the function to be benchmarked
- $result = is_callable($callable) ? call_fuel_func_array($callable, $params) : null;
-
- // get the after-benchmark time
- if (function_exists('getrusage'))
- {
- $dat = getrusage();
- $utime_after = $dat['ru_utime.tv_sec'] + round($dat['ru_utime.tv_usec']/1000000, 4);
- $stime_after = $dat['ru_stime.tv_sec'] + round($dat['ru_stime.tv_usec']/1000000, 4);
- }
- else
- {
- list($usec, $sec) = explode(" ", microtime());
- $utime_after = ((float) $usec + (float) $sec);
- $stime_after = 0;
- }
-
- return array(
- 'user' => sprintf('%1.6f', $utime_after - $utime_before),
- 'system' => sprintf('%1.6f', $stime_after - $stime_before),
- 'result' => $result,
- );
- }
-
-}
diff --git a/fuel/core/classes/errorhandler.php b/fuel/core/classes/errorhandler.php
deleted file mode 100755
index d4f6547..0000000
--- a/fuel/core/classes/errorhandler.php
+++ /dev/null
@@ -1,325 +0,0 @@
-code.' - '.$this->message.' in '.$this->file.' on line '.$this->line);
-
- if (\Fuel::$env != \Fuel::PRODUCTION and ($this->code & error_reporting()) == $this->code)
- {
- static::$count++;
- \Errorhandler::exception_handler(new \ErrorException($this->message, $this->code, 0, $this->file, $this->line));
- }
- }
- elseif (\Fuel::$env != \Fuel::PRODUCTION
- and static::$count == (\Config::get('errors.throttle', 10) + 1)
- and ($this->severity & error_reporting()) == $this->severity)
- {
- static::$count++;
- \Errorhandler::notice('Error throttling threshold was reached, no more full error reports are shown.', true);
- }
- }
-}
-
-/**
- *
- */
-class Errorhandler
-{
- public static $loglevel = \Fuel::L_ERROR;
-
- public static $levels = array(
- 0 => 'Error',
- E_ERROR => 'Fatal Error',
- E_WARNING => 'Warning',
- E_PARSE => 'Parsing Error',
- E_NOTICE => 'Notice',
- E_CORE_ERROR => 'Core Error',
- E_CORE_WARNING => 'Core Warning',
- E_COMPILE_ERROR => 'Compile Error',
- E_COMPILE_WARNING => 'Compile Warning',
- E_USER_ERROR => 'User Error',
- E_USER_WARNING => 'User Warning',
- E_USER_NOTICE => 'User Notice',
- E_STRICT => 'Runtime Notice',
- E_RECOVERABLE_ERROR => 'Runtime Recoverable error',
- E_DEPRECATED => 'Runtime Deprecated code usage',
- E_USER_DEPRECATED => 'User Deprecated code usage',
- );
-
- public static $fatal_levels = array(E_PARSE, E_ERROR, E_USER_ERROR, E_COMPILE_ERROR);
-
- public static $non_fatal_cache = array();
-
- /**
- * Native PHP shutdown handler
- *
- * @return string
- */
- public static function shutdown_handler()
- {
- $last_error = error_get_last();
-
- // Only show valid fatal errors
- if ($last_error AND in_array($last_error['type'], static::$fatal_levels))
- {
- $severity = static::$levels[$last_error['type']];
- logger(static::$loglevel, $severity.' - '.$last_error['message'].' in '.$last_error['file'].' on line '.$last_error['line']);
-
- $error = new \ErrorException($last_error['message'], $last_error['type'], 0, $last_error['file'], $last_error['line']);
- if (\Fuel::$env != \Fuel::PRODUCTION)
- {
- static::show_php_error($error);
- }
- else
- {
- static::show_production_error($error);
- }
-
- exit(1);
- }
- }
-
- /**
- * PHP Exception handler
- *
- * @param Exception $e the exception
- * @return bool
- */
- public static function exception_handler($e)
- {
- // make sure we've got something useful passed
- if ($e instanceOf \Exception or (PHP_VERSION_ID >= 70000 and $e instanceOf \Error))
- {
- if (method_exists($e, 'handle'))
- {
- return $e->handle();
- }
-
- $severity = ( ! isset(static::$levels[$e->getCode()])) ? $e->getCode() : static::$levels[$e->getCode()];
- logger(static::$loglevel, $severity.' - '.$e->getMessage().' in '.$e->getFile().' on line '.$e->getLine());
-
- if (\Fuel::$env != \Fuel::PRODUCTION)
- {
- static::show_php_error($e);
- }
- else
- {
- static::show_production_error($e);
- }
- }
- else
- {
- die('Something was passed to the Exception handler that was neither an Error or an Exception !!!');
- }
-
- return true;
- }
-
- /**
- * PHP Error handler
- *
- * @param int $severity the severity code
- * @param string $message the error message
- * @param string $filepath the path to the file throwing the error
- * @param int $line the line number of the error
- * @return bool whether to continue with execution
- */
- public static function error_handler($severity, $message, $filepath, $line)
- {
- // don't do anything if error reporting is disabled
- if (error_reporting() !== 0)
- {
- $fatal = (bool) ( ! in_array($severity, \Config::get('errors.continue_on', array())));
-
- if ($fatal)
- {
- throw new \PhpErrorException($message, $severity, 0, $filepath, $line);
- }
- else
- {
- // non-fatal, recover from the error
- $e = new \PhpErrorException($message, $severity, 0, $filepath, $line);
- $e->recover();
- }
- }
-
- return true;
- }
-
- /**
- * Shows a small notice error, only when not in production or when forced.
- * This is used by several libraries to notify the developer of certain things.
- *
- * @param string $msg the message to display
- * @param bool $always_show whether to force display the notice or not
- * @return void
- */
- public static function notice($msg, $always_show = false)
- {
- $trace = array_merge(array('file' => '(unknown)', 'line' => '(unknown)'), \Arr::get(debug_backtrace(), 1));
- logger(\Fuel::L_DEBUG, 'Notice - '.$msg.' in '.$trace['file'].' on line '.$trace['line']);
-
- if (\Fuel::$is_test or ( ! $always_show and (\Fuel::$env == \Fuel::PRODUCTION or \Config::get('errors.notices', true) === false)))
- {
- return;
- }
-
- $data['message'] = $msg;
- $data['type'] = 'Notice';
- $data['filepath'] = \Fuel::clean_path($trace['file']);
- $data['line'] = $trace['line'];
- $data['function'] = $trace['function'];
-
- echo \View::forge('errors'.DS.'php_short', $data, false);
- }
-
- /**
- * Shows an error. It will stop script execution if the error code is not
- * in the errors.continue_on whitelist.
- *
- * @param Exception $e the exception to show
- * @return void
- */
- protected static function show_php_error($e)
- {
- $fatal = (bool) ( ! in_array($e->getCode(), \Config::get('errors.continue_on', array())));
- $data = static::prepare_exception($e, $fatal);
-
- if ($fatal)
- {
- $data['contents'] = ob_get_contents();
- while (ob_get_level() > 0)
- {
- ob_end_clean();
- }
- ob_start(\Config::get('ob_callback', null));
- }
- else
- {
- static::$non_fatal_cache[] = $data;
- }
-
- if (\Fuel::$is_cli)
- {
- \Cli::write(\Cli::color($data['severity'].' - '.$data['message'].' in '.\Fuel::clean_path($data['filepath']).' on line '.$data['error_line'], 'red'));
- if (\Config::get('cli_backtrace'))
- {
- \Cli::write('Stack trace:');
- \Cli::write(\Debug::backtrace($e->getTrace()));
- }
- return;
- }
-
- if ($fatal)
- {
- if ( ! headers_sent())
- {
- $protocol = \Input::server('SERVER_PROTOCOL') ? \Input::server('SERVER_PROTOCOL') : 'HTTP/1.1';
- header($protocol.' 500 Internal Server Error');
- }
-
- $data['non_fatal'] = static::$non_fatal_cache;
-
- try
- {
- exit(\View::forge('errors'.DS.'php_fatal_error', $data, false));
- }
- catch (\FuelException $view_exception)
- {
- exit($data['severity'].' - '.$data['message'].' in '.\Fuel::clean_path($data['filepath']).' on line '.$data['error_line']);
- }
- }
-
- try
- {
- echo \View::forge('errors'.DS.'php_error', $data, false);
- }
- catch (\FuelException $e)
- {
- echo $e->getMessage().'