system\classes\Kohana\Core.php 核心文件

View Code
   1 <?php defined('SYSPATH') OR die('No direct script access.');

   2 /**

   3  * Contains the most low-level helpers methods in Kohana:

   4  *

   5  * - Environment initialization

   6  * - Locating files within the cascading filesystem

   7  * - Auto-loading and transparent extension of classes

   8  * - Variable and path debugging

   9  *

  10  * @package    Kohana

  11  * @category   Base

  12  * @author     Kohana Team

  13  * @copyright  (c) 2008-2012 Kohana Team

  14  * @license    http://kohanaframework.org/license

  15  */

  16 class Kohana_Core {

  17 

  18     // Release version and codename

  19     const VERSION  = '3.3.0';

  20     const CODENAME = 'badius';

  21 

  22     // Common environment type constants for consistency and convenience

  23     const PRODUCTION  = 10;

  24     const STAGING     = 20;

  25     const TESTING     = 30;

  26     const DEVELOPMENT = 40;

  27 

  28     // Security check that is added to all generated PHP files

  29     const FILE_SECURITY = '<?php defined(\'SYSPATH\') OR die(\'No direct script access.\');';

  30 

  31     // Format of cache files: header, cache name, and data

  32     const FILE_CACHE = ":header \n\n// :name\n\n:data\n";

  33 

  34     /**

  35      * @var  string  Current environment name

  36      */

  37     public static $environment = Kohana::DEVELOPMENT;

  38 

  39     /**

  40      * @var  boolean  True if Kohana is running on windows

  41      */

  42     public static $is_windows = FALSE;

  43 

  44     /**

  45      * @var  boolean  True if [magic quotes](http://php.net/manual/en/security.magicquotes.php) is enabled.

  46      */

  47     public static $magic_quotes = FALSE;

  48 

  49     /**

  50      * @var  boolean  TRUE if PHP safe mode is on

  51      */

  52     public static $safe_mode = FALSE;

  53 

  54     /**

  55      * @var  string

  56      */

  57     public static $content_type = 'text/html';

  58 

  59     /**

  60      * @var  string  character set of input and output

  61      */

  62     public static $charset = 'utf-8';

  63 

  64     /**

  65      * @var  string  the name of the server Kohana is hosted upon

  66      */

  67     public static $server_name = '';

  68 

  69     /**

  70      * @var  array   list of valid host names for this instance

  71      */

  72     public static $hostnames = array();

  73 

  74     /**

  75      * @var  string  base URL to the application

  76      */

  77     public static $base_url = '/';

  78 

  79     /**

  80      * @var  string  Application index file, added to links generated by Kohana. Set by [Kohana::init]

  81      */

  82     public static $index_file = 'index.php';

  83 

  84     /**

  85      * @var  string  Cache directory, used by [Kohana::cache]. Set by [Kohana::init]

  86      */

  87     public static $cache_dir;

  88 

  89     /**

  90      * @var  integer  Default lifetime for caching, in seconds, used by [Kohana::cache]. Set by [Kohana::init]

  91      */

  92     public static $cache_life = 60;

  93 

  94     /**

  95      * @var  boolean  Whether to use internal caching for [Kohana::find_file], does not apply to [Kohana::cache]. Set by [Kohana::init]

  96      */

  97     public static $caching = FALSE;

  98 

  99     /**

 100      * @var  boolean  Whether to enable [profiling](kohana/profiling). Set by [Kohana::init]

 101      */

 102     public static $profiling = TRUE;

 103 

 104     /**

 105      * @var  boolean  Enable Kohana catching and displaying PHP errors and exceptions. Set by [Kohana::init]

 106      */

 107     public static $errors = TRUE;

 108 

 109     /**

 110      * @var  array  Types of errors to display at shutdown

 111      */

 112     public static $shutdown_errors = array(E_PARSE, E_ERROR, E_USER_ERROR);

 113 

 114     /**

 115      * @var  boolean  set the X-Powered-By header

 116      */

 117     public static $expose = FALSE;

 118 

 119     /**

 120      * @var  Log  logging object

 121      */

 122     public static $log;

 123 

 124     /**

 125      * @var  Config  config object

 126      */

 127     public static $config;

 128 

 129     /**

 130      * @var  boolean  Has [Kohana::init] been called?

 131      */

 132     protected static $_init = FALSE;

 133 

 134     /**

 135      * @var  array   Currently active modules

 136      */

 137     protected static $_modules = array();

 138 

 139     /**

 140      * @var  array   Include paths that are used to find files

 141      */

 142     protected static $_paths = array(APPPATH, SYSPATH);

 143 

 144     /**

 145      * @var  array   File path cache, used when caching is true in [Kohana::init]

 146      */

 147     protected static $_files = array();

 148 

 149     /**

 150      * @var  boolean  Has the file path cache changed during this execution?  Used internally when when caching is true in [Kohana::init]

 151      */

 152     protected static $_files_changed = FALSE;

 153 

 154     /**

 155      * Initializes the environment:

 156      *

 157      * - Disables register_globals and magic_quotes_gpc

 158      * - Determines the current environment

 159      * - Set global settings

 160      * - Sanitizes GET, POST, and COOKIE variables

 161      * - Converts GET, POST, and COOKIE variables to the global character set

 162      *

 163      * The following settings can be set:

 164      *

 165      * Type      | Setting    | Description                                    | Default Value

 166      * ----------|------------|------------------------------------------------|---------------

 167      * `string`  | base_url   | The base URL for your application.  This should be the *relative* path from your DOCROOT to your `index.php` file, in other words, if Kohana is in a subfolder, set this to the subfolder name, otherwise leave it as the default.  **The leading slash is required**, trailing slash is optional.   | `"/"`

 168      * `string`  | index_file | The name of the [front controller](http://en.wikipedia.org/wiki/Front_Controller_pattern).  This is used by Kohana to generate relative urls like [HTML::anchor()] and [URL::base()]. This is usually `index.php`.  To [remove index.php from your urls](tutorials/clean-urls), set this to `FALSE`. | `"index.php"`

 169      * `string`  | charset    | Character set used for all input and output    | `"utf-8"`

 170      * `string`  | cache_dir  | Kohana's cache directory.  Used by [Kohana::cache] for simple internal caching, like [Fragments](kohana/fragments) and **\[caching database queries](this should link somewhere)**.  This has nothing to do with the [Cache module](cache). | `APPPATH."cache"`

 171      * `integer` | cache_life | Lifetime, in seconds, of items cached by [Kohana::cache]         | `60`

 172      * `boolean` | errors     | Should Kohana catch PHP errors and uncaught Exceptions and show the `error_view`. See [Error Handling](kohana/errors) for more info. <br /> <br /> Recommended setting: `TRUE` while developing, `FALSE` on production servers. | `TRUE`

 173      * `boolean` | profile    | Whether to enable the [Profiler](kohana/profiling). <br /> <br />Recommended setting: `TRUE` while developing, `FALSE` on production servers. | `TRUE`

 174      * `boolean` | caching    | Cache file locations to speed up [Kohana::find_file].  This has nothing to do with [Kohana::cache], [Fragments](kohana/fragments) or the [Cache module](cache).  <br /> <br />  Recommended setting: `FALSE` while developing, `TRUE` on production servers. | `FALSE`

 175      * `boolean` | expose     | Set the X-Powered-By header

 176      *

 177      * @throws  Kohana_Exception

 178      * @param   array   $settings   Array of settings.  See above.

 179      * @return  void

 180      * @uses    Kohana::globals

 181      * @uses    Kohana::sanitize

 182      * @uses    Kohana::cache

 183      * @uses    Profiler

 184      */

 185     public static function init(array $settings = NULL)

 186     {

 187         if (Kohana::$_init)

 188         {

 189             // Do not allow execution twice

 190             return;

 191         }

 192 

 193         // Kohana is now initialized

 194         Kohana::$_init = TRUE;

 195 

 196         if (isset($settings['profile']))

 197         {

 198             // Enable profiling

 199             Kohana::$profiling = (bool) $settings['profile'];

 200         }

 201 

 202         // Start an output buffer

 203         ob_start();

 204 

 205         if (isset($settings['errors']))

 206         {

 207             // Enable error handling

 208             Kohana::$errors = (bool) $settings['errors'];

 209         }

 210 

 211         if (Kohana::$errors === TRUE)

 212         {

 213             // Enable Kohana exception handling, adds stack traces and error source.

 214             set_exception_handler(array('Kohana_Exception', 'handler'));

 215 

 216             // Enable Kohana error handling, converts all PHP errors to exceptions.

 217             set_error_handler(array('Kohana', 'error_handler'));

 218         }

 219 

 220         /**

 221          * Enable xdebug parameter collection in development mode to improve fatal stack traces.

 222          */

 223         if (Kohana::$environment == Kohana::DEVELOPMENT AND extension_loaded('xdebug'))

 224         {

 225             ini_set('xdebug.collect_params', 3);

 226         }

 227 

 228         // Enable the Kohana shutdown handler, which catches E_FATAL errors.

 229         register_shutdown_function(array('Kohana', 'shutdown_handler'));

 230 

 231         if (ini_get('register_globals'))

 232         {

 233             // Reverse the effects of register_globals

 234             Kohana::globals();

 235         }

 236 

 237         if (isset($settings['expose']))

 238         {

 239             Kohana::$expose = (bool) $settings['expose'];

 240         }

 241 

 242         // Determine if we are running in a Windows environment

 243         Kohana::$is_windows = (DIRECTORY_SEPARATOR === '\\');

 244 

 245         // Determine if we are running in safe mode

 246         Kohana::$safe_mode = (bool) ini_get('safe_mode');

 247 

 248         if (isset($settings['cache_dir']))

 249         {

 250             if ( ! is_dir($settings['cache_dir']))

 251             {

 252                 try

 253                 {

 254                     // Create the cache directory

 255                     mkdir($settings['cache_dir'], 0755, TRUE);

 256 

 257                     // Set permissions (must be manually set to fix umask issues)

 258                     chmod($settings['cache_dir'], 0755);

 259                 }

 260                 catch (Exception $e)

 261                 {

 262                     throw new Kohana_Exception('Could not create cache directory :dir',

 263                         array(':dir' => Debug::path($settings['cache_dir'])));

 264                 }

 265             }

 266 

 267             // Set the cache directory path

 268             Kohana::$cache_dir = realpath($settings['cache_dir']);

 269         }

 270         else

 271         {

 272             // Use the default cache directory

 273             Kohana::$cache_dir = APPPATH.'cache';

 274         }

 275 

 276         if ( ! is_writable(Kohana::$cache_dir))

 277         {

 278             throw new Kohana_Exception('Directory :dir must be writable',

 279                 array(':dir' => Debug::path(Kohana::$cache_dir)));

 280         }

 281 

 282         if (isset($settings['cache_life']))

 283         {

 284             // Set the default cache lifetime

 285             Kohana::$cache_life = (int) $settings['cache_life'];

 286         }

 287 

 288         if (isset($settings['caching']))

 289         {

 290             // Enable or disable internal caching

 291             Kohana::$caching = (bool) $settings['caching'];

 292         }

 293 

 294         if (Kohana::$caching === TRUE)

 295         {

 296             // Load the file path cache

 297             Kohana::$_files = Kohana::cache('Kohana::find_file()');

 298         }

 299 

 300         if (isset($settings['charset']))

 301         {

 302             // Set the system character set

 303             Kohana::$charset = strtolower($settings['charset']);

 304         }

 305 

 306         if (function_exists('mb_internal_encoding'))

 307         {

 308             // Set the MB extension encoding to the same character set

 309             mb_internal_encoding(Kohana::$charset);

 310         }

 311 

 312         if (isset($settings['base_url']))

 313         {

 314             // Set the base URL

 315             Kohana::$base_url = rtrim($settings['base_url'], '/').'/';

 316         }

 317 

 318         if (isset($settings['index_file']))

 319         {

 320             // Set the index file

 321             Kohana::$index_file = trim($settings['index_file'], '/');

 322         }

 323 

 324         // Determine if the extremely evil magic quotes are enabled

 325         Kohana::$magic_quotes = (version_compare(PHP_VERSION, '5.4') < 0 AND get_magic_quotes_gpc());

 326 

 327         // Sanitize all request variables

 328         $_GET    = Kohana::sanitize($_GET);

 329         $_POST   = Kohana::sanitize($_POST);

 330         $_COOKIE = Kohana::sanitize($_COOKIE);

 331 

 332         // Load the logger if one doesn't already exist

 333         if ( ! Kohana::$log instanceof Log)

 334         {

 335             Kohana::$log = Log::instance();

 336         }

 337 

 338         // Load the config if one doesn't already exist

 339         if ( ! Kohana::$config instanceof Config)

 340         {

 341             Kohana::$config = new Config;

 342         }

 343     }

 344 

 345     /**

 346      * Cleans up the environment:

 347      *

 348      * - Restore the previous error and exception handlers

 349      * - Destroy the Kohana::$log and Kohana::$config objects

 350      *

 351      * @return  void

 352      */

 353     public static function deinit()

 354     {

 355         if (Kohana::$_init)

 356         {

 357             // Removed the autoloader

 358             spl_autoload_unregister(array('Kohana', 'auto_load'));

 359 

 360             if (Kohana::$errors)

 361             {

 362                 // Go back to the previous error handler

 363                 restore_error_handler();

 364 

 365                 // Go back to the previous exception handler

 366                 restore_exception_handler();

 367             }

 368 

 369             // Destroy objects created by init

 370             Kohana::$log = Kohana::$config = NULL;

 371 

 372             // Reset internal storage

 373             Kohana::$_modules = Kohana::$_files = array();

 374             Kohana::$_paths   = array(APPPATH, SYSPATH);

 375 

 376             // Reset file cache status

 377             Kohana::$_files_changed = FALSE;

 378 

 379             // Kohana is no longer initialized

 380             Kohana::$_init = FALSE;

 381         }

 382     }

 383 

 384     /**

 385      * Reverts the effects of the `register_globals` PHP setting by unsetting

 386      * all global varibles except for the default super globals (GPCS, etc),

 387      * which is a [potential security hole.][ref-wikibooks]

 388      *

 389      * This is called automatically by [Kohana::init] if `register_globals` is

 390      * on.

 391      *

 392      *

 393      * [ref-wikibooks]: http://en.wikibooks.org/wiki/PHP_Programming/Register_Globals

 394      *

 395      * @return  void

 396      */

 397     public static function globals()

 398     {

 399         if (isset($_REQUEST['GLOBALS']) OR isset($_FILES['GLOBALS']))

 400         {

 401             // Prevent malicious GLOBALS overload attack

 402             echo "Global variable overload attack detected! Request aborted.\n";

 403 

 404             // Exit with an error status

 405             exit(1);

 406         }

 407 

 408         // Get the variable names of all globals

 409         $global_variables = array_keys($GLOBALS);

 410 

 411         // Remove the standard global variables from the list

 412         $global_variables = array_diff($global_variables, array(

 413             '_COOKIE',

 414             '_ENV',

 415             '_GET',

 416             '_FILES',

 417             '_POST',

 418             '_REQUEST',

 419             '_SERVER',

 420             '_SESSION',

 421             'GLOBALS',

 422         ));

 423 

 424         foreach ($global_variables as $name)

 425         {

 426             // Unset the global variable, effectively disabling register_globals

 427             unset($GLOBALS[$name]);

 428         }

 429     }

 430 

 431     /**

 432      * Recursively sanitizes an input variable:

 433      *

 434      * - Strips slashes if magic quotes are enabled

 435      * - Normalizes all newlines to LF

 436      *

 437      * @param   mixed   $value  any variable

 438      * @return  mixed   sanitized variable

 439      */

 440     public static function sanitize($value)

 441     {

 442         if (is_array($value) OR is_object($value))

 443         {

 444             foreach ($value as $key => $val)

 445             {

 446                 // Recursively clean each value

 447                 $value[$key] = Kohana::sanitize($val);

 448             }

 449         }

 450         elseif (is_string($value))

 451         {

 452             if (Kohana::$magic_quotes === TRUE)

 453             {

 454                 // Remove slashes added by magic quotes

 455                 $value = stripslashes($value);

 456             }

 457 

 458             if (strpos($value, "\r") !== FALSE)

 459             {

 460                 // Standardize newlines

 461                 $value = str_replace(array("\r\n", "\r"), "\n", $value);

 462             }

 463         }

 464 

 465         return $value;

 466     }

 467 

 468     /**

 469      * Provides auto-loading support of classes that follow Kohana's [class

 470      * naming conventions](kohana/conventions#class-names-and-file-location).

 471      * See [Loading Classes](kohana/autoloading) for more information.

 472      *

 473      *     // Loads classes/My/Class/Name.php

 474      *     Kohana::auto_load('My_Class_Name');

 475      *

 476      * or with a custom directory:

 477      *

 478      *     // Loads vendor/My/Class/Name.php

 479      *     Kohana::auto_load('My_Class_Name', 'vendor');

 480      *

 481      * You should never have to call this function, as simply calling a class

 482      * will cause it to be called.

 483      *

 484      * This function must be enabled as an autoloader in the bootstrap:

 485      *

 486      *     spl_autoload_register(array('Kohana', 'auto_load'));

 487      *

 488      * @param   string  $class      Class name

 489      * @param   string  $directory  Directory to load from

 490      * @return  boolean

 491      */

 492     public static function auto_load($class, $directory = 'classes')

 493     {

 494         // Transform the class name according to PSR-0

 495         $class     = ltrim($class, '\\');

 496         $file      = '';

 497         $namespace = '';

 498 

 499         if ($last_namespace_position = strripos($class, '\\'))

 500         {

 501             $namespace = substr($class, 0, $last_namespace_position);

 502             $class     = substr($class, $last_namespace_position + 1);

 503             $file      = str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR;

 504         }

 505 

 506         $file .= str_replace('_', DIRECTORY_SEPARATOR, $class);

 507 

 508         if ($path = Kohana::find_file($directory, $file))

 509         {

 510             // Load the class file

 511             require $path;

 512 

 513             // Class has been found

 514             return TRUE;

 515         }

 516 

 517         // Class is not in the filesystem

 518         return FALSE;

 519     }

 520 

 521     /**

 522      * Provides auto-loading support of classes that follow Kohana's old class

 523      * naming conventions.

 524      * 

 525      * This is included for compatibility purposes with older modules.

 526      *

 527      * @param   string  $class      Class name

 528      * @param   string  $directory  Directory to load from

 529      * @return  boolean

 530      */

 531     public static function auto_load_lowercase($class, $directory = 'classes')

 532     {

 533         // Transform the class name into a path

 534         $file = str_replace('_', DIRECTORY_SEPARATOR, strtolower($class));

 535 

 536         if ($path = Kohana::find_file($directory, $file))

 537         {

 538             // Load the class file

 539             require $path;

 540 

 541             // Class has been found

 542             return TRUE;

 543         }

 544 

 545         // Class is not in the filesystem

 546         return FALSE;

 547     }

 548 

 549     /**

 550      * Changes the currently enabled modules. Module paths may be relative

 551      * or absolute, but must point to a directory:

 552      *

 553      *     Kohana::modules(array('modules/foo', MODPATH.'bar'));

 554      *

 555      * @param   array   $modules    list of module paths

 556      * @return  array   enabled modules

 557      */

 558     public static function modules(array $modules = NULL)

 559     {

 560         if ($modules === NULL)

 561         {

 562             // Not changing modules, just return the current set

 563             return Kohana::$_modules;

 564         }

 565 

 566         // Start a new list of include paths, APPPATH first

 567         $paths = array(APPPATH);

 568 

 569         foreach ($modules as $name => $path)

 570         {

 571             if (is_dir($path))

 572             {

 573                 // Add the module to include paths

 574                 $paths[] = $modules[$name] = realpath($path).DIRECTORY_SEPARATOR;

 575             }

 576             else

 577             {

 578                 // This module is invalid, remove it

 579                 throw new Kohana_Exception('Attempted to load an invalid or missing module \':module\' at \':path\'', array(

 580                     ':module' => $name,

 581                     ':path'   => Debug::path($path),

 582                 ));

 583             }

 584         }

 585 

 586         // Finish the include paths by adding SYSPATH

 587         $paths[] = SYSPATH;

 588 

 589         // Set the new include paths

 590         Kohana::$_paths = $paths;

 591 

 592         // Set the current module list

 593         Kohana::$_modules = $modules;

 594 

 595         foreach (Kohana::$_modules as $path)

 596         {

 597             $init = $path.'init'.EXT;

 598 

 599             if (is_file($init))

 600             {

 601                 // Include the module initialization file once

 602                 require_once $init;

 603             }

 604         }

 605 

 606         return Kohana::$_modules;

 607     }

 608 

 609     /**

 610      * Returns the the currently active include paths, including the

 611      * application, system, and each module's path.

 612      *

 613      * @return  array

 614      */

 615     public static function include_paths()

 616     {

 617         return Kohana::$_paths;

 618     }

 619 

 620     /**

 621      * Searches for a file in the [Cascading Filesystem](kohana/files), and

 622      * returns the path to the file that has the highest precedence, so that it

 623      * can be included.

 624      *

 625      * When searching the "config", "messages", or "i18n" directories, or when

 626      * the `$array` flag is set to true, an array of all the files that match

 627      * that path in the [Cascading Filesystem](kohana/files) will be returned.

 628      * These files will return arrays which must be merged together.

 629      *

 630      * If no extension is given, the default extension (`EXT` set in

 631      * `index.php`) will be used.

 632      *

 633      *     // Returns an absolute path to views/template.php

 634      *     Kohana::find_file('views', 'template');

 635      *

 636      *     // Returns an absolute path to media/css/style.css

 637      *     Kohana::find_file('media', 'css/style', 'css');

 638      *

 639      *     // Returns an array of all the "mimes" configuration files

 640      *     Kohana::find_file('config', 'mimes');

 641      *

 642      * @param   string  $dir    directory name (views, i18n, classes, extensions, etc.)

 643      * @param   string  $file   filename with subdirectory

 644      * @param   string  $ext    extension to search for

 645      * @param   boolean $array  return an array of files?

 646      * @return  array   a list of files when $array is TRUE

 647      * @return  string  single file path

 648      */

 649     public static function find_file($dir, $file, $ext = NULL, $array = FALSE)

 650     {

 651         if ($ext === NULL)

 652         {

 653             // Use the default extension

 654             $ext = EXT;

 655         }

 656         elseif ($ext)

 657         {

 658             // Prefix the extension with a period

 659             $ext = ".{$ext}";

 660         }

 661         else

 662         {

 663             // Use no extension

 664             $ext = '';

 665         }

 666 

 667         // Create a partial path of the filename

 668         $path = $dir.DIRECTORY_SEPARATOR.$file.$ext;

 669 

 670         if (Kohana::$caching === TRUE AND isset(Kohana::$_files[$path.($array ? '_array' : '_path')]))

 671         {

 672             // This path has been cached

 673             return Kohana::$_files[$path.($array ? '_array' : '_path')];

 674         }

 675 

 676         if (Kohana::$profiling === TRUE AND class_exists('Profiler', FALSE))

 677         {

 678             // Start a new benchmark

 679             $benchmark = Profiler::start('Kohana', __FUNCTION__);

 680         }

 681 

 682         if ($array OR $dir === 'config' OR $dir === 'i18n' OR $dir === 'messages')

 683         {

 684             // Include paths must be searched in reverse

 685             $paths = array_reverse(Kohana::$_paths);

 686 

 687             // Array of files that have been found

 688             $found = array();

 689 

 690             foreach ($paths as $dir)

 691             {

 692                 if (is_file($dir.$path))

 693                 {

 694                     // This path has a file, add it to the list

 695                     $found[] = $dir.$path;

 696                 }

 697             }

 698         }

 699         else

 700         {

 701             // The file has not been found yet

 702             $found = FALSE;

 703 

 704             foreach (Kohana::$_paths as $dir)

 705             {

 706                 if (is_file($dir.$path))

 707                 {

 708                     // A path has been found

 709                     $found = $dir.$path;

 710 

 711                     // Stop searching

 712                     break;

 713                 }

 714             }

 715         }

 716 

 717         if (Kohana::$caching === TRUE)

 718         {

 719             // Add the path to the cache

 720             Kohana::$_files[$path.($array ? '_array' : '_path')] = $found;

 721 

 722             // Files have been changed

 723             Kohana::$_files_changed = TRUE;

 724         }

 725 

 726         if (isset($benchmark))

 727         {

 728             // Stop the benchmark

 729             Profiler::stop($benchmark);

 730         }

 731 

 732         return $found;

 733     }

 734 

 735     /**

 736      * Recursively finds all of the files in the specified directory at any

 737      * location in the [Cascading Filesystem](kohana/files), and returns an

 738      * array of all the files found, sorted alphabetically.

 739      *

 740      *     // Find all view files.

 741      *     $views = Kohana::list_files('views');

 742      *

 743      * @param   string  $directory  directory name

 744      * @param   array   $paths      list of paths to search

 745      * @return  array

 746      */

 747     public static function list_files($directory = NULL, array $paths = NULL)

 748     {

 749         if ($directory !== NULL)

 750         {

 751             // Add the directory separator

 752             $directory .= DIRECTORY_SEPARATOR;

 753         }

 754 

 755         if ($paths === NULL)

 756         {

 757             // Use the default paths

 758             $paths = Kohana::$_paths;

 759         }

 760 

 761         // Create an array for the files

 762         $found = array();

 763 

 764         foreach ($paths as $path)

 765         {

 766             if (is_dir($path.$directory))

 767             {

 768                 // Create a new directory iterator

 769                 $dir = new DirectoryIterator($path.$directory);

 770 

 771                 foreach ($dir as $file)

 772                 {

 773                     // Get the file name

 774                     $filename = $file->getFilename();

 775 

 776                     if ($filename[0] === '.' OR $filename[strlen($filename)-1] === '~')

 777                     {

 778                         // Skip all hidden files and UNIX backup files

 779                         continue;

 780                     }

 781 

 782                     // Relative filename is the array key

 783                     $key = $directory.$filename;

 784 

 785                     if ($file->isDir())

 786                     {

 787                         if ($sub_dir = Kohana::list_files($key, $paths))

 788                         {

 789                             if (isset($found[$key]))

 790                             {

 791                                 // Append the sub-directory list

 792                                 $found[$key] += $sub_dir;

 793                             }

 794                             else

 795                             {

 796                                 // Create a new sub-directory list

 797                                 $found[$key] = $sub_dir;

 798                             }

 799                         }

 800                     }

 801                     else

 802                     {

 803                         if ( ! isset($found[$key]))

 804                         {

 805                             // Add new files to the list

 806                             $found[$key] = realpath($file->getPathName());

 807                         }

 808                     }

 809                 }

 810             }

 811         }

 812 

 813         // Sort the results alphabetically

 814         ksort($found);

 815 

 816         return $found;

 817     }

 818 

 819     /**

 820      * Loads a file within a totally empty scope and returns the output:

 821      *

 822      *     $foo = Kohana::load('foo.php');

 823      *

 824      * @param   string  $file

 825      * @return  mixed

 826      */

 827     public static function load($file)

 828     {

 829         return include $file;

 830     }

 831 

 832     /**

 833      * Provides simple file-based caching for strings and arrays:

 834      *

 835      *     // Set the "foo" cache

 836      *     Kohana::cache('foo', 'hello, world');

 837      *

 838      *     // Get the "foo" cache

 839      *     $foo = Kohana::cache('foo');

 840      *

 841      * All caches are stored as PHP code, generated with [var_export][ref-var].

 842      * Caching objects may not work as expected. Storing references or an

 843      * object or array that has recursion will cause an E_FATAL.

 844      *

 845      * The cache directory and default cache lifetime is set by [Kohana::init]

 846      *

 847      * [ref-var]: http://php.net/var_export

 848      *

 849      * @throws  Kohana_Exception

 850      * @param   string  $name       name of the cache

 851      * @param   mixed   $data       data to cache

 852      * @param   integer $lifetime   number of seconds the cache is valid for

 853      * @return  mixed    for getting

 854      * @return  boolean  for setting

 855      */

 856     public static function cache($name, $data = NULL, $lifetime = NULL)

 857     {

 858         // Cache file is a hash of the name

 859         $file = sha1($name).'.txt';

 860 

 861         // Cache directories are split by keys to prevent filesystem overload

 862         $dir = Kohana::$cache_dir.DIRECTORY_SEPARATOR.$file[0].$file[1].DIRECTORY_SEPARATOR;

 863 

 864         if ($lifetime === NULL)

 865         {

 866             // Use the default lifetime

 867             $lifetime = Kohana::$cache_life;

 868         }

 869 

 870         if ($data === NULL)

 871         {

 872             if (is_file($dir.$file))

 873             {

 874                 if ((time() - filemtime($dir.$file)) < $lifetime)

 875                 {

 876                     // Return the cache

 877                     try

 878                     {

 879                         return unserialize(file_get_contents($dir.$file));

 880                     }

 881                     catch (Exception $e)

 882                     {

 883                         // Cache is corrupt, let return happen normally.

 884                     }

 885                 }

 886                 else

 887                 {

 888                     try

 889                     {

 890                         // Cache has expired

 891                         unlink($dir.$file);

 892                     }

 893                     catch (Exception $e)

 894                     {

 895                         // Cache has mostly likely already been deleted,

 896                         // let return happen normally.

 897                     }

 898                 }

 899             }

 900 

 901             // Cache not found

 902             return NULL;

 903         }

 904 

 905         if ( ! is_dir($dir))

 906         {

 907             // Create the cache directory

 908             mkdir($dir, 0777, TRUE);

 909 

 910             // Set permissions (must be manually set to fix umask issues)

 911             chmod($dir, 0777);

 912         }

 913 

 914         // Force the data to be a string

 915         $data = serialize($data);

 916 

 917         try

 918         {

 919             // Write the cache

 920             return (bool) file_put_contents($dir.$file, $data, LOCK_EX);

 921         }

 922         catch (Exception $e)

 923         {

 924             // Failed to write cache

 925             return FALSE;

 926         }

 927     }

 928 

 929     /**

 930      * Get a message from a file. Messages are arbitary strings that are stored

 931      * in the `messages/` directory and reference by a key. Translation is not

 932      * performed on the returned values.  See [message files](kohana/files/messages)

 933      * for more information.

 934      *

 935      *     // Get "username" from messages/text.php

 936      *     $username = Kohana::message('text', 'username');

 937      *

 938      * @param   string  $file       file name

 939      * @param   string  $path       key path to get

 940      * @param   mixed   $default    default value if the path does not exist

 941      * @return  string  message string for the given path

 942      * @return  array   complete message list, when no path is specified

 943      * @uses    Arr::merge

 944      * @uses    Arr::path

 945      */

 946     public static function message($file, $path = NULL, $default = NULL)

 947     {

 948         static $messages;

 949 

 950         if ( ! isset($messages[$file]))

 951         {

 952             // Create a new message list

 953             $messages[$file] = array();

 954 

 955             if ($files = Kohana::find_file('messages', $file))

 956             {

 957                 foreach ($files as $f)

 958                 {

 959                     // Combine all the messages recursively

 960                     $messages[$file] = Arr::merge($messages[$file], Kohana::load($f));

 961                 }

 962             }

 963         }

 964 

 965         if ($path === NULL)

 966         {

 967             // Return all of the messages

 968             return $messages[$file];

 969         }

 970         else

 971         {

 972             // Get a message using the path

 973             return Arr::path($messages[$file], $path, $default);

 974         }

 975     }

 976 

 977     /**

 978      * PHP error handler, converts all errors into ErrorExceptions. This handler

 979      * respects error_reporting settings.

 980      *

 981      * @throws  ErrorException

 982      * @return  TRUE

 983      */

 984     public static function error_handler($code, $error, $file = NULL, $line = NULL)

 985     {

 986         if (error_reporting() & $code)

 987         {

 988             // This error is not suppressed by current error reporting settings

 989             // Convert the error into an ErrorException

 990             throw new ErrorException($error, $code, 0, $file, $line);

 991         }

 992 

 993         // Do not execute the PHP error handler

 994         return TRUE;

 995     }

 996 

 997     /**

 998      * Catches errors that are not caught by the error handler, such as E_PARSE.

 999      *

1000      * @uses    Kohana_Exception::handler

1001      * @return  void

1002      */

1003     public static function shutdown_handler()

1004     {

1005         if ( ! Kohana::$_init)

1006         {

1007             // Do not execute when not active

1008             return;

1009         }

1010 

1011         try

1012         {

1013             if (Kohana::$caching === TRUE AND Kohana::$_files_changed === TRUE)

1014             {

1015                 // Write the file path cache

1016                 Kohana::cache('Kohana::find_file()', Kohana::$_files);

1017             }

1018         }

1019         catch (Exception $e)

1020         {

1021             // Pass the exception to the handler

1022             Kohana_Exception::handler($e);

1023         }

1024 

1025         if (Kohana::$errors AND $error = error_get_last() AND in_array($error['type'], Kohana::$shutdown_errors))

1026         {

1027             // Clean the output buffer

1028             ob_get_level() AND ob_clean();

1029 

1030             // Fake an exception for nice debugging

1031             Kohana_Exception::handler(new ErrorException($error['message'], $error['type'], 0, $error['file'], $error['line']));

1032 

1033             // Shutdown now to avoid a "death loop"

1034             exit(1);

1035         }

1036     }

1037 

1038     /**

1039      * Generates a version string based on the variables defined above.

1040      * 

1041      * @return string

1042      */

1043     public static function version()

1044     {

1045         return 'Kohana Framework '.Kohana::VERSION.' ('.Kohana::CODENAME.')';

1046     }

1047 

1048 } // End Kohana

 

你可能感兴趣的:(classes)