Commit 81048626 authored by Taylor Otwell's avatar Taylor Otwell

Merge branch 'develop' of github.com:laravel/laravel into develop

parents 606b8cea 9bb69309
...@@ -66,21 +66,4 @@ return array( ...@@ -66,21 +66,4 @@ return array(
Log::exception($exception); Log::exception($exception);
}, },
/*
|--------------------------------------------------------------------------
| PHP INI Display Errors Setting
|--------------------------------------------------------------------------
|
| Here you may specify the display_errors setting of the PHP.ini file.
| Typically you may keep this "Off", as Laravel will cleanly handle
| the display of all errors.
|
| However, if you encounter an infamous white screen of death scenario,
| turning this "On" may help you solve the problem by getting the
| real error message being thrown by the application.
|
*/
'display' => 'Off',
); );
\ No newline at end of file
<?php <?php
/*
|--------------------------------------------------------------------------
| PHP Display Errors Configuration
|--------------------------------------------------------------------------
|
| Since Laravel intercepts and displays all errors with a detailed stack
| trace, we can turn off the display_errors ini directive. However, you
| may want to enable this option if you ever run into a dreaded white
| screen of death, as it can provide some clues.
|
*/
ini_set('display_errors', 'On');
/*
|--------------------------------------------------------------------------
| Laravel Configuration Loader
|--------------------------------------------------------------------------
|
| The Laravel configuration loader is responsible for returning an array
| of configuration options for a given bundle and file. By default, we
| use the files provided with Laravel; however, you are free to use
| your own storage mechanism for configuration arrays.
|
*/
Laravel\Event::listen(Laravel\Config::loader, function($bundle, $file)
{
return Laravel\Config::file($bundle, $file);
});
/*
|--------------------------------------------------------------------------
| Register Class Aliases
|--------------------------------------------------------------------------
|
| Aliases allow you to use classes without always specifying their fully
| namespaced path. This is convenient for working with any library that
| makes a heavy use of namespace for class organization. Here we will
| simply register the configured class aliases.
|
*/
$aliases = Laravel\Config::get('application.aliases');
Laravel\Autoloader::$aliases = $aliases;
/*
|--------------------------------------------------------------------------
| Laravel View Loader
|--------------------------------------------------------------------------
|
| The Laravel view loader is responsible for returning the full file path
| for the given bundle and view. Of course, a default implementation is
| provided to load views according to typical Laravel conventions but
| you may change this to customize how your views are organized.
|
*/
Event::listen(View::loader, function($bundle, $view)
{
return View::file($bundle, $view);
});
/*
|--------------------------------------------------------------------------
| Laravel Language Loader
|--------------------------------------------------------------------------
|
| The Laravel language loader is responsible for returning the array of
| language lines for a given bundle, language, and "file". A default
| implementation has been provided which uses the default language
| directories included with Laravel. However, you may tweak this
| method to laad your language arrays however you wish.
|
*/
Event::listen(Lang::loader, function($bundle, $language, $file)
{
return Lang::file($bundle, $language, $file);
});
/*
|--------------------------------------------------------------------------
| Set The Default Timezone
|--------------------------------------------------------------------------
|
| We need to set the default timezone for the application. This controls
| the timezone that will be used by any of the date methods and classes
| utilized by Laravel or your application. The timezone may be set in
| your application configuration file.
|
*/
date_default_timezone_set(Config::get('application.timezone'));
/*
|--------------------------------------------------------------------------
| Start / Load The User Session
|--------------------------------------------------------------------------
|
| Sessions allow the web, which is stateless, to simulate state. In other
| words, sessions allow you to store information about the current user
| and state of your application. Here we'll just fire up the session
| if a session driver has been configured.
|
*/
if ( ! Request::cli() and Config::get('session.driver') !== '')
{
Session::load();
}
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Auto-Loader Mappings | Auto-Loader Mappings
......
...@@ -9,4 +9,9 @@ Changes for 3.1: ...@@ -9,4 +9,9 @@ Changes for 3.1:
- Registering of view paths and extensions - Registering of view paths and extensions
- Pattern based filters. - Pattern based filters.
- Better session ID assignment - Better session ID assignment
- Added cviebrock's unsigned support. - Added cviebrock's unsigned support.
\ No newline at end of file - Added config, view, and lang loaders.
- Moved more stuff into application/start
- Removed error.display config options.
- Added foreign key support to schema builder.
- Postgres "unique" indexes are now added with ADD CONSTRAINT
\ No newline at end of file
...@@ -44,7 +44,7 @@ class Command { ...@@ -44,7 +44,7 @@ class Command {
throw new \Exception("Sorry, I can't find that task."); throw new \Exception("Sorry, I can't find that task.");
} }
if(is_callable(array($task, $method))) if (is_callable(array($task, $method)))
{ {
$task->$method(array_slice($arguments, 1)); $task->$method(array_slice($arguments, 1));
} }
...@@ -114,7 +114,7 @@ class Command { ...@@ -114,7 +114,7 @@ class Command {
// First we'll check to see if the task has been registered in the // First we'll check to see if the task has been registered in the
// application IoC container. This allows all dependencies to be // application IoC container. This allows all dependencies to be
// injected into tasks for more testability. // injected into tasks for more flexible testability.
if (IoC::registered("task: {$identifier}")) if (IoC::registered("task: {$identifier}"))
{ {
return IoC::resolve("task: {$identifier}"); return IoC::resolve("task: {$identifier}");
......
...@@ -20,6 +20,13 @@ class Config { ...@@ -20,6 +20,13 @@ class Config {
*/ */
public static $cache = array(); public static $cache = array();
/**
* The configuration loader event name.
*
* @var string
*/
const loader = 'laravel.config.loader';
/** /**
* Determine if a configuration item or file exists. * Determine if a configuration item or file exists.
* *
...@@ -106,8 +113,7 @@ class Config { ...@@ -106,8 +113,7 @@ class Config {
// If the item is null, it means the developer wishes to set the entire // If the item is null, it means the developer wishes to set the entire
// configuration array to a given value, so we will pass the entire // configuration array to a given value, so we will pass the entire
// array for the bundle into the array_set method, otherwise we'll // array for the bundle into the array_set method.
// only pass the file array for the bundle.
if (is_null($item)) if (is_null($item))
{ {
array_set(static::$items[$bundle], $file, $value); array_set(static::$items[$bundle], $file, $value);
...@@ -166,6 +172,31 @@ class Config { ...@@ -166,6 +172,31 @@ class Config {
{ {
if (isset(static::$items[$bundle][$file])) return true; if (isset(static::$items[$bundle][$file])) return true;
// We allow a "config.loader" event to be registered which is responsible for
// returning an array representing the configuration for the bundle and file
// requested. This allows many types of config "drivers".
$config = Event::first(static::loader, func_get_args());
// If configuration items were actually found for the bundle and file we
// will add them to the configuration array and return true, otherwise
// we will return false indicating the file was not found.
if (count($config) > 0)
{
static::$items[$bundle][$file] = $config;
}
return isset(static::$items[$bundle][$file]);
}
/**
* Load the configuration items from a configuration file.
*
* @param string $bundle
* @param string $file
* @return array
*/
public static function file($bundle, $file)
{
$config = array(); $config = array();
// Configuration files cascade. Typically, the bundle configuration array is // Configuration files cascade. Typically, the bundle configuration array is
...@@ -179,12 +210,7 @@ class Config { ...@@ -179,12 +210,7 @@ class Config {
} }
} }
if (count($config) > 0) return $config;
{
static::$items[$bundle][$file] = $config;
}
return isset(static::$items[$bundle][$file]);
} }
/** /**
......
<?php namespace Laravel; <?php namespace Laravel;
/** /*
* Define all of the constants that we will need to use the framework. |--------------------------------------------------------------------------
* These are things like file extensions, as well as all of the paths | PHP Display Errors Configuration
* used by the framework. All of the paths are built on top of the |--------------------------------------------------------------------------
* basic application, laravel, and public paths. |
*/ | Register the constants used by the framework. These are things like file
| extensions and other information that we want to be able to access with
| just a simple constant.
|
*/
define('EXT', '.php'); define('EXT', '.php');
define('CRLF', "\r\n"); define('CRLF', "\r\n");
define('DEFAULT_BUNDLE', 'application'); define('DEFAULT_BUNDLE', 'application');
define('MB_STRING', (int) function_exists('mb_get_info')); define('MB_STRING', (int) function_exists('mb_get_info'));
/** /*
* Require all of the classes that can't be loaded by the auto-loader. |--------------------------------------------------------------------------
* These are typically classes that the auto-loader relies upon to | Require Core Classes
* load classes, such as the array and configuration classes. |--------------------------------------------------------------------------
*/ |
| Here we will just load in the classes that are used for every request
| or are used by the configuration class. It is quicker and simpler to
| just manually load them in instead of using the auto-loader.
|
*/
require path('sys').'ioc'.EXT;
require path('sys').'event'.EXT; require path('sys').'event'.EXT;
require path('sys').'bundle'.EXT; require path('sys').'bundle'.EXT;
require path('sys').'config'.EXT; require path('sys').'config'.EXT;
require path('sys').'helpers'.EXT; require path('sys').'helpers'.EXT;
require path('sys').'autoloader'.EXT; require path('sys').'autoloader'.EXT;
/** /*
* Register the Autoloader's "load" method on the auto-loader stack. |--------------------------------------------------------------------------
* This method provides the lazy-loading of all class files, as well | Register The Framework Auto-Loader
* as any PSR-0 compliant libraries used by the application. |--------------------------------------------------------------------------
*/ |
| Next we'll register the Autoloader class on the SPL auto-loader stack
| so it can lazy-load our class files as we need them. This class and
| method will be called each time a class is needed but has not been
| defined yet and will load the appropriate file.
|
*/
spl_autoload_register(array('Laravel\\Autoloader', 'load')); spl_autoload_register(array('Laravel\\Autoloader', 'load'));
/** /*
* Register the Laravel namespace so that the auto-loader loads it |--------------------------------------------------------------------------
* according to the PSR-0 naming conventions. This should provide | Register The Laravel Namespace
* fast resolution of all core classes. |--------------------------------------------------------------------------
*/ |
| Register the "Laravel" namespace and its directory mapping so the class
| loader can quickly load all of the core classes using PSR-0 style load
| conventions throughout the "laravel" directory since all core classes
| are namespaced into the "Laravel" namespace.
|
*/
Autoloader::namespaces(array('Laravel' => path('sys'))); Autoloader::namespaces(array('Laravel' => path('sys')));
/** /*
* Set the CLI options on the $_SERVER global array so we can easily |--------------------------------------------------------------------------
* retrieve them from the various parts of the CLI code. We can use | Set The CLI Options Array
* the Request class to access them conveniently. |--------------------------------------------------------------------------
*/ |
| If the current request is from the Artisan command-line interface, we
| will parse the command line arguments and options and set them the
| array of options in the $_SERVER global array for convenience.
|
*/
if (defined('STDIN')) if (defined('STDIN'))
{ {
$console = CLI\Command::options($_SERVER['argv']); $console = CLI\Command::options($_SERVER['argv']);
...@@ -52,39 +84,34 @@ if (defined('STDIN')) ...@@ -52,39 +84,34 @@ if (defined('STDIN'))
$_SERVER['CLI'] = $options; $_SERVER['CLI'] = $options;
} }
/** /*
* The Laravel environment may be specified on the CLI using the env |--------------------------------------------------------------------------
* option, allowing the developer to easily use local configuration | Set The CLI Laravel Environment
* files from the CLI since the environment is usually controlled |--------------------------------------------------------------------------
* by server environmenet variables. |
*/ | Next we'll set the LARAVEL_ENV variable if the current request is from
| the Artisan command-line interface. Since the environment is often
| specified within an Apache .htaccess file, we need to set it here
| when the request is not coming through Apache.
|
*/
if (isset($_SERVER['CLI']['ENV'])) if (isset($_SERVER['CLI']['ENV']))
{ {
$_SERVER['LARAVEL_ENV'] = $_SERVER['CLI']['ENV']; $_SERVER['LARAVEL_ENV'] = $_SERVER['CLI']['ENV'];
} }
/** /*
* Register all of the core class aliases. These aliases provide a |--------------------------------------------------------------------------
* convenient way of working with the Laravel core classes without | Register The Laravel Bundles
* having to worry about the namespacing. The developer is also |--------------------------------------------------------------------------
* free to remove aliases when they extend core classes. |
*/ | Finally we will register all of the bundles that have been defined for
Autoloader::$aliases = Config::get('application.aliases'); | the application. None of them will be started, yet but will be setup
| so that they may be started by the develop at any time.
/** |
* Register the default timezone for the application. This will */
* be the default timezone used by all date functions through
* throughout the entire application.
*/
$timezone = Config::get('application.timezone');
date_default_timezone_set($timezone);
/**
* Finally we'll grab all of the bundles and register them
* with the bundle class. All of the bundles are stored in
* an array within the application directory.
*/
$bundles = require path('app').'bundles'.EXT; $bundles = require path('app').'bundles'.EXT;
foreach ($bundles as $bundle => $config) foreach ($bundles as $bundle => $config)
......
...@@ -6,14 +6,60 @@ use Laravel\Database\Schema\Table; ...@@ -6,14 +6,60 @@ use Laravel\Database\Schema\Table;
abstract class Grammar extends \Laravel\Database\Grammar { abstract class Grammar extends \Laravel\Database\Grammar {
/** /**
* Get the appropriate data type definition for the column. * Generate the SQL statement for creating a foreign key.
* *
* @param Table $table
* @param Command $command
* @return string
*/
public function foreign(Table $table, Fluent $command)
{
$name = $command->name;
// We need to wrap both of the table names in quoted identifiers to protect
// against any possible keyword collisions, both the table on which the
// command is being executed and the referenced table are wrapped.
$table = $this->wrap($table);
$on = $this->wrap($command->on);
// Next we need to columnize both the command table's columns as well as
// the columns referenced by the foreign key. We'll cast the referenced
// columns to an array since they aren't by the fluent command.
$foreign = $this->columnize($command->columns);
$referenced = $this->columnize((array) $command->references);
$sql = "ALTER TABLE $table ADD CONSTRAINT $name ";
return $sql .= "FOREIGN KEY ($foreign) REFERENCES $on ($referenced)";
}
/**
* Drop a constraint from the table.
*
* @param Table $table
* @param Fluent $fluent
* @return string
*/
protected function drop_constraint(Table $table, Fluent $command)
{
return "ALTER TABLE ".$this->wrap($table)." DROP CONSTRAINT ".$command->name;
}
/**
* Get the SQL syntax for indicating if a column is unsigned.
*
* @param Table $table
* @param Fluent $column * @param Fluent $column
* @return string * @return string
*/ */
protected function type(Fluent $column) protected function unsigned(Table $table, Fluent $column)
{ {
return $this->{'type_'.$column->type}($column); if ($column->type == 'integer' && $column->unsigned)
{
return ' UNSIGNED';
}
} }
/** /**
...@@ -40,18 +86,14 @@ abstract class Grammar extends \Laravel\Database\Grammar { ...@@ -40,18 +86,14 @@ abstract class Grammar extends \Laravel\Database\Grammar {
} }
/** /**
* Get the SQL syntax for indicating if a column is unsigned. * Get the appropriate data type definition for the column.
* *
* @param Table $table
* @param Fluent $column * @param Fluent $column
* @return string * @return string
*/ */
protected function unsigned(Table $table, Fluent $column) protected function type(Fluent $column)
{ {
if ($column->type == 'integer' && $column->unsigned) return $this->{'type_'.$column->type}($column);
{
return ' UNSIGNED';
}
} }
} }
\ No newline at end of file
...@@ -292,6 +292,18 @@ class MySQL extends Grammar { ...@@ -292,6 +292,18 @@ class MySQL extends Grammar {
return 'ALTER TABLE '.$this->wrap($table)." DROP INDEX {$command->name}"; return 'ALTER TABLE '.$this->wrap($table)." DROP INDEX {$command->name}";
} }
/**
* Drop a foreign key constraint from the table.
*
* @param Table $table
* @param Fluent $fluent
* @return string
*/
public function drop_foreign(Table $table, Fluent $command)
{
return "ALTER TABLE ".$this->wrap($table)." DROP FOREIGN KEY ".$command->name;
}
/** /**
* Generate the data-type definition for a string. * Generate the data-type definition for a string.
* *
......
...@@ -146,7 +146,11 @@ class Postgres extends Grammar { ...@@ -146,7 +146,11 @@ class Postgres extends Grammar {
*/ */
public function unique(Table $table, Fluent $command) public function unique(Table $table, Fluent $command)
{ {
return $this->key($table, $command, true); $table = $this->wrap($table);
$columns = $this->columnize($command->columns);
return "ALTER TABLE $table ADD CONSTRAINT ".$command->name." UNIQUE ($columns)";
} }
/** /**
...@@ -250,7 +254,7 @@ class Postgres extends Grammar { ...@@ -250,7 +254,7 @@ class Postgres extends Grammar {
*/ */
public function drop_unique(Table $table, Fluent $command) public function drop_unique(Table $table, Fluent $command)
{ {
return $this->drop_key($table, $command); return $this->drop_constraint($table, $command);
} }
/** /**
...@@ -289,6 +293,18 @@ class Postgres extends Grammar { ...@@ -289,6 +293,18 @@ class Postgres extends Grammar {
return 'DROP INDEX '.$command->name; return 'DROP INDEX '.$command->name;
} }
/**
* Drop a foreign key constraint from the table.
*
* @param Table $table
* @param Fluent $fluent
* @return string
*/
public function drop_foreign(Table $table, Fluent $command)
{
return $this->drop_constraint($table, $command);
}
/** /**
* Generate the data-type definition for a string. * Generate the data-type definition for a string.
* *
......
...@@ -311,6 +311,18 @@ class SQLServer extends Grammar { ...@@ -311,6 +311,18 @@ class SQLServer extends Grammar {
return "DROP INDEX {$command->name} ON ".$this->wrap($table); return "DROP INDEX {$command->name} ON ".$this->wrap($table);
} }
/**
* Drop a foreign key constraint from the table.
*
* @param Table $table
* @param Fluent $fluent
* @return string
*/
public function drop_foreign(Table $table, Fluent $command)
{
return $this->drop_constraint($table, $command);
}
/** /**
* Generate the data-type definition for a string. * Generate the data-type definition for a string.
* *
......
...@@ -108,6 +108,17 @@ class Table { ...@@ -108,6 +108,17 @@ class Table {
return $this->key(__FUNCTION__, $columns, $name); return $this->key(__FUNCTION__, $columns, $name);
} }
/**
* Add a foreign key constraint to the table.
*
* @param string|array $columns
* @param string $name
*/
public function foreign($columns, $name = null)
{
return $this->key(__FUNCTION__, $columns, $name);
}
/** /**
* Create a command for creating any index. * Create a command for creating any index.
* *
...@@ -196,6 +207,17 @@ class Table { ...@@ -196,6 +207,17 @@ class Table {
return $this->drop_key(__FUNCTION__, $name); return $this->drop_key(__FUNCTION__, $name);
} }
/**
* Drop a foreign key constraint from the table.
*
* @param string $name
* @return void
*/
public function drop_foreign($name)
{
return $this->drop_key(__FUNCTION__, $name);
}
/** /**
* Create a command to drop any type of index. * Create a command to drop any type of index.
* *
...@@ -205,7 +227,7 @@ class Table { ...@@ -205,7 +227,7 @@ class Table {
*/ */
protected function drop_key($type, $name) protected function drop_key($type, $name)
{ {
return $this->command($type, array('name' => $name)); return $this->command($type, compact('name'));
} }
/** /**
......
...@@ -12,7 +12,7 @@ class Error { ...@@ -12,7 +12,7 @@ class Error {
{ {
static::log($exception); static::log($exception);
ob_end_clean(); ob_get_level() and ob_end_clean();
// If detailed errors are enabled, we'll just format the exception into // If detailed errors are enabled, we'll just format the exception into
// a simple error message and display it on the screen. We don't use a // a simple error message and display it on the screen. We don't use a
......
...@@ -40,6 +40,31 @@ class Event { ...@@ -40,6 +40,31 @@ class Event {
static::$events[$event][] = $callback; static::$events[$event][] = $callback;
} }
/**
* Override all callbacks for a given event with a new callback.
*
* @param string $event
* @param mixed $callback
* @return void
*/
public static function override($event, $callback)
{
static::clear($event);
static::listen($event, $callback);
}
/**
* Clear all event listeners for a given event.
*
* @param string $event
* @return void
*/
public static function clear($event)
{
static::$events[$event] = array();
}
/** /**
* Fire an event and return the first response. * Fire an event and return the first response.
* *
......
...@@ -32,6 +32,13 @@ class Lang { ...@@ -32,6 +32,13 @@ class Lang {
*/ */
protected static $lines = array(); protected static $lines = array();
/**
* The language loader event name.
*
* @var string
*/
const loader = 'laravel.language.loader';
/** /**
* Create a new Lang instance. * Create a new Lang instance.
* *
...@@ -179,6 +186,26 @@ class Lang { ...@@ -179,6 +186,26 @@ class Lang {
return true; return true;
} }
// We use a "loader" event to delegate the loading of the language
// array, which allows the develop to organize the language line
// arrays for their application however they wish.
$lines = Event::first(static::loader, func_get_args());
static::$lines[$bundle][$language][$file] = $lines;
return count($lines) > 0;
}
/**
* Load a language array from a language file.
*
* @param string $bundle
* @param string $language
* @param string $file
* @return array
*/
public static function file($bundle, $language, $file)
{
$lines = array(); $lines = array();
// Language files can belongs to the application or to any bundle // Language files can belongs to the application or to any bundle
...@@ -191,12 +218,7 @@ class Lang { ...@@ -191,12 +218,7 @@ class Lang {
$lines = require $path; $lines = require $path;
} }
// All of the language lines are cached in an array so we can return $lines;
// quickly look them up on subsequent reqwuests for the line.
// This keeps us from loading files each time.
static::$lines[$bundle][$language][$file] = $lines;
return count($lines) > 0;
} }
/** /**
......
This diff is collapsed.
...@@ -141,6 +141,27 @@ class Request { ...@@ -141,6 +141,27 @@ class Request {
return defined('STDIN'); return defined('STDIN');
} }
/**
* Get the Laravel environment for the current request.
*
* @return string|null
*/
public static function env()
{
if (isset($_SERVER['LARAVEL_ENV'])) return $_SERVER['LARAVEL_ENV'];
}
/**
* Determine the current request environment.
*
* @param string $env
* @return bool
*/
public static function is_env($env)
{
return static::env() === $env;
}
/** /**
* Get the main route handling the request. * Get the main route handling the request.
* *
......
...@@ -17,7 +17,19 @@ class Session { ...@@ -17,7 +17,19 @@ class Session {
const csrf_token = 'csrf_token'; const csrf_token = 'csrf_token';
/** /**
* Create the session payload instance and load the session for the request. * Create the session payload and the load the session.
*
* @return void
*/
public static function load()
{
static::start(Config::get('session.driver'));
static::$instance->load(Cookie::get(Config::get('session.cookie')));
}
/**
* Create the session payload instance for the request.
* *
* @param string $driver * @param string $driver
* @return void * @return void
......
...@@ -51,6 +51,13 @@ class View implements ArrayAccess { ...@@ -51,6 +51,13 @@ class View implements ArrayAccess {
*/ */
public static $paths = array(DEFAULT_BUNDLE => array('')); public static $paths = array(DEFAULT_BUNDLE => array(''));
/**
* The Laravel view loader event name.
*
* @var string
*/
const loader = 'laravel.view.loader';
/** /**
* The Laravel view engine event name. * The Laravel view engine event name.
* *
...@@ -106,28 +113,40 @@ class View implements ArrayAccess { ...@@ -106,28 +113,40 @@ class View implements ArrayAccess {
*/ */
protected function path($view) protected function path($view)
{ {
$view = str_replace('.', '/', $view); list($bundle, $view) = Bundle::parse($view);
$root = Bundle::path(Bundle::name($view)).'views/'; $view = str_replace('.', '/', $view);
// We need to make sure that the view exists. If it doesn't, we will // We delegate the determination of view paths to the view loader
// throw an exception since there is not any point in going further. // event so that the developer is free to override and manage
// If it does, we can just return the full view path. // the loading views in any way they see fit.
$paths = array_get(static::$paths, Bundle::name($view), array('')); $path = Event::first(static::loader, array($bundle, $view));
foreach ($paths as $path) if ( ! is_null($path))
{ {
foreach (static::$extensions as $ext) return $path;
{
$file = $root.$path.Bundle::element($view).$ext;
if (file_exists($file)) return $file;
}
} }
throw new \Exception("View [$view] doesn't exist."); throw new \Exception("View [$view] doesn't exist.");
} }
/**
* Get the path to a view using the default folder convention.
*
* @param string $bundle
* @param string $view
* @return string
*/
public static function file($bundle, $view)
{
$root = Bundle::path($bundle).'views/';
if (file_exists($path = $root.$view.EXT))
{
return $path;
}
}
/** /**
* Create a new view instance. * Create a new view instance.
* *
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment