Merge branch '98-implement-hybrid-router' into 'master'
Implemented renewed Routing and Output system. Everything is in accordance with issue #89 and #90. > Closes #89 > Closes #90 > Closes #98 See merge request !47
This commit is contained in:
commit
625e7ffa2b
|
@ -24,3 +24,4 @@ Modules/admin/themes/adminlte2.1/bootstrap/
|
|||
doc
|
||||
nbproject
|
||||
Application/Cache
|
||||
Application/Logs
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
return array(
|
||||
'cache_file_path' => '',
|
||||
'cache_query_string' => false,
|
||||
'memcached' => array(
|
||||
'default' => array(
|
||||
'hostname' => '127.0.0.1',
|
||||
|
|
|
@ -11,12 +11,13 @@ return array(
|
|||
'username' => '',
|
||||
'password' => '',
|
||||
'database' => '',
|
||||
'dbdriver' => 'mysqli',
|
||||
'dbdriver' => '',
|
||||
'subdriver'=> '',
|
||||
'dbprefix' => '',
|
||||
'pconnect' => FALSE,
|
||||
'db_debug' => FALSE,
|
||||
'cache_on' => FALSE,
|
||||
'cachedir' => '',
|
||||
'cachedir' => 'Application/Cache',
|
||||
'char_set' => 'utf8',
|
||||
'dbcollat' => 'utf8_general_ci',
|
||||
'swap_pre' => '',
|
||||
|
@ -24,7 +25,6 @@ return array(
|
|||
'compress' => FALSE,
|
||||
'stricton' => FALSE,
|
||||
'failover' => array(),
|
||||
'save_queries' => TRUE
|
||||
),
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<?php return array (
|
||||
'debug' => false,
|
||||
'error_reporting' => true,
|
||||
'log_to_file' => false,
|
||||
'logger_template' => 'logger_default',
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
'SITE_URL' => '',
|
||||
'SITE_DOMAIN' => '',
|
||||
'SERVER_NAME' => '',
|
||||
'SITE_LOGO_URL' => '',
|
||||
'base_url' => '',
|
||||
'index_page' => 'index.php',
|
||||
'server_name' => '',
|
||||
|
||||
'administrator_mail' => '',
|
||||
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
// '/^alias(|\-(?P<function>.*?))$/' => array(
|
||||
// 'controller' => 'home'
|
||||
// ),
|
||||
'/^(?P<controller>.*?)(|\/(?P<function>.*?)(|\/(?P<parameters>.*?)))$/',
|
||||
);
|
||||
|
|
|
@ -84,4 +84,7 @@ return array(
|
|||
*/
|
||||
'url_suffix' => '',
|
||||
|
||||
'default_controller' => 'standard',
|
||||
'default_function' => 'index',
|
||||
|
||||
);
|
||||
|
|
|
@ -54,6 +54,7 @@ class Standard extends ControllerAbstract
|
|||
*/
|
||||
public function index($path = null)
|
||||
{
|
||||
$this->output->cache(60);
|
||||
$this->layout->view('home');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
use FuzeWorks\Logger;
|
||||
use Fuzeworks\Factory;
|
||||
use FuzeWorks\Core;
|
||||
|
||||
/**
|
||||
* Database Cache Class
|
||||
|
@ -43,17 +44,9 @@ use Fuzeworks\Factory;
|
|||
* @author EllisLab Dev Team
|
||||
* @link https://codeigniter.com/user_guide/database/
|
||||
* @license http://opensource.org/licenses/MIT MIT License
|
||||
* @todo Fix URI
|
||||
*/
|
||||
class FW_DB_Cache {
|
||||
|
||||
/**
|
||||
* CI Singleton
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $CI;
|
||||
|
||||
/**
|
||||
* Database object
|
||||
*
|
||||
|
@ -81,7 +74,7 @@ class FW_DB_Cache {
|
|||
*/
|
||||
public function __construct(&$db)
|
||||
{
|
||||
// Assign the main CI object to $this->CI and load the file helper since we use it a lot
|
||||
$this->db =& $db;
|
||||
$this->factory = Factory::getInstance();
|
||||
$this->factory->helpers->load('file');
|
||||
|
||||
|
@ -121,7 +114,7 @@ class FW_DB_Cache {
|
|||
return $this->db->cache_off();
|
||||
}
|
||||
|
||||
if ( ! is_really_writable($path))
|
||||
if ( ! Core::isReallyWritable($path))
|
||||
{
|
||||
Logger::logDebug('DB cache dir not writable: '.$path);
|
||||
|
||||
|
@ -146,8 +139,8 @@ class FW_DB_Cache {
|
|||
*/
|
||||
public function read($sql)
|
||||
{
|
||||
$segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);
|
||||
$segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);
|
||||
$segment_one = ($this->factory->uri->segment(1) == FALSE) ? 'default' : $this->factory->uri->segment(1);
|
||||
$segment_two = ($this->factory->uri->segment(2) == FALSE) ? 'index' : $this->factory->uri->segment(2);
|
||||
$filepath = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'.md5($sql);
|
||||
|
||||
if (FALSE === ($cachedata = @file_get_contents($filepath)))
|
||||
|
@ -169,8 +162,8 @@ class FW_DB_Cache {
|
|||
*/
|
||||
public function write($sql, $object)
|
||||
{
|
||||
$segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);
|
||||
$segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);
|
||||
$segment_one = ($this->factory->uri->segment(1) == FALSE) ? 'default' : $this->factory->uri->segment(1);
|
||||
$segment_two = ($this->factory->uri->segment(2) == FALSE) ? 'index' : $this->factory->uri->segment(2);
|
||||
$dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/';
|
||||
$filename = md5($sql);
|
||||
|
||||
|
@ -201,12 +194,12 @@ class FW_DB_Cache {
|
|||
{
|
||||
if ($segment_one === '')
|
||||
{
|
||||
$segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);
|
||||
$segment_one = ($this->factory->uri->segment(1) == FALSE) ? 'default' : $this->factory->uri->segment(1);
|
||||
}
|
||||
|
||||
if ($segment_two === '')
|
||||
{
|
||||
$segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);
|
||||
$segment_two = ($this->factory->uri->segment(2) == FALSE) ? 'index' : $this->factory->uri->segment(2);
|
||||
}
|
||||
|
||||
$dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/';
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
* @version Version 0.0.1
|
||||
*/
|
||||
|
||||
use FuzeWorks\Factory;
|
||||
use FuzeWorks\Logger;
|
||||
use FuzeWorks\DatabaseException;
|
||||
use FuzeWorks\Utf8;
|
||||
|
@ -375,7 +376,7 @@ abstract class FW_DB_driver {
|
|||
|
||||
$this->factory = Factory::getInstance();
|
||||
|
||||
Logger::log('Database Driver Class Initialized');
|
||||
Logger::log('Database Driver ' . get_class($this) . ' Initialized');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -1739,14 +1740,13 @@ abstract class FW_DB_driver {
|
|||
* @param string any "swap" values
|
||||
* @param bool whether to localize the message
|
||||
* @return string sends the application/views/errors/error_db.php template
|
||||
* @todo FIX THIS
|
||||
*/
|
||||
public function display_error($error = '', $swap = '', $native = FALSE)
|
||||
{
|
||||
// First load the language
|
||||
$LANG = Language::get('db');
|
||||
Language::get('db');
|
||||
|
||||
$heading = $LANG->line('db_error_heading');
|
||||
$heading = Language::line('db_error_heading');
|
||||
|
||||
if ($native === TRUE)
|
||||
{
|
||||
|
@ -1754,7 +1754,7 @@ abstract class FW_DB_driver {
|
|||
}
|
||||
else
|
||||
{
|
||||
$message = is_array($error) ? $error : array(str_replace('%s', $swap, $LANG->line($error)));
|
||||
$message = is_array($error) ? $error : array(str_replace('%s', $swap, Language::line($error)));
|
||||
}
|
||||
|
||||
// Find the most likely culprit of the error by going through
|
||||
|
@ -1774,14 +1774,17 @@ abstract class FW_DB_driver {
|
|||
if (strpos($call['file'], 'Core'.DS.'Database') === FALSE && strpos($call['class'], 'Loader') === FALSE)
|
||||
{
|
||||
// Found it - use a relative path for safety
|
||||
$message[] = 'Filename: '.str_replace(array(APPPATH, BASEPATH), '', $call['file']);
|
||||
$message[] = 'Filename: '.str_replace(array('Application', 'Core'), '', $call['file']);
|
||||
$message[] = 'Line Number: '.$call['line'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger::logError($heading . ' || ' . $message);
|
||||
Logger::logError($heading);
|
||||
foreach ($message as $message) {
|
||||
Logger::logError($message);
|
||||
}
|
||||
Logger::http_error(500);
|
||||
exit(8); // EXIT_DATABASE
|
||||
}
|
||||
|
|
|
@ -54,7 +54,14 @@ class routerRouteEvent extends Event
|
|||
/**
|
||||
* @var bool Whether the callable will be loaded directly after or not
|
||||
*/
|
||||
public $loadCallable;
|
||||
public $performLoading;
|
||||
|
||||
/**
|
||||
* Whether a cached page should be ignored or not
|
||||
*
|
||||
* @var bool true if cache should not be used
|
||||
*/
|
||||
public $cacheOverride = false;
|
||||
|
||||
/**
|
||||
* The current path input to FuzeWorks.
|
||||
|
@ -63,10 +70,20 @@ class routerRouteEvent extends Event
|
|||
*/
|
||||
public $path;
|
||||
|
||||
public function init($routes, $loadCallable, $path)
|
||||
public function init($routes, $performLoading, $path)
|
||||
{
|
||||
$this->routes = $routes;
|
||||
$this->loadCallable = $loadCallable;
|
||||
$this->performLoading = $performLoading;
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a cached page should be ignored or not
|
||||
*
|
||||
* @param bool $overrideCache true if cache should not be used
|
||||
*/
|
||||
public function overrideCache($bool = true)
|
||||
{
|
||||
$this->cacheOverride = $bool;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks.
|
||||
*
|
||||
* The FuzeWorks MVC PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2015 TechFuze
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
||||
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
||||
*
|
||||
* @link http://fuzeworks.techfuze.net
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 0.0.1
|
||||
*/
|
||||
|
||||
namespace FuzeWorks\Event;
|
||||
|
||||
use FuzeWorks\Event;
|
||||
|
||||
/**
|
||||
* Class routerSetPathEvent.
|
||||
*
|
||||
* Fired when the router's path is changing
|
||||
*
|
||||
* @author Abel Hoogeveen <abel@techfuze.net>
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
*/
|
||||
class routerSetPathEvent extends Event
|
||||
{
|
||||
/**
|
||||
* The path to be set to the router.
|
||||
*
|
||||
* @var string The new path
|
||||
*/
|
||||
public $path;
|
||||
|
||||
public function init($path)
|
||||
{
|
||||
$this->path = $path;
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ namespace FuzeWorks\Library;
|
|||
use FuzeWorks\Config;
|
||||
use FuzeWorks\Logger;
|
||||
use FuzeWorks\LibraryException;
|
||||
use FuzeWorks\Libraries;
|
||||
use FuzeWorks\Factory;
|
||||
use ReflectionObject;
|
||||
|
||||
/**
|
||||
|
@ -117,7 +117,7 @@ class FW_Driver_Library {
|
|||
}
|
||||
|
||||
// Get package paths and filename case variations to search
|
||||
$paths = Libraries::getLibraryPaths();
|
||||
$paths = Factory::getInstance()->libraries->getLibraryPaths();
|
||||
|
||||
// Is there an extension?
|
||||
$class_name = str_replace('{prefix}', $prefix, $child_name);
|
||||
|
|
|
@ -132,7 +132,7 @@ class FW_Email {
|
|||
/**
|
||||
* Number of characters to wrap at.
|
||||
*
|
||||
* @see CI_Email::$wordwrap
|
||||
* @see Email::$wordwrap
|
||||
* @var int
|
||||
*/
|
||||
public $wrapchars = 76;
|
||||
|
@ -227,7 +227,7 @@ class FW_Email {
|
|||
/**
|
||||
* BCC Batch max number size.
|
||||
*
|
||||
* @see CI_Email::$bcc_batch_mode
|
||||
* @see Email::$bcc_batch_mode
|
||||
* @var int
|
||||
*/
|
||||
public $bcc_batch_size = 200;
|
||||
|
@ -314,7 +314,7 @@ class FW_Email {
|
|||
/**
|
||||
* Debug messages
|
||||
*
|
||||
* @see CI_Email::print_debugger()
|
||||
* @see Email::print_debugger()
|
||||
* @var string
|
||||
*/
|
||||
protected $_debug_msg = array();
|
||||
|
@ -357,7 +357,7 @@ class FW_Email {
|
|||
/**
|
||||
* Valid $protocol values
|
||||
*
|
||||
* @see CI_Email::$protocol
|
||||
* @see Email::$protocol
|
||||
* @var string[]
|
||||
*/
|
||||
protected $_protocols = array('mail', 'sendmail', 'smtp');
|
||||
|
@ -377,7 +377,7 @@ class FW_Email {
|
|||
*
|
||||
* Valid mail encodings
|
||||
*
|
||||
* @see CI_Email::$_encoding
|
||||
* @see Email::$_encoding
|
||||
* @var string[]
|
||||
*/
|
||||
protected $_bit_depths = array('7bit', '8bit');
|
||||
|
@ -447,7 +447,7 @@ class FW_Email {
|
|||
* Initialize preferences
|
||||
*
|
||||
* @param array
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function initialize($config = array())
|
||||
{
|
||||
|
@ -480,7 +480,7 @@ class FW_Email {
|
|||
* Initialize the Email Data
|
||||
*
|
||||
* @param bool
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function clear($clear_attachments = FALSE)
|
||||
{
|
||||
|
@ -514,7 +514,7 @@ class FW_Email {
|
|||
* @param string $from
|
||||
* @param string $name
|
||||
* @param string $return_path = NULL Return-Path
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function from($from, $name = '', $return_path = NULL)
|
||||
{
|
||||
|
@ -562,7 +562,7 @@ class FW_Email {
|
|||
*
|
||||
* @param string
|
||||
* @param string
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function reply_to($replyto, $name = '')
|
||||
{
|
||||
|
@ -602,7 +602,7 @@ class FW_Email {
|
|||
* Set Recipients
|
||||
*
|
||||
* @param string
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function to($to)
|
||||
{
|
||||
|
@ -630,7 +630,7 @@ class FW_Email {
|
|||
* Set CC
|
||||
*
|
||||
* @param string
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function cc($cc)
|
||||
{
|
||||
|
@ -658,7 +658,7 @@ class FW_Email {
|
|||
*
|
||||
* @param string
|
||||
* @param string
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function bcc($bcc, $limit = '')
|
||||
{
|
||||
|
@ -693,7 +693,7 @@ class FW_Email {
|
|||
* Set Email Subject
|
||||
*
|
||||
* @param string
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function subject($subject)
|
||||
{
|
||||
|
@ -708,7 +708,7 @@ class FW_Email {
|
|||
* Set Body
|
||||
*
|
||||
* @param string
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function message($body)
|
||||
{
|
||||
|
@ -737,7 +737,7 @@ class FW_Email {
|
|||
* @param string $disposition = 'attachment'
|
||||
* @param string $newname = NULL
|
||||
* @param string $mime = ''
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function attach($file, $disposition = '', $newname = NULL, $mime = '')
|
||||
{
|
||||
|
@ -810,7 +810,7 @@ class FW_Email {
|
|||
*
|
||||
* @param string
|
||||
* @param string
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function set_header($header, $value)
|
||||
{
|
||||
|
@ -844,7 +844,7 @@ class FW_Email {
|
|||
* Set Multipart Value
|
||||
*
|
||||
* @param string
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function set_alt_message($str)
|
||||
{
|
||||
|
@ -858,7 +858,7 @@ class FW_Email {
|
|||
* Set Mailtype
|
||||
*
|
||||
* @param string
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function set_mailtype($type = 'text')
|
||||
{
|
||||
|
@ -872,7 +872,7 @@ class FW_Email {
|
|||
* Set Wordwrap
|
||||
*
|
||||
* @param bool
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function set_wordwrap($wordwrap = TRUE)
|
||||
{
|
||||
|
@ -886,7 +886,7 @@ class FW_Email {
|
|||
* Set Protocol
|
||||
*
|
||||
* @param string
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function set_protocol($protocol = 'mail')
|
||||
{
|
||||
|
@ -900,7 +900,7 @@ class FW_Email {
|
|||
* Set Priority
|
||||
*
|
||||
* @param int
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function set_priority($n = 3)
|
||||
{
|
||||
|
@ -914,7 +914,7 @@ class FW_Email {
|
|||
* Set Newline Character
|
||||
*
|
||||
* @param string
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function set_newline($newline = "\n")
|
||||
{
|
||||
|
@ -928,7 +928,7 @@ class FW_Email {
|
|||
* Set CRLF
|
||||
*
|
||||
* @param string
|
||||
* @return CI_Email
|
||||
* @return Email
|
||||
*/
|
||||
public function set_crlf($crlf = "\n")
|
||||
{
|
||||
|
|
|
@ -184,7 +184,7 @@ class FW_Encryption {
|
|||
* Initialize
|
||||
*
|
||||
* @param array $params Configuration parameters
|
||||
* @return CI_Encryption
|
||||
* @return Encryption
|
||||
*/
|
||||
public function initialize(array $params)
|
||||
{
|
||||
|
|
|
@ -96,6 +96,11 @@ class Config
|
|||
return $this->cfg[$configName];
|
||||
}
|
||||
|
||||
public function __get($configName)
|
||||
{
|
||||
return $this->getConfig($configName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the file exists and, if so, load the ConfigORM
|
||||
*
|
||||
|
|
|
@ -70,6 +70,15 @@ class Core
|
|||
*/
|
||||
public static function init()
|
||||
{
|
||||
// Set the CWD for usage in the shutdown function+
|
||||
self::$cwd = getcwd();
|
||||
|
||||
// If the environment is not yet defined, use production settings
|
||||
if (!defined('ENVIRONMENT'))
|
||||
{
|
||||
define('ENVIRONMENT', 'PRODUCTION');
|
||||
}
|
||||
|
||||
// Defines the time the framework starts. Used for timing functions in the framework
|
||||
if (!defined('STARTTIME')) {
|
||||
define('STARTTIME', microtime(true));
|
||||
|
@ -112,9 +121,6 @@ class Core
|
|||
if ($event->isCancelled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set the CWD for usage in the shutdown function+
|
||||
self::$cwd = getcwd();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -172,10 +178,15 @@ class Core
|
|||
chdir(self::$cwd);
|
||||
|
||||
// Fire the Shutdown event
|
||||
Events::fireEvent('coreShutdownEvent');
|
||||
$event = Events::fireEvent('coreShutdownEvent');
|
||||
|
||||
// And end the logger
|
||||
Logger::shutdown();
|
||||
if ($event->isCancelled() === false)
|
||||
{
|
||||
// If the output should be displayed, send the final render and parse the logger
|
||||
Logger::shutdownError();
|
||||
Factory::getInstance()->output->_display();
|
||||
Logger::shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -190,6 +201,7 @@ class Core
|
|||
if (file_exists($file)) {
|
||||
include $file;
|
||||
Logger::log('Loaded Composer');
|
||||
Logger::loadComposer();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -216,4 +228,170 @@ class Core
|
|||
|
||||
return $_is_php[$version];
|
||||
}
|
||||
|
||||
public static function isCli()
|
||||
{
|
||||
return (PHP_SAPI === 'cli' OR defined('STDIN'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is HTTPS?
|
||||
*
|
||||
* Determines if the application is accessed via an encrypted
|
||||
* (HTTPS) connection.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isHttps()
|
||||
{
|
||||
if ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
elseif ( ! empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off')
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for file writability
|
||||
*
|
||||
* is_writable() returns TRUE on Windows servers when you really can't write to
|
||||
* the file, based on the read-only attribute. is_writable() is also unreliable
|
||||
* on Unix servers if safe_mode is on.
|
||||
*
|
||||
* @link https://bugs.php.net/bug.php?id=54709
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
public static function isReallyWritable($file)
|
||||
{
|
||||
// If we're on a Unix server with safe_mode off we call is_writable
|
||||
if (DIRECTORY_SEPARATOR === '/' && (self::isPHP('5.4') OR ! ini_get('safe_mode')))
|
||||
{
|
||||
return is_writable($file);
|
||||
}
|
||||
|
||||
/* For Windows servers and safe_mode "on" installations we'll actually
|
||||
* write a file then read it. Bah...
|
||||
*/
|
||||
if (is_dir($file))
|
||||
{
|
||||
$file = rtrim($file, '/').'/'.md5(mt_rand());
|
||||
if (($fp = @fopen($file, 'ab')) === FALSE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
@chmod($file, 0777);
|
||||
@unlink($file);
|
||||
return TRUE;
|
||||
}
|
||||
elseif ( ! is_file($file) OR ($fp = @fopen($file, 'ab')) === FALSE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set HTTP Status Header
|
||||
*
|
||||
* @param int the status code
|
||||
* @param string
|
||||
* @return void
|
||||
*/
|
||||
public static function setStatusHeader($code = 200, $text = '')
|
||||
{
|
||||
if (self::isCli())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($code) OR ! is_numeric($code))
|
||||
{
|
||||
throw new Exception('Status codes must be numeric', 1);
|
||||
}
|
||||
|
||||
if (empty($text))
|
||||
{
|
||||
is_int($code) OR $code = (int) $code;
|
||||
$stati = array(
|
||||
100 => 'Continue',
|
||||
101 => 'Switching Protocols',
|
||||
|
||||
200 => 'OK',
|
||||
201 => 'Created',
|
||||
202 => 'Accepted',
|
||||
203 => 'Non-Authoritative Information',
|
||||
204 => 'No Content',
|
||||
205 => 'Reset Content',
|
||||
206 => 'Partial Content',
|
||||
|
||||
300 => 'Multiple Choices',
|
||||
301 => 'Moved Permanently',
|
||||
302 => 'Found',
|
||||
303 => 'See Other',
|
||||
304 => 'Not Modified',
|
||||
305 => 'Use Proxy',
|
||||
307 => 'Temporary Redirect',
|
||||
|
||||
400 => 'Bad Request',
|
||||
401 => 'Unauthorized',
|
||||
402 => 'Payment Required',
|
||||
403 => 'Forbidden',
|
||||
404 => 'Not Found',
|
||||
405 => 'Method Not Allowed',
|
||||
406 => 'Not Acceptable',
|
||||
407 => 'Proxy Authentication Required',
|
||||
408 => 'Request Timeout',
|
||||
409 => 'Conflict',
|
||||
410 => 'Gone',
|
||||
411 => 'Length Required',
|
||||
412 => 'Precondition Failed',
|
||||
413 => 'Request Entity Too Large',
|
||||
414 => 'Request-URI Too Long',
|
||||
415 => 'Unsupported Media Type',
|
||||
416 => 'Requested Range Not Satisfiable',
|
||||
417 => 'Expectation Failed',
|
||||
422 => 'Unprocessable Entity',
|
||||
|
||||
500 => 'Internal Server Error',
|
||||
501 => 'Not Implemented',
|
||||
502 => 'Bad Gateway',
|
||||
503 => 'Service Unavailable',
|
||||
504 => 'Gateway Timeout',
|
||||
505 => 'HTTP Version Not Supported'
|
||||
);
|
||||
|
||||
if (isset($stati[$code]))
|
||||
{
|
||||
$text = $stati[$code];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new CoreException('No status text available. Please check your status code number or supply your own message text.', 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (strpos(PHP_SAPI, 'cgi') === 0)
|
||||
{
|
||||
header('Status: '.$code.' '.$text, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
$server_protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
|
||||
header($server_protocol.' '.$code.' '.$text, TRUE, $code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,11 +98,11 @@ class Factory
|
|||
$this->instances['Database'] = new Database();
|
||||
$this->instances['Language'] = new Language();
|
||||
$this->instances['Utf8'] = new Utf8();
|
||||
$this->instances['URI'] = new URI();
|
||||
$this->instances['Uri'] = new URI();
|
||||
$this->instances['Security'] = new Security();
|
||||
$this->instances['Input'] = new Input();
|
||||
$this->instances['Router'] = new Router();
|
||||
$this->instances['Output'] = new Output();
|
||||
$this->instances['Router'] = new Router();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ class Input {
|
|||
*
|
||||
* Parsed from php://input at runtime
|
||||
*
|
||||
* @see CI_Input::input_stream()
|
||||
* @see Input::input_stream()
|
||||
* @var array
|
||||
*/
|
||||
protected $_input_stream;
|
||||
|
@ -685,7 +685,7 @@ class Input {
|
|||
// Clean UTF-8 if supported
|
||||
if (UTF8_ENABLED === TRUE)
|
||||
{
|
||||
$str = UTF8::clean_string($str);
|
||||
$str = $this->factory->utf8->clean_string($str);
|
||||
}
|
||||
|
||||
// Remove control characters
|
||||
|
@ -734,7 +734,7 @@ class Input {
|
|||
// Clean UTF-8 if supported
|
||||
if (UTF8_ENABLED === TRUE)
|
||||
{
|
||||
return UTF8::clean_string($str);
|
||||
return $this->factory->utf8->clean_string($str);
|
||||
}
|
||||
|
||||
return $str;
|
||||
|
|
|
@ -95,23 +95,33 @@ class Layout
|
|||
private static $current_engine;
|
||||
|
||||
/**
|
||||
* Retrieve a template file using a string and a directory and immediatly echo it.
|
||||
* Retrieve a template file using a string and a directory and immediatly parse it to the output class.
|
||||
*
|
||||
* What template file gets loaded depends on the template engine that is being used.
|
||||
* PHP for example uses .php files. Providing this function with 'home/dashboard' will load the home/view.dashboard.php file.
|
||||
* You can also provide no particular engine, and the manager will decide what template to load.
|
||||
* Remember that doing so will result in a LayoutException when multiple compatible files are found.
|
||||
*
|
||||
* @param string $file File to load
|
||||
* @param string $directory Directory to load it from
|
||||
* @param string $file File to load
|
||||
* @param string $directory Directory to load it from
|
||||
* @param bool $directOutput Whether to directly output the result with an echo or send it to the output class. True if echo
|
||||
*
|
||||
* @throws LayoutException On error
|
||||
*/
|
||||
public static function view($file, $directory = null)
|
||||
public static function view($file, $directory = null, $directOutput = false)
|
||||
{
|
||||
$output = Factory::getInstance()->output;
|
||||
$directory = (is_null($directory) ? self::$directory : $directory);
|
||||
echo self::get($file, $directory);
|
||||
|
||||
if ($directOutput === true)
|
||||
{
|
||||
echo self::get($file, $directory);
|
||||
}
|
||||
else
|
||||
{
|
||||
$output->append_output(self::get($file, $directory));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -146,11 +156,9 @@ class Layout
|
|||
}
|
||||
|
||||
// Then assign some basic variables for the template
|
||||
self::$assigned_variables['viewDir'] = Config::get('main')->SITE_URL.preg_replace('#/+#', '/', substr(self::$directory.'/', -strlen(self::$directory.'/')));
|
||||
self::$assigned_variables['siteURL'] = Config::get('main')->SITE_URL;
|
||||
self::$assigned_variables['siteLogo'] = Config::get('main')->SITE_LOGO_URL;
|
||||
self::$assigned_variables['serverName'] = Config::get('main')->SERVER_NAME;
|
||||
self::$assigned_variables['siteDomain'] = Config::get('main')->SITE_DOMAIN;
|
||||
self::$assigned_variables['viewDir'] = Config::get('main')->base_url.preg_replace('#/+#', '/', substr(self::$directory.'/', -strlen(self::$directory.'/')));
|
||||
self::$assigned_variables['siteURL'] = Config::get('main')->base_url;
|
||||
self::$assigned_variables['serverName'] = Config::get('main')->server_name;
|
||||
self::$assigned_variables['adminMail'] = Config::get('main')->administrator_mail;
|
||||
self::$assigned_variables['contact'] = Config::get('contact')->toArray();
|
||||
|
||||
|
@ -469,8 +477,8 @@ class Layout
|
|||
|
||||
// Load the engines provided in this file
|
||||
self::registerEngine(new PHPEngine(), 'PHP', array('php'));
|
||||
self::registerEngine(new SmartyEngine(), 'Smarty', array('tpl'));
|
||||
self::registerEngine(new JsonEngine(), 'JSON', array('json'));
|
||||
self::registerEngine(new SmartyEngine(), 'Smarty', array('tpl'));
|
||||
self::$engines_loaded = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
*/
|
||||
|
||||
namespace FuzeWorks;
|
||||
use Tracy\Debugger;
|
||||
|
||||
/**
|
||||
* Logger Class.
|
||||
|
@ -115,6 +116,13 @@ class Logger {
|
|||
*/
|
||||
public static $markPoints = array();
|
||||
|
||||
/**
|
||||
* Whether to use the Tracy debugger instead of FuzeWorks Logger
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public static $useTracy = false;
|
||||
|
||||
/**
|
||||
* Initiates the Logger.
|
||||
*
|
||||
|
@ -127,18 +135,60 @@ class Logger {
|
|||
set_Exception_handler(array('\FuzeWorks\Logger', 'exceptionHandler'));
|
||||
error_reporting(false);
|
||||
}
|
||||
self::$debug = Config::get('error')->debug;
|
||||
self::$debug = (ENVIRONMENT === 'DEVELOPMENT');
|
||||
self::$log_to_file = Config::get('error')->log_to_file;
|
||||
self::$logger_template = Config::get('error')->logger_template;
|
||||
self::newLevel('Logger Initiated');
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to load Trace Debugger when available
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function loadComposer()
|
||||
{
|
||||
if (class_exists('\Tracy\Debugger', true))
|
||||
{
|
||||
if (ENVIRONMENT === 'DEVELOPMENT')
|
||||
{
|
||||
Debugger::enable(Debugger::DEVELOPMENT, realpath('Application'.DS.'Logs'));
|
||||
}
|
||||
else
|
||||
{
|
||||
Debugger::enable(Debugger::PRODUCTION, realpath('Application'.DS.'Logs'));
|
||||
}
|
||||
self::$useTracy = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to be run upon FuzeWorks shutdown.
|
||||
*
|
||||
* Logs data to screen when requested to do so
|
||||
*/
|
||||
public static function shutdown() {
|
||||
// And finally stop the Logging
|
||||
self::stopLevel();
|
||||
|
||||
if (self::$debug === true || self::$print_to_screen) {
|
||||
self::log('Parsing debug log');
|
||||
self::logToScreen();
|
||||
}
|
||||
|
||||
if (self::$log_to_file == true)
|
||||
{
|
||||
self::logToFile();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to be run upon FuzeWorks shutdown.
|
||||
*
|
||||
* Logs a fatal error and outputs the log when configured or requested to do so
|
||||
*/
|
||||
public static function shutdown() {
|
||||
public static function shutdownError()
|
||||
{
|
||||
// Load last error if thrown
|
||||
$errfile = 'Unknown file';
|
||||
$errstr = 'shutdown';
|
||||
|
@ -153,20 +203,13 @@ class Logger {
|
|||
$errstr = $error['message'];
|
||||
|
||||
// Log it!
|
||||
Factory::getInstance()->output->set_output('');
|
||||
self::errorHandler($errno, $errstr, $errfile, $errline);
|
||||
}
|
||||
|
||||
// And finally stop the Logging
|
||||
self::stopLevel();
|
||||
|
||||
if (self::$debug == true || self::$print_to_screen) {
|
||||
self::log('Parsing debug log');
|
||||
self::logToScreen();
|
||||
}
|
||||
|
||||
if (self::$log_to_file == true)
|
||||
{
|
||||
self::logToFile();
|
||||
if (self::$useTracy === false)
|
||||
{
|
||||
self::http_error('500');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,7 +275,7 @@ class Logger {
|
|||
|
||||
Layout::reset();
|
||||
Layout::assign('Logs', self::$Logs);
|
||||
Layout::view(self::$logger_template, 'Core'.DS.'Views');
|
||||
Layout::view(self::$logger_template, 'Core'.DS.'Views', true);
|
||||
}
|
||||
|
||||
public static function logToFile()
|
||||
|
@ -314,6 +357,12 @@ class Logger {
|
|||
|
||||
self::$infoErrors[] = $LOG;
|
||||
self::$Logs[] = $LOG;
|
||||
|
||||
// Use Tracy when we can
|
||||
if (self::$useTracy === true)
|
||||
{
|
||||
Debugger::log($msg, 'info');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -334,6 +383,12 @@ class Logger {
|
|||
|
||||
self::$debugErrors[] = $LOG;
|
||||
self::$Logs[] = $LOG;
|
||||
|
||||
// Use Tracy when we can
|
||||
if (self::$useTracy === true)
|
||||
{
|
||||
Debugger::log($msg, 'debug');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -354,6 +409,12 @@ class Logger {
|
|||
|
||||
self::$criticalErrors[] = $LOG;
|
||||
self::$Logs[] = $LOG;
|
||||
|
||||
// Use Tracy when we can
|
||||
if (self::$useTracy === true)
|
||||
{
|
||||
Debugger::log($msg, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -374,6 +435,12 @@ class Logger {
|
|||
|
||||
self::$warningErrors[] = $LOG;
|
||||
self::$Logs[] = $LOG;
|
||||
|
||||
// Use Tracy when we can
|
||||
if (self::$useTracy === true)
|
||||
{
|
||||
Debugger::log($msg, 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -393,6 +460,12 @@ class Logger {
|
|||
'runtime' => round(self::getRelativeTime(), 4),);
|
||||
|
||||
self::$Logs[] = $LOG;
|
||||
|
||||
// Use Tracy when we can
|
||||
if (self::$useTracy === true)
|
||||
{
|
||||
Debugger::log($msg, 'info');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -385,7 +385,7 @@ class Modules
|
|||
if ($cache)
|
||||
{
|
||||
// Retrieve the cache if possible
|
||||
$cache = Libraries::getDriver('cache');
|
||||
$cache = Factory::getInstance()->libraries->getDriver('cache');
|
||||
$cacheData = $cache->$cachingMethod->get('moduleRegisters');
|
||||
|
||||
if ( ! is_bool($cacheData) )
|
||||
|
@ -403,7 +403,7 @@ class Modules
|
|||
self::$advertiseRegister = $advertiseRegister;
|
||||
self::$module_routes = $routeRegister;
|
||||
foreach ($routeRegister as $route => $name) {
|
||||
Router::addRoute($route, array('\FuzeWorks\Modules', 'moduleCallable'), true);
|
||||
Factory::getInstance()->router->addRoute($route, array('callable' => array('\FuzeWorks\Modules', 'moduleCallable')), true);
|
||||
}
|
||||
Logger::stopLevel();
|
||||
return true;
|
||||
|
@ -489,7 +489,7 @@ class Modules
|
|||
foreach ($cfg->routes as $route) {
|
||||
// Create the route and callable and parse them
|
||||
$callable = array('\FuzeWorks\Modules', 'moduleCallable');
|
||||
Router::addRoute($route, $callable, true);
|
||||
Factory::getInstance()->router->addRoute($route, array('callable' => $callable), true);
|
||||
self::$module_routes[$route] = $name;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,6 +115,10 @@ class Output {
|
|||
*/
|
||||
public $parse_exec_vars = TRUE;
|
||||
|
||||
protected $config;
|
||||
protected $uri;
|
||||
protected $router;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
|
@ -124,15 +128,20 @@ class Output {
|
|||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$factory = Factory::getInstance();
|
||||
$this->config = $factory->config;
|
||||
$this->uri = $factory->uri;
|
||||
$this->router = $factory->router;
|
||||
|
||||
$this->_zlib_oc = (bool) ini_get('zlib.output_compression');
|
||||
$this->_compress_output = (
|
||||
$this->_zlib_oc === FALSE
|
||||
&& Config::get('main')->compress_output === TRUE
|
||||
&& $this->config->main->compress_output === TRUE
|
||||
&& extension_loaded('zlib')
|
||||
);
|
||||
|
||||
// Get mime types for later
|
||||
$this->mimes = Config::get('mimes')->toArray();
|
||||
$this->mimes = $this->config->mimes->toArray();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -157,7 +166,7 @@ class Output {
|
|||
* Sets the output string.
|
||||
*
|
||||
* @param string $output Output data
|
||||
* @return CI_Output
|
||||
* @return Output
|
||||
*/
|
||||
public function set_output($output)
|
||||
{
|
||||
|
@ -173,7 +182,7 @@ class Output {
|
|||
* Appends data onto the output string.
|
||||
*
|
||||
* @param string $output Data to append
|
||||
* @return CI_Output
|
||||
* @return Output
|
||||
*/
|
||||
public function append_output($output)
|
||||
{
|
||||
|
@ -193,7 +202,7 @@ class Output {
|
|||
*
|
||||
* @param string $header Header
|
||||
* @param bool $replace Whether to replace the old header value, if already set
|
||||
* @return CI_Output
|
||||
* @return Output
|
||||
*/
|
||||
public function set_header($header, $replace = TRUE)
|
||||
{
|
||||
|
@ -217,7 +226,7 @@ class Output {
|
|||
*
|
||||
* @param string $mime_type Extension of the file we're outputting
|
||||
* @param string $charset Character set (default: NULL)
|
||||
* @return CI_Output
|
||||
* @return Output
|
||||
*/
|
||||
public function set_content_type($mime_type, $charset = NULL)
|
||||
{
|
||||
|
@ -314,13 +323,11 @@ class Output {
|
|||
*
|
||||
* @param int $code Status code (default: 200)
|
||||
* @param string $text Optional message
|
||||
* @todo Fix this
|
||||
* @return CI_Output
|
||||
* @return Output
|
||||
*/
|
||||
public function set_status_header($code = 200, $text = '')
|
||||
{
|
||||
return $this;
|
||||
set_status_header($code, $text);
|
||||
Core::setStatusHeader($code, $text);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -330,7 +337,7 @@ class Output {
|
|||
* Enable/disable Profiler
|
||||
*
|
||||
* @param bool $val TRUE to enable or FALSE to disable
|
||||
* @return CI_Output
|
||||
* @return Output
|
||||
*/
|
||||
public function enable_profiler($val = TRUE)
|
||||
{
|
||||
|
@ -347,7 +354,7 @@ class Output {
|
|||
* Profiler section display.
|
||||
*
|
||||
* @param array $sections Profiler sections
|
||||
* @return CI_Output
|
||||
* @return Output
|
||||
*/
|
||||
public function set_profiler_sections($sections)
|
||||
{
|
||||
|
@ -371,7 +378,7 @@ class Output {
|
|||
* Set Cache
|
||||
*
|
||||
* @param int $time Cache expiration time in minutes
|
||||
* @return CI_Output
|
||||
* @return Output
|
||||
*/
|
||||
public function cache($time)
|
||||
{
|
||||
|
@ -391,23 +398,21 @@ class Output {
|
|||
* Note: All "view" data is automatically put into $this->final_output
|
||||
* by controller class.
|
||||
*
|
||||
* @uses CI_Output::$final_output
|
||||
* @uses Output::$final_output
|
||||
* @param string $output Output data override
|
||||
* @return void
|
||||
* @todo Implement cache
|
||||
*/
|
||||
public function _display($output = '')
|
||||
{
|
||||
// Note: We use load_class() because we can't use $CI =& get_instance()
|
||||
// since this function is sometimes called by the caching mechanism,
|
||||
// which happens before the CI super object is available.
|
||||
$BM =& load_class('Benchmark', 'core');
|
||||
$CFG =& load_class('Config', 'core');
|
||||
|
||||
$router = Factory::getInstance()->router;
|
||||
// Grab the super object if we can.
|
||||
if (class_exists('CI_Controller', FALSE))
|
||||
if ($router->getCallable() === null)
|
||||
{
|
||||
$CI =& get_instance();
|
||||
$use_cache = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$use_cache = false;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -423,10 +428,10 @@ class Output {
|
|||
// Do we need to write a cache file? Only if the controller does not have its
|
||||
// own _output() method and we are not dealing with a cache file, which we
|
||||
// can determine by the existence of the $CI object above
|
||||
//if ($this->cache_expiration > 0 && isset($CI) && ! method_exists($CI, '_output'))
|
||||
//{
|
||||
// $this->_write_cache($output);
|
||||
//}
|
||||
if ($this->cache_expiration > 0 && $use_cache === false)
|
||||
{
|
||||
$this->_write_cache($output);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
@ -444,12 +449,12 @@ class Output {
|
|||
// --------------------------------------------------------------------
|
||||
|
||||
// Is compression requested?
|
||||
//if (isset($CI) // This means that we're not serving a cache file, if we were, it would already be compressed
|
||||
// && $this->_compress_output === TRUE
|
||||
// && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
|
||||
//{
|
||||
// ob_start('ob_gzhandler');
|
||||
//}
|
||||
if ($use_cache === false // This means that we're not serving a cache file, if we were, it would already be compressed
|
||||
&& $this->_compress_output === TRUE
|
||||
&& isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
|
||||
{
|
||||
ob_start('ob_gzhandler');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
@ -464,10 +469,7 @@ class Output {
|
|||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Does the $CI object exist?
|
||||
// If not we know we are dealing with a cache file so we'll
|
||||
// simply echo out the data and exit.
|
||||
if ( ! isset($CI))
|
||||
if ( $use_cache === true)
|
||||
{
|
||||
if ($this->_compress_output === TRUE)
|
||||
{
|
||||
|
@ -494,8 +496,11 @@ class Output {
|
|||
|
||||
// Do we need to generate profile data?
|
||||
// If so, load the Profile class and run it.
|
||||
/*if ($this->enable_profiler === TRUE)
|
||||
if ($this->enable_profiler === TRUE)
|
||||
{
|
||||
Logger::logWarning("Profiler not yet implemented");
|
||||
return;
|
||||
|
||||
$CI->load->library('profiler');
|
||||
if ( ! empty($this->_profiler_sections))
|
||||
{
|
||||
|
@ -511,16 +516,7 @@ class Output {
|
|||
}
|
||||
}
|
||||
|
||||
// Does the controller contain a function named _output()?
|
||||
// If so send the output there. Otherwise, echo it.
|
||||
if (method_exists($CI, '_output'))
|
||||
{
|
||||
$CI->_output($output);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo $output; // Send it to the browser!
|
||||
}*/
|
||||
echo $output;
|
||||
|
||||
Logger::log('Final output sent to browser');
|
||||
Logger::logDebug('Total execution time: '.$elapsed);
|
||||
|
@ -532,30 +528,24 @@ class Output {
|
|||
* Write Cache
|
||||
*
|
||||
* @param string $output Output data to cache
|
||||
* @todo Implement cache
|
||||
* @return void
|
||||
*/
|
||||
public function _write_cache($output)
|
||||
{
|
||||
Logger::logWarning("Cache is not implemented as of yet");
|
||||
return;
|
||||
$path = $this->config->cache->cache_file_path;
|
||||
$cache_path = ($path === '') ? 'Application'.DS.'Cache'.DS : $path;
|
||||
|
||||
|
||||
$CI =& get_instance();
|
||||
$path = $CI->config->item('cache_path');
|
||||
$cache_path = ($path === '') ? APPPATH.'cache/' : $path;
|
||||
|
||||
if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
|
||||
if ( ! is_dir($cache_path) OR ! Core::isReallyWritable($cache_path))
|
||||
{
|
||||
log_message('error', 'Unable to write cache file: '.$cache_path);
|
||||
Logger::logError('Unable to write cache file: '.$cache_path);
|
||||
return;
|
||||
}
|
||||
|
||||
$uri = $CI->config->item('base_url')
|
||||
.$CI->config->item('index_page')
|
||||
.$CI->uri->uri_string();
|
||||
$uri = $this->config->main->base_url
|
||||
.$this->config->main->index_page
|
||||
.$this->uri->uri_string();
|
||||
|
||||
if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
|
||||
if (($cache_query_string = $this->config->cache->cache_query_string) && ! empty($_SERVER['QUERY_STRING']))
|
||||
{
|
||||
if (is_array($cache_query_string))
|
||||
{
|
||||
|
@ -571,7 +561,7 @@ class Output {
|
|||
|
||||
if ( ! $fp = @fopen($cache_path, 'w+b'))
|
||||
{
|
||||
log_message('error', 'Unable to write cache file: '.$cache_path);
|
||||
Logger::logError('Unable to write cache file: '.$cache_path);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -612,7 +602,7 @@ class Output {
|
|||
}
|
||||
else
|
||||
{
|
||||
log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
|
||||
Logger::logError('Unable to secure a file lock for file at: '.$cache_path);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -621,7 +611,7 @@ class Output {
|
|||
if (is_int($result))
|
||||
{
|
||||
chmod($cache_path, 0640);
|
||||
log_message('debug', 'Cache file written: '.$cache_path);
|
||||
Logger::logDebug('Cache file written: '.$cache_path);
|
||||
|
||||
// Send HTTP cache-control headers to browser to match file cache settings.
|
||||
$this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
|
||||
|
@ -629,7 +619,7 @@ class Output {
|
|||
else
|
||||
{
|
||||
@unlink($cache_path);
|
||||
log_message('error', 'Unable to write the complete cache content at: '.$cache_path);
|
||||
Logger::logError('Unable to write the complete cache content at: '.$cache_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -638,26 +628,20 @@ class Output {
|
|||
/**
|
||||
* Update/serve cached output
|
||||
*
|
||||
* @uses CI_Config
|
||||
* @uses CI_URI
|
||||
* @todo Implement
|
||||
* @uses Config
|
||||
* @uses URI
|
||||
*
|
||||
* @param object &$CFG CI_Config class instance
|
||||
* @param object &$URI CI_URI class instance
|
||||
* @return bool TRUE on success or FALSE on failure
|
||||
*/
|
||||
public function _display_cache(&$CFG, &$URI)
|
||||
public function _display_cache()
|
||||
{
|
||||
Logger::logWarning("Cache is not implemented as of yet");
|
||||
return false;
|
||||
|
||||
|
||||
$cache_path = ($CFG->item('cache_path') === '') ? APPPATH.'cache/' : $CFG->item('cache_path');
|
||||
$cache_path = ($this->config->cache->cache_file_path === '') ? 'Application'.DS.'Cache'.DS : $this->config->cache->cache_file_path;
|
||||
|
||||
// Build the file path. The file name is an MD5 hash of the full URI
|
||||
$uri = $CFG->item('base_url').$CFG->item('index_page').$URI->uri_string;
|
||||
$main = $this->config->main;
|
||||
$uri = $main->base_url.$main->index_page.$this->uri->uri_string;
|
||||
|
||||
if (($cache_query_string = $CFG->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
|
||||
if (($cache_query_string = $this->config->cache->cache_query_string) && ! empty($_SERVER['QUERY_STRING']))
|
||||
{
|
||||
if (is_array($cache_query_string))
|
||||
{
|
||||
|
@ -673,6 +657,7 @@ class Output {
|
|||
|
||||
if ( ! file_exists($filepath) OR ! $fp = @fopen($filepath, 'rb'))
|
||||
{
|
||||
Logger::logDebug("No cache file for $uri found");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -695,11 +680,11 @@ class Output {
|
|||
$last_modified = filemtime($filepath);
|
||||
|
||||
// Has the file expired?
|
||||
if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path))
|
||||
if ($_SERVER['REQUEST_TIME'] >= $expire && Core::isReallyWritable($cache_path))
|
||||
{
|
||||
// If so we'll delete it.
|
||||
@unlink($filepath);
|
||||
log_message('debug', 'Cache file has expired. File deleted.');
|
||||
Logger::logDebug('Cache file has expired. File deleted.');
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
|
@ -716,7 +701,7 @@ class Output {
|
|||
|
||||
// Display the cache
|
||||
$this->_display(substr($cache, strlen($match[0])));
|
||||
log_message('debug', 'Cache file is current. Sending it to browser.');
|
||||
Logger::logDebug('Cache file is current. Sending it to browser.');
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -727,31 +712,26 @@ class Output {
|
|||
*
|
||||
* @param string $uri URI string
|
||||
* @return bool
|
||||
* @todo Implement
|
||||
*/
|
||||
public function delete_cache($uri = '')
|
||||
{
|
||||
Logger::logWarning("Caching is not implemented as of yet");
|
||||
return false;
|
||||
|
||||
$CI =& get_instance();
|
||||
$cache_path = $CI->config->item('cache_path');
|
||||
$cache_path = $this->config->cache->cache_file_path;
|
||||
if ($cache_path === '')
|
||||
{
|
||||
$cache_path = APPPATH.'cache/';
|
||||
$cache_path = 'Application'.DS.'Cache'.DS;
|
||||
}
|
||||
|
||||
if ( ! is_dir($cache_path))
|
||||
{
|
||||
log_message('error', 'Unable to find cache path: '.$cache_path);
|
||||
Logger::logError('Unable to find cache path: '.$cache_path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (empty($uri))
|
||||
{
|
||||
$uri = $CI->uri->uri_string();
|
||||
$uri = $this->uri->uri_string();
|
||||
|
||||
if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
|
||||
if (($cache_query_string = $this->config->cache->cache_query_string) && ! empty($_SERVER['QUERY_STRING']))
|
||||
{
|
||||
if (is_array($cache_query_string))
|
||||
{
|
||||
|
@ -764,11 +744,11 @@ class Output {
|
|||
}
|
||||
}
|
||||
|
||||
$cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').ltrim($uri, '/'));
|
||||
$cache_path .= md5($this->config->mainbase_url.$this->config->main->index_page.ltrim($uri, '/'));
|
||||
|
||||
if ( ! @unlink($cache_path))
|
||||
{
|
||||
log_message('error', 'Unable to delete cache file for '.$uri);
|
||||
Logger::logError('Unable to delete cache file for '.$uri);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,12 +41,14 @@ use Application\Init;
|
|||
* The overall structure of the routing is as follows:
|
||||
*
|
||||
* The routes-array will hold a list of RegEx-strings. When the route-method is called, the framework will try
|
||||
* to match the current path against all the RegEx's. When a RegEx matches, the linked callable will be called.
|
||||
* to match the current path found in the URI class against all the RegEx's. When a RegEx matches,
|
||||
* it will try and load what the route is related to. This can be a callable or a translator. A translator will
|
||||
* convert the values of a route into a callable. In the end a callable will always be loaded.
|
||||
*
|
||||
* Every module can register routes and add their own callables. By default, two callables are used:
|
||||
* The defaultCallable and the moduleCallable.
|
||||
* Every module can register routes and add their own callables. By default, two callables are available:
|
||||
* The defaultCallable and the moduleCallable of which the last one is found in the Modules class.
|
||||
*
|
||||
* The defaultCallable is a traditional MVC controller loader. Loading an URL using a default route works as follows:
|
||||
* The defaultCallable is a traditional MVC controller loader. Loading an URL when no route matches works as follows:
|
||||
*
|
||||
* Let's say the visitor requests /A/B/C
|
||||
*
|
||||
|
@ -54,7 +56,7 @@ use Application\Init;
|
|||
* B would be the function to be called in the 'controller' (default: index)
|
||||
* C would be the first parameter
|
||||
*
|
||||
* All controllers are to be placed in the /Application/controller-directory.
|
||||
* All controllers are to be placed in the /Application/Controller - directory.
|
||||
*
|
||||
* This is the default behaviour by adding routes to the config.routes.php. It is also possible to load Modules using routes.
|
||||
* To load a Module using a route, add the route to the moduleInfo.php in a routes array.
|
||||
|
@ -69,63 +71,143 @@ use Application\Init;
|
|||
* Callables are NO controllers!! By default, the 'defaultCallable' will load the correct controller from
|
||||
* the default controller directory. When you make custom routes, the callable will need to call your own
|
||||
* controllers. This means that the one callable you provide with your RegEx will be called for EVERYTHING
|
||||
* the RegEx matches. The names groups 'controller' and 'function' will be passed as first two arguments,
|
||||
* the RegEx matches. Only the regex matches will be provided to the callable,
|
||||
* if no names groups are available; you will need to extract them yourself from the path.
|
||||
*
|
||||
* After the core has been loaded, the method setPath will be called with the request URI (e.g. obtained via .htaccess).
|
||||
* That method will then call the route-method, which will call the right controller and it's method.
|
||||
* After the core has been loaded, the URI class will generate the URI which is currently being used.
|
||||
* The index file will then call the route-method, which will call the right controller and it's associated method.
|
||||
*
|
||||
* @see Router::setPath
|
||||
* @see Router::route
|
||||
* @see Router::addRoute
|
||||
*
|
||||
* @author Abel Hoogeveen <abel@techfuze.net>
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
*
|
||||
* @todo Implement Query Strings
|
||||
* @todo Implement Unit tests
|
||||
*/
|
||||
class Router
|
||||
{
|
||||
/**
|
||||
* @var null|string The provided path
|
||||
*/
|
||||
private static $path = null;
|
||||
|
||||
/**
|
||||
* @var array Routes
|
||||
*/
|
||||
private static $routes = array();
|
||||
protected $routes = array();
|
||||
|
||||
/**
|
||||
* @var null|mixed The callable
|
||||
*/
|
||||
private static $callable = null;
|
||||
protected $callable = null;
|
||||
|
||||
/**
|
||||
* @var null|array The extracted matches from the regex
|
||||
*/
|
||||
private static $matches = null;
|
||||
protected $matches = null;
|
||||
|
||||
/**
|
||||
* The constructor adds the default route to the routing table.
|
||||
* Translate URI dashes
|
||||
*
|
||||
* Determines whether dashes in controller & method segments
|
||||
* should be automatically replaced by underscores.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $translate_uri_dashes = false;
|
||||
|
||||
/**
|
||||
* The Config class used to get configurations
|
||||
*
|
||||
* @var Config FuzeWorks config class
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* The Uri class used to get paths
|
||||
*
|
||||
* @var Uri FuzeWorks uri class
|
||||
*/
|
||||
protected $uri;
|
||||
|
||||
/**
|
||||
* The Logger class used to log information
|
||||
*
|
||||
* @var Logger FuzeWorks logger class
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* The Events class used to fire events
|
||||
*
|
||||
* @var Events FuzeWorks events class
|
||||
*/
|
||||
protected $events;
|
||||
|
||||
/**
|
||||
* The Output class used to parse cache data
|
||||
*
|
||||
* @var Output FuzeWorks output class
|
||||
*/
|
||||
protected $output;
|
||||
|
||||
/**
|
||||
* Constructor of the Router
|
||||
*
|
||||
* Loads all required classes and adds all the routes to the routingTable
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
foreach (Config::get('routes') as $route => $callable) {
|
||||
if (is_int($route)) {
|
||||
$route = $callable;
|
||||
$callable = array('\FuzeWorks\Router', 'defaultCallable');
|
||||
}
|
||||
// Load related classes
|
||||
$factory = Factory::getInstance();
|
||||
$this->config = $factory->config;
|
||||
$this->uri = $factory->uri;
|
||||
$this->logger = $factory->logger;
|
||||
$this->events = $factory->events;
|
||||
$this->output = $factory->output;
|
||||
|
||||
self::addRoute($route, $callable, false);
|
||||
}
|
||||
// Start parsing the routing
|
||||
$this->parseRouting();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current routing path.
|
||||
*
|
||||
* @return bool|string
|
||||
* Route Parser
|
||||
*
|
||||
* This method parses all the routes in the routes table config file
|
||||
* and adds them to the Router. It converts some routes which use wildcards
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function getPath()
|
||||
protected function parseRouting()
|
||||
{
|
||||
return self::$path;
|
||||
// Get routing routes
|
||||
$routes = $this->config->routes;
|
||||
$routing = $this->config->routing;
|
||||
|
||||
// If no query strings are used, we will add all routes in the config.routes.php file.
|
||||
// We modify these routes to be an array of a regex string and a callable
|
||||
$http_verb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli';
|
||||
|
||||
foreach ($routes as $route => $value)
|
||||
{
|
||||
// Check if the route format is using HTTP verbs
|
||||
if (is_array($value))
|
||||
{
|
||||
$value = array_change_key_case($value, CASE_LOWER);
|
||||
if (isset($value[$http_verb]))
|
||||
{
|
||||
$value = $value['http_verb'];
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert wildcards to Regex
|
||||
$route = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $route);
|
||||
|
||||
$this->addRoute($route, $value, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,19 +215,19 @@ class Router
|
|||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getRoutes()
|
||||
public function getRoutes()
|
||||
{
|
||||
return self::$routes;
|
||||
return $this->routes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently loaded callable.
|
||||
* Returns the currently loaded or selected callable.
|
||||
*
|
||||
* @return null|callable
|
||||
*/
|
||||
public static function getCallable()
|
||||
public function getCallable()
|
||||
{
|
||||
return self::$callable;
|
||||
return $this->callable;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,99 +235,39 @@ class Router
|
|||
*
|
||||
* @return null|array
|
||||
*/
|
||||
public static function getMatches()
|
||||
public function getMatches()
|
||||
{
|
||||
return self::$matches;
|
||||
return $this->matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current routing path.
|
||||
* Add a route to the Router's routing table
|
||||
*
|
||||
* The route consists of 2 parts: the route and data.
|
||||
*
|
||||
* The route is a regex string which will later be matched upon Router::route().
|
||||
*
|
||||
* The data can be multiple things. First it can be a string, which will later be processed and turned into
|
||||
* a callable. If the string is like 'controller/method' then the contoller 'Controller' will be loaded and the
|
||||
* method 'method' will be called. The data can also be a callable. That callable will be called with all the regex
|
||||
* that match the route. The callable is expected to return a string just like above. You can also provide an array.
|
||||
* If you have an array like this: array('callable' => array('Class', 'method')) then your callable shall be used
|
||||
* instead of the defaultCallabele.
|
||||
*
|
||||
* @param string $path The routing path (e.g. a/b/c/d/e)
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
public static function setPath($path)
|
||||
{
|
||||
|
||||
// Fire the event to notify our modules
|
||||
$event = Events::fireEvent('routerSetPathEvent', $path);
|
||||
|
||||
// The event has been cancelled
|
||||
if ($event->isCancelled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove double slashes
|
||||
$path = preg_replace('@[/]+@', '/', $event->path);
|
||||
|
||||
// Remove first slash
|
||||
if (substr($path, 0, 1) == '/') {
|
||||
$path = substr($path, 1);
|
||||
}
|
||||
|
||||
// Remove trailing slash
|
||||
if (substr($path, -1, 1) == '/') {
|
||||
$path = substr($path, 0, strlen($path) - 1);
|
||||
}
|
||||
|
||||
return self::$path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a route.
|
||||
*
|
||||
* The path will be checked before custom routes before the default route(/controller/function/param1/param2/etc)
|
||||
* When the given RegEx matches the current routing-path, the callable will be called.
|
||||
*
|
||||
* The callable will be called with three arguments:
|
||||
*
|
||||
* Callable($regex_matches = array())
|
||||
*
|
||||
* The variables in the array will be the named groups of your RegEx. When one or more named groups are
|
||||
* not matched, they will be set to NULL. The default RegEx is:
|
||||
*
|
||||
* /^(?P<controller>.*?)(|\/(?P<function>.*?)(|\/(?P<parameters>.*?)))$/
|
||||
*
|
||||
* ^ Named group 1 ^ Named group 2 ^ Named group 3
|
||||
*
|
||||
* Named group 1 is named 'controller' and thus will become $controller
|
||||
* Named group 2 is named 'function' and thus will become $function
|
||||
* Named group 3 is named 'parameters' and thus will become $parameters
|
||||
*
|
||||
* You can also add aliases with the following:
|
||||
*
|
||||
* '/^this-is-an-alias$/' => array(
|
||||
* 'controller' => 'home',
|
||||
* 'function' => 'index',
|
||||
* 'parameters' => array()
|
||||
* ),
|
||||
*
|
||||
* This will link '/this-is-an-alias/ to /home/index. It is also possible to use the three named capture groups
|
||||
* for the function, parameters or controllers. Like this:
|
||||
*
|
||||
* '/^alias(|\-(?P<function>.*?))$/' => array(
|
||||
* 'controller' => 'home'
|
||||
* ),
|
||||
*
|
||||
* This will mask '/alias' to '/home' and '/alias-test' to 'home/test'.
|
||||
*
|
||||
* You do not *have* to use named groups, but when you don't the arguments will be left NULL; and you will need to
|
||||
* extract the information from the routing-path yourself.
|
||||
*
|
||||
* @param string $route This is a RegEx of the route, Every capture group will be a parameter
|
||||
* @param callable $callable The callable to execute
|
||||
* @param string $route This is a RegEx of the route, Every capture group will be a match, passed on to a callable
|
||||
* @param mixed $data Can be multiple things. See description above
|
||||
* @param bool $prepend Whether or not to insert at the beginning of the routing table
|
||||
* @return void
|
||||
*/
|
||||
public static function addRoute($route, $callable, $prepend = true)
|
||||
public function addRoute($route, $callable, $prepend = true)
|
||||
{
|
||||
if ($prepend) {
|
||||
self::$routes = array($route => $callable) + self::$routes;
|
||||
$this->routes = array($route => $callable) + $this->routes;
|
||||
} else {
|
||||
self::$routes[$route] = $callable;
|
||||
$this->routes[$route] = $callable;
|
||||
}
|
||||
|
||||
Logger::log('Route added at '.($prepend ? 'top' : 'bottom').': "'.$route.'"');
|
||||
$this->logger->log('Route added at '.($prepend ? 'top' : 'bottom').': "'.$route.'"');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -253,59 +275,154 @@ class Router
|
|||
*
|
||||
* @param $route string The route to remove
|
||||
*/
|
||||
public static function removeRoute($route)
|
||||
public function removeRoute($route)
|
||||
{
|
||||
unset(self::$routes[$route]);
|
||||
unset($this->routes[$route]);
|
||||
|
||||
Logger::log('Route removed: '.$route);
|
||||
$this->logger->log('Route removed: '.$route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the routing path from the URL using the routing table.
|
||||
*
|
||||
* Determines what callable should be loaded and what data matches the route regex.
|
||||
* Determines what should be loaded and what data matches the route regex.
|
||||
*
|
||||
* @param bool $loadCallable Immediate load the callable when it's route matches
|
||||
* @param bool $performLoading Immediate process the route after it has been determined
|
||||
*/
|
||||
public static function route($loadCallable = true)
|
||||
public function route($performLoading = true)
|
||||
{
|
||||
// Turn the segment array into a URI string
|
||||
$uri = implode('/', $this->uri->segments);
|
||||
|
||||
// Fire the event to notify our modules
|
||||
$event = Events::fireEvent('routerRouteEvent', self::$routes, $loadCallable, self::$path);
|
||||
$event = Events::fireEvent('routerRouteEvent', $this->routes, $performLoading, $uri);
|
||||
|
||||
// The event has been cancelled
|
||||
if ($event->isCancelled()) {
|
||||
if ($event->isCancelled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign everything to the object to make it accessible, but let modules check it first
|
||||
$routes = $event->routes;
|
||||
$loadCallable = $event->loadCallable;
|
||||
$performLoading = $event->performLoading;
|
||||
|
||||
//Check the custom routes
|
||||
foreach ($routes as $r => $c) {
|
||||
//A custom route is found
|
||||
if (preg_match($r, $event->path, $matches)) {
|
||||
Logger::log('Route matched: '.$r);
|
||||
// If a cached page should be loaded, do so and stop loading a routed page
|
||||
if ($performLoading === true && $event->cacheOverride === false && $this->output->_display_cache() === true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add the matches to the current class
|
||||
self::$matches = $matches;
|
||||
// Check the custom routes
|
||||
foreach ($routes as $route => $value)
|
||||
{
|
||||
// Match the path against the routes
|
||||
if (preg_match('#^'.$route.'$#', $event->path, $matches))
|
||||
{
|
||||
$this->logger->log('Route matched: '.$route);
|
||||
// Save the matches
|
||||
$this->matches = $matches;
|
||||
|
||||
self::$callable = $c;
|
||||
if (!$loadCallable || !self::loadCallable($matches, $r)) {
|
||||
break;
|
||||
// Are we using callbacks or another method?
|
||||
if ( is_array($value))
|
||||
{
|
||||
// Maybe there is a real callable which should be called in the future
|
||||
if ( isset($value['callable']) )
|
||||
{
|
||||
$this->callable = $value['callable'];
|
||||
}
|
||||
|
||||
// If the callable is satisfied, break away
|
||||
if (!$performLoading || !$this->loadCallable($matches, $route))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise try other routes
|
||||
continue;
|
||||
}
|
||||
elseif ( ! is_string($value) && is_callable($value))
|
||||
{
|
||||
// Prepare the callable
|
||||
array_shift($matches);
|
||||
|
||||
// Retrieve the path that should be loaded
|
||||
$value = call_user_func_array($value, $matches);
|
||||
}
|
||||
elseif (strpos($value, '$') !== FALSE && strpos($route, '(') !== FALSE)
|
||||
{
|
||||
$value = preg_replace('#^'.$route.'$#', $value, $event->path);
|
||||
}
|
||||
|
||||
// Now run the defaultRouter for when something is not a callable
|
||||
$this->routeDefault(explode('/', $value), $route);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we found a callable anyway
|
||||
if (self::$callable === null) {
|
||||
Logger::log('No routes found for given path: "'.$event->path.'"', E_WARNING);
|
||||
Logger::http_error(404);
|
||||
|
||||
return;
|
||||
// If we got this far it means we didn't encounter a
|
||||
// matching route so we'll set the site default route
|
||||
$this->matches = array();
|
||||
if ($performLoading === true)
|
||||
{
|
||||
$this->routeDefault(array_values($this->uri->segments), '.*$');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Implement validateRequest
|
||||
*/
|
||||
protected function validateRequest($segments)
|
||||
{
|
||||
$c = count($segments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a routing string into parameters for the defaultCallable.
|
||||
*
|
||||
* @param array $segments Segments of the controller,method,parameters to open
|
||||
* @param string @route The route which was matched
|
||||
* @return void
|
||||
*/
|
||||
protected function routeDefault($segments = array(), $route)
|
||||
{
|
||||
// If we don't have any segments left - try the default controller;
|
||||
// WARNING: Directories get shifted out of the segments array!
|
||||
if (empty($segments))
|
||||
{
|
||||
$segments[0] = $this->config->routing->default_controller;
|
||||
}
|
||||
|
||||
if ($this->translate_uri_dashes === true)
|
||||
{
|
||||
$segments[0] = str_replace('-', '_', $segments[0]);
|
||||
if (isset($segments[1]))
|
||||
{
|
||||
$segments[1] = str_replace('-', '_', $segments[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the values for loading
|
||||
$controller = $segments[0];
|
||||
$function = (isset($segments[1]) ? $segments[1] : $this->config->routing->default_function);
|
||||
|
||||
// And prepare the Router URI
|
||||
array_unshift($segments, null);
|
||||
unset($segments[0]);
|
||||
$this->uri->rsegments = $segments;
|
||||
|
||||
// Now create a matches array
|
||||
$matches = array(
|
||||
'controller' => $controller,
|
||||
'function' => $function,
|
||||
'parameters' => array_slice($this->uri->rsegments, 2)
|
||||
);
|
||||
|
||||
// And finally load the callable
|
||||
$this->callable = array('\FuzeWorks\Router', 'defaultCallable');
|
||||
$this->loadCallable($matches, $route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the callable to which the route matched.
|
||||
*
|
||||
|
@ -318,12 +435,12 @@ class Router
|
|||
*
|
||||
* @return bool Whether or not the callable was satisfied
|
||||
*/
|
||||
public static function loadCallable($matches = array(), $route)
|
||||
public function loadCallable($matches = array(), $route)
|
||||
{
|
||||
Logger::newLevel('Loading callable');
|
||||
$this->logger->newLevel('Loading callable');
|
||||
|
||||
// Fire the event to notify our modules
|
||||
$event = Events::fireEvent('routerLoadCallableEvent', self::$callable, $matches, $route);
|
||||
$event = Events::fireEvent('routerLoadCallableEvent', $this->callable, $matches, $route);
|
||||
|
||||
// The event has been cancelled
|
||||
if ($event->isCancelled()) {
|
||||
|
@ -335,39 +452,39 @@ class Router
|
|||
$args['route'] = $event->route;
|
||||
|
||||
if (!is_callable($event->callable)) {
|
||||
if (isset(self::$callable['controller'])) {
|
||||
if (isset($this->callable['controller'])) {
|
||||
// Reset the arguments and fetch from custom callable
|
||||
$args = array();
|
||||
$args['controller'] = isset(self::$callable['controller']) ? self::$callable['controller'] : (isset($matches['controller']) ? $matches['controller'] : null);
|
||||
$args['function'] = isset(self::$callable['function']) ? self::$callable['function'] : (isset($matches['function']) ? $matches['function'] : null);
|
||||
$args['parameters'] = isset(self::$callable['parameters']) ? self::$callable['parameters'] : (isset($matches['parameters']) ? explode('/', $matches['parameters']) : null);
|
||||
$args['controller'] = isset($this->callable['controller']) ? $this->callable['controller'] : (isset($matches['controller']) ? $matches['controller'] : null);
|
||||
$args['function'] = isset($this->callable['function']) ? $this->callable['function'] : (isset($matches['function']) ? $matches['function'] : null);
|
||||
$args['parameters'] = isset($this->callable['parameters']) ? $this->callable['parameters'] : (isset($matches['parameters']) ? explode('/', $matches['parameters']) : null);
|
||||
|
||||
self::$callable = array('\FuzeWorks\Router', 'defaultCallable');
|
||||
$this->callable = array('\FuzeWorks\Router', 'defaultCallable');
|
||||
} else {
|
||||
Logger::log('The given callable is not callable!', E_ERROR);
|
||||
Logger::http_error(500);
|
||||
Logger::stopLevel();
|
||||
$this->logger->log('The given callable is not callable!', E_ERROR);
|
||||
$this->logger->http_error(500);
|
||||
$this->logger->stopLevel();
|
||||
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
self::$callable = $event->callable;
|
||||
$this->callable = $event->callable;
|
||||
}
|
||||
|
||||
// And log the input to the logger
|
||||
Logger::newLevel('Calling callable');
|
||||
$this->logger->newLevel('Calling callable');
|
||||
foreach ($args as $key => $value) {
|
||||
Logger::log($key.': '.var_export($value, true).'');
|
||||
$this->logger->log($key.': '.var_export($value, true).'');
|
||||
}
|
||||
Logger::stopLevel();
|
||||
$this->logger->stopLevel();
|
||||
|
||||
$skip = call_user_func_array(self::$callable, array($args)) === false;
|
||||
$skip = call_user_func_array($this->callable, array($args)) === false;
|
||||
|
||||
if ($skip) {
|
||||
Logger::log('Callable not satisfied, skipping to next callable');
|
||||
$this->logger->log('Callable not satisfied, skipping to next callable');
|
||||
}
|
||||
|
||||
Logger::stopLevel();
|
||||
$this->logger->stopLevel();
|
||||
|
||||
return $skip;
|
||||
}
|
||||
|
@ -378,12 +495,12 @@ class Router
|
|||
* This callable will do the 'old skool' routing. It will load the controllers from the controller-directory
|
||||
* in the application-directory.
|
||||
*/
|
||||
public static function defaultCallable($arguments = array())
|
||||
public function defaultCallable($arguments = array())
|
||||
{
|
||||
Logger::log('Default callable called!');
|
||||
$this->logger->log('Default callable called!');
|
||||
|
||||
$controller = empty($arguments['controller']) ? Config::get('main')->default_controller : $arguments['controller'];
|
||||
$function = empty($arguments['function']) ? Config::get('main')->default_function : $arguments['function'];
|
||||
$controller = $arguments['controller'];
|
||||
$function = $arguments['function'];
|
||||
$parameters = empty($arguments['parameters']) ? null : $arguments['parameters'];
|
||||
|
||||
// Construct file paths and classes
|
||||
|
@ -405,38 +522,37 @@ class Router
|
|||
return;
|
||||
}
|
||||
|
||||
Logger::log('Loading controller '.$event->className.' from file: '.$event->file);
|
||||
|
||||
// Check if the file exists
|
||||
if (file_exists($event->file)) {
|
||||
if (!class_exists($event->className)) {
|
||||
$this->logger->log('Loading controller '.$event->className.' from file: '.$event->file);
|
||||
include $event->file;
|
||||
}
|
||||
|
||||
// Get the path the controller should know about
|
||||
$path = substr(self::getPath(), ($pos = strpos(self::getPath(), '/')) !== false ? $pos + 1 : 0);
|
||||
$path = implode('/', $this->uri->rsegments);
|
||||
|
||||
// And create the controller
|
||||
self::$callable = new $event->className($path);
|
||||
$this->callable = new $event->className($path);
|
||||
|
||||
// If the controller does not want a function to be loaded, provide a halt parameter.
|
||||
if (isset(self::$callable->halt)) {
|
||||
if (isset($this->callable->halt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if method exists or if there is a caller function
|
||||
if (method_exists(self::$callable, $event->function) || method_exists(self::$callable, '__call')) {
|
||||
if (method_exists($this->callable, $event->function) || method_exists($this->callable, '__call')) {
|
||||
// Execute the function on the controller
|
||||
echo self::$callable->{$event->function}($event->parameters);
|
||||
echo $this->callable->{$event->function}($event->parameters);
|
||||
} else {
|
||||
// Function could not be found
|
||||
Logger::log('Could not find function '.$event->function.' on controller '.$event->className);
|
||||
Logger::http_error(404);
|
||||
$this->logger->log('Could not find function '.$event->function.' on controller '.$event->className);
|
||||
$this->logger->http_error(404);
|
||||
}
|
||||
} else {
|
||||
// Controller could not be found
|
||||
Logger::log('Could not find controller '.$event->className);
|
||||
Logger::http_error(404);
|
||||
$this->logger->log('Could not find controller '.$event->className);
|
||||
$this->logger->http_error(404);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,14 +48,14 @@ class URI {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $keyval = array();
|
||||
public $keyval = array();
|
||||
|
||||
/**
|
||||
* Current URI string
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $uri_string = '';
|
||||
public $uri_string = '';
|
||||
|
||||
/**
|
||||
* List of URI segments
|
||||
|
@ -64,7 +64,7 @@ class URI {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $segments = array();
|
||||
public $segments = array();
|
||||
|
||||
/**
|
||||
* List of routed URI segments
|
||||
|
@ -73,7 +73,7 @@ class URI {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $rsegments = array();
|
||||
public $rsegments = array();
|
||||
|
||||
/**
|
||||
* Permitted URI chars
|
||||
|
@ -82,14 +82,14 @@ class URI {
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $_permitted_uri_chars;
|
||||
protected $_permitted_uri_chars;
|
||||
|
||||
/**
|
||||
* The configuration of this class
|
||||
*
|
||||
* @var ConfigORM
|
||||
*/
|
||||
private static $config;
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
|
@ -98,43 +98,69 @@ class URI {
|
|||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::$config = Config::get('routing');
|
||||
$this->config = Config::get('routing');
|
||||
|
||||
// If query strings are enabled, we don't need to parse any segments.
|
||||
// However, they don't make sense under CLI.
|
||||
if ((PHP_SAPI === 'cli' OR defined('STDIN')) OR self::$config->enable_query_strings !== TRUE)
|
||||
// Determine the base_url
|
||||
if (empty(Config::get('main')->base_url))
|
||||
{
|
||||
self::$_permitted_uri_chars = self::$config->permitted_uri_chars;
|
||||
|
||||
// If it's a CLI request, ignore the configuration
|
||||
if ( (PHP_SAPI === 'cli' OR defined('STDIN')) )
|
||||
if (isset($_SERVER['SERVER_ADDR']))
|
||||
{
|
||||
$uri = self::_parse_argv();
|
||||
if (strpos($_SERVER['SERVER_ADDR'], ':') !== FALSE)
|
||||
{
|
||||
$server_addr = '['.$_SERVER['SERVER_ADDR'].']';
|
||||
}
|
||||
else
|
||||
{
|
||||
$server_addr = $_SERVER['SERVER_ADDR'];
|
||||
}
|
||||
|
||||
$base_url = (Core::isHttps() ? 'https' : 'http').'://'.$server_addr
|
||||
.substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'], basename($_SERVER['SCRIPT_FILENAME'])));
|
||||
}
|
||||
else
|
||||
{
|
||||
$protocol = self::$config->uri_protocol;
|
||||
$base_url = 'http://localhost/';
|
||||
}
|
||||
|
||||
Config::get('main')->base_url = $base_url;
|
||||
}
|
||||
|
||||
|
||||
// If query strings are enabled, we don't need to parse any segments.
|
||||
// However, they don't make sense under CLI.
|
||||
if (Core::isCli() OR $this->config->enable_query_strings !== TRUE)
|
||||
{
|
||||
$this->_permitted_uri_chars = $this->config->permitted_uri_chars;
|
||||
|
||||
// If it's a CLI request, ignore the configuration
|
||||
if ( Core::isCli() )
|
||||
{
|
||||
$uri = $this->_parse_argv();
|
||||
}
|
||||
else
|
||||
{
|
||||
$protocol = $this->config->uri_protocol;
|
||||
empty($protocol) && $protocol = 'REQUEST_URI';
|
||||
|
||||
switch ($protocol)
|
||||
{
|
||||
case 'AUTO': // For BC purposes only
|
||||
case 'REQUEST_URI':
|
||||
$uri = self::_parse_request_uri();
|
||||
$uri = $this->_parse_request_uri();
|
||||
break;
|
||||
case 'QUERY_STRING':
|
||||
$uri = self::_parse_query_string();
|
||||
$uri = $this->_parse_query_string();
|
||||
break;
|
||||
case 'PATH_INFO':
|
||||
default:
|
||||
$uri = isset($_SERVER[$protocol])
|
||||
? $_SERVER[$protocol]
|
||||
: self::_parse_request_uri();
|
||||
: $this->_parse_request_uri();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self::_set_uri_string($uri);
|
||||
$this->_set_uri_string($uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,39 +172,39 @@ class URI {
|
|||
* @param string $str
|
||||
* @return void
|
||||
*/
|
||||
protected static function _set_uri_string($str)
|
||||
protected function _set_uri_string($str)
|
||||
{
|
||||
// Filter out control characters and trim slashes
|
||||
self::$uri_string = trim(Utf8::remove_invisible_characters($str, FALSE), '/');
|
||||
$this->uri_string = trim(Utf8::remove_invisible_characters($str, FALSE), '/');
|
||||
|
||||
if (self::$uri_string !== '')
|
||||
if ($this->uri_string !== '')
|
||||
{
|
||||
// Remove the URL suffix, if present
|
||||
if (($suffix = (string) self::$config->url_suffix) !== '')
|
||||
if (($suffix = (string) $this->config->url_suffix) !== '')
|
||||
{
|
||||
$slen = strlen($suffix);
|
||||
|
||||
if (substr(self::$uri_string, -$slen) === $suffix)
|
||||
if (substr($this->uri_string, -$slen) === $suffix)
|
||||
{
|
||||
self::$uri_string = substr(self::$uri_string, 0, -$slen);
|
||||
$this->uri_string = substr($this->uri_string, 0, -$slen);
|
||||
}
|
||||
}
|
||||
|
||||
self::$segments[0] = NULL;
|
||||
$this->segments[0] = NULL;
|
||||
// Populate the segments array
|
||||
foreach (explode('/', trim(self::$uri_string, '/')) as $val)
|
||||
foreach (explode('/', trim($this->uri_string, '/')) as $val)
|
||||
{
|
||||
$val = trim($val);
|
||||
// Filter segments for security
|
||||
self::filter_uri($val);
|
||||
$this->filter_uri($val);
|
||||
|
||||
if ($val !== '')
|
||||
{
|
||||
self::$segments[] = $val;
|
||||
$this->segments[] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
unset(self::$segments[0]);
|
||||
unset($this->segments[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +218,7 @@ class URI {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function _parse_request_uri()
|
||||
protected function _parse_request_uri()
|
||||
{
|
||||
if ( ! isset($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']))
|
||||
{
|
||||
|
@ -240,7 +266,7 @@ class URI {
|
|||
|
||||
|
||||
// Do some final cleaning of the URI and return it
|
||||
return self::_remove_relative_directory($uri);
|
||||
return $this->_remove_relative_directory($uri);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -252,7 +278,7 @@ class URI {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function _parse_query_string()
|
||||
protected function _parse_query_string()
|
||||
{
|
||||
$uri = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
|
||||
|
||||
|
@ -269,7 +295,7 @@ class URI {
|
|||
|
||||
parse_str($_SERVER['QUERY_STRING'], $_GET);
|
||||
|
||||
return self::_remove_relative_directory($uri);
|
||||
return $this->_remove_relative_directory($uri);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -281,7 +307,7 @@ class URI {
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function _parse_argv()
|
||||
protected function _parse_argv()
|
||||
{
|
||||
$args = array_slice($_SERVER['argv'], 1);
|
||||
return $args ? implode('/', $args) : '';
|
||||
|
@ -292,12 +318,12 @@ class URI {
|
|||
/**
|
||||
* Remove relative directory (../) and multi slashes (///)
|
||||
*
|
||||
* Do some final cleaning of the URI and return it, currently only used in self::_parse_request_uri()
|
||||
* Do some final cleaning of the URI and return it, currently only used in $this->_parse_request_uri()
|
||||
*
|
||||
* @param string $uri
|
||||
* @return string
|
||||
*/
|
||||
protected static function _remove_relative_directory($uri)
|
||||
protected function _remove_relative_directory($uri)
|
||||
{
|
||||
$uris = array();
|
||||
$tok = strtok($uri, '/');
|
||||
|
@ -323,9 +349,9 @@ class URI {
|
|||
* @param string $str
|
||||
* @return void
|
||||
*/
|
||||
public static function filter_uri(&$str)
|
||||
public function filter_uri(&$str)
|
||||
{
|
||||
if ( ! empty($str) && ! empty(self::$_permitted_uri_chars) && ! preg_match('/^['.self::$_permitted_uri_chars.']+$/i'.(UTF8_ENABLED ? 'u' : ''), $str))
|
||||
if ( ! empty($str) && ! empty($this->_permitted_uri_chars) && ! preg_match('/^['.$this->_permitted_uri_chars.']+$/i'.(UTF8_ENABLED ? 'u' : ''), $str))
|
||||
{
|
||||
throw new UriException('The URI you submitted has disallowed characters.', 1);
|
||||
}
|
||||
|
@ -336,14 +362,14 @@ class URI {
|
|||
/**
|
||||
* Fetch URI Segment
|
||||
*
|
||||
* @see CI_URI::$segments
|
||||
* @see URI::$segments
|
||||
* @param int $n Index
|
||||
* @param mixed $no_result What to return if the segment index is not found
|
||||
* @return mixed
|
||||
*/
|
||||
public static function segment($n, $no_result = NULL)
|
||||
public function segment($n, $no_result = NULL)
|
||||
{
|
||||
return isset(self::$segments[$n]) ? self::$segments[$n] : $no_result;
|
||||
return isset($this->segments[$n]) ? $this->segments[$n] : $no_result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -353,17 +379,17 @@ class URI {
|
|||
*
|
||||
* Returns the re-routed URI segment (assuming routing rules are used)
|
||||
* based on the index provided. If there is no routing, will return
|
||||
* the same result as CI_URI::segment().
|
||||
* the same result as URI::segment().
|
||||
*
|
||||
* @see CI_URI::$rsegments
|
||||
* @see CI_URI::segment()
|
||||
* @see URI::$rsegments
|
||||
* @see URI::segment()
|
||||
* @param int $n Index
|
||||
* @param mixed $no_result What to return if the segment index is not found
|
||||
* @return mixed
|
||||
*/
|
||||
public static function rsegment($n, $no_result = NULL)
|
||||
public function rsegment($n, $no_result = NULL)
|
||||
{
|
||||
return isset(self::$rsegments[$n]) ? self::$rsegments[$n] : $no_result;
|
||||
return isset($this->rsegments[$n]) ? $this->rsegments[$n] : $no_result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -388,9 +414,9 @@ class URI {
|
|||
* @param array $default Default values
|
||||
* @return array
|
||||
*/
|
||||
public static function uri_to_assoc($n = 3, $default = array())
|
||||
public function uri_to_assoc($n = 3, $default = array())
|
||||
{
|
||||
return self::_uri_to_assoc($n, $default, 'segment');
|
||||
return $this->_uri_to_assoc($n, $default, 'segment');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -398,17 +424,17 @@ class URI {
|
|||
/**
|
||||
* Routed URI to assoc
|
||||
*
|
||||
* Identical to CI_URI::uri_to_assoc(), only it uses the re-routed
|
||||
* Identical to URI::uri_to_assoc(), only it uses the re-routed
|
||||
* segment array.
|
||||
*
|
||||
* @see CI_URI::uri_to_assoc()
|
||||
* @see URI::uri_to_assoc()
|
||||
* @param int $n Index (default: 3)
|
||||
* @param array $default Default values
|
||||
* @return array
|
||||
*/
|
||||
public static function ruri_to_assoc($n = 3, $default = array())
|
||||
public function ruri_to_assoc($n = 3, $default = array())
|
||||
{
|
||||
return self::_uri_to_assoc($n, $default, 'rsegment');
|
||||
return $this->_uri_to_assoc($n, $default, 'rsegment');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -418,36 +444,36 @@ class URI {
|
|||
*
|
||||
* Generates a key/value pair from the URI string or re-routed URI string.
|
||||
*
|
||||
* @used-by CI_URI::uri_to_assoc()
|
||||
* @used-by CI_URI::ruri_to_assoc()
|
||||
* @used-by URI::uri_to_assoc()
|
||||
* @used-by URI::ruri_to_assoc()
|
||||
* @param int $n Index (default: 3)
|
||||
* @param array $default Default values
|
||||
* @param string $which Array name ('segment' or 'rsegment')
|
||||
* @return array
|
||||
*/
|
||||
protected static function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
|
||||
protected function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
|
||||
{
|
||||
if ( ! is_numeric($n))
|
||||
{
|
||||
return $default;
|
||||
}
|
||||
|
||||
if (isset(self::$keyval[$which], self::$keyval[$which][$n]))
|
||||
if (isset($this->keyval[$which], $this->keyval[$which][$n]))
|
||||
{
|
||||
return self::$keyval[$which][$n];
|
||||
return $this->keyval[$which][$n];
|
||||
}
|
||||
|
||||
$total_segments = "total_{$which}s";
|
||||
$segment_array = "{$which}_array";
|
||||
|
||||
if (self::$total_segments() < $n)
|
||||
if ($this->$total_segments() < $n)
|
||||
{
|
||||
return (count($default) === 0)
|
||||
? array()
|
||||
: array_fill_keys($default, NULL);
|
||||
}
|
||||
|
||||
$segments = array_slice(self::$segment_array(), ($n - 1));
|
||||
$segments = array_slice($this->$segment_array(), ($n - 1));
|
||||
$i = 0;
|
||||
$lastval = '';
|
||||
$retval = array();
|
||||
|
@ -478,8 +504,8 @@ class URI {
|
|||
}
|
||||
|
||||
// Cache the array for reuse
|
||||
isset(self::$keyval[$which]) OR self::$keyval[$which] = array();
|
||||
self::$keyval[$which][$n] = $retval;
|
||||
isset($this->keyval[$which]) OR $this->keyval[$which] = array();
|
||||
$this->keyval[$which][$n] = $retval;
|
||||
return $retval;
|
||||
}
|
||||
|
||||
|
@ -493,7 +519,7 @@ class URI {
|
|||
* @param array $array Input array of key/value pairs
|
||||
* @return string URI string
|
||||
*/
|
||||
public static function assoc_to_uri($array)
|
||||
public function assoc_to_uri($array)
|
||||
{
|
||||
$temp = array();
|
||||
foreach ((array) $array as $key => $val)
|
||||
|
@ -516,9 +542,9 @@ class URI {
|
|||
* @param string $where Where to add the slash ('trailing' or 'leading')
|
||||
* @return string
|
||||
*/
|
||||
public static function slash_segment($n, $where = 'trailing')
|
||||
public function slash_segment($n, $where = 'trailing')
|
||||
{
|
||||
return self::_slash_segment($n, $where, 'segment');
|
||||
return $this->_slash_segment($n, $where, 'segment');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -532,9 +558,9 @@ class URI {
|
|||
* @param string $where Where to add the slash ('trailing' or 'leading')
|
||||
* @return string
|
||||
*/
|
||||
public static function slash_rsegment($n, $where = 'trailing')
|
||||
public function slash_rsegment($n, $where = 'trailing')
|
||||
{
|
||||
return self::_slash_segment($n, $where, 'rsegment');
|
||||
return $this->_slash_segment($n, $where, 'rsegment');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -544,15 +570,15 @@ class URI {
|
|||
*
|
||||
* Fetches an URI Segment and adds a slash to it.
|
||||
*
|
||||
* @used-by CI_URI::slash_segment()
|
||||
* @used-by CI_URI::slash_rsegment()
|
||||
* @used-by URI::slash_segment()
|
||||
* @used-by URI::slash_rsegment()
|
||||
*
|
||||
* @param int $n Index
|
||||
* @param string $where Where to add the slash ('trailing' or 'leading')
|
||||
* @param string $which Array name ('segment' or 'rsegment')
|
||||
* @return string
|
||||
*/
|
||||
protected static function _slash_segment($n, $where = 'trailing', $which = 'segment')
|
||||
protected function _slash_segment($n, $where = 'trailing', $which = 'segment')
|
||||
{
|
||||
$leading = $trailing = '/';
|
||||
|
||||
|
@ -565,7 +591,7 @@ class URI {
|
|||
$trailing = '';
|
||||
}
|
||||
|
||||
return $leading.self::$which($n).$trailing;
|
||||
return $leading.$this->$which($n).$trailing;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -573,11 +599,11 @@ class URI {
|
|||
/**
|
||||
* Segment Array
|
||||
*
|
||||
* @return array CI_URI::$segments
|
||||
* @return array URI::$segments
|
||||
*/
|
||||
public static function segment_array()
|
||||
public function segment_array()
|
||||
{
|
||||
return self::$segments;
|
||||
return $this->segments;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -585,11 +611,11 @@ class URI {
|
|||
/**
|
||||
* Routed Segment Array
|
||||
*
|
||||
* @return array CI_URI::$rsegments
|
||||
* @return array URI::$rsegments
|
||||
*/
|
||||
public static function rsegment_array()
|
||||
public function rsegment_array()
|
||||
{
|
||||
return self::$rsegments;
|
||||
return $this->rsegments;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -599,9 +625,9 @@ class URI {
|
|||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function total_segments()
|
||||
public function total_segments()
|
||||
{
|
||||
return count(self::$segments);
|
||||
return count($this->segments);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -611,9 +637,9 @@ class URI {
|
|||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function total_rsegments()
|
||||
public function total_rsegments()
|
||||
{
|
||||
return count(self::$rsegments);
|
||||
return count($this->rsegments);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -621,24 +647,10 @@ class URI {
|
|||
/**
|
||||
* Fetch URI string
|
||||
*
|
||||
* @return string CI_URI::$uri_string
|
||||
* @return string URI::$uri_string
|
||||
*/
|
||||
public static function uri_string()
|
||||
public function uri_string()
|
||||
{
|
||||
return self::$uri_string;
|
||||
return $this->uri_string;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch Re-routed URI string
|
||||
*
|
||||
* @return string
|
||||
* @todo Implement router
|
||||
*/
|
||||
public static function ruri_string()
|
||||
{
|
||||
return ltrim(load_class('Router', 'core')->directory, '/').implode('/', self::$rsegments);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ class Utf8 {
|
|||
mb_internal_encoding($charset);
|
||||
}
|
||||
// This is required for mb_convert_encoding() to strip invalid characters.
|
||||
// That's utilized by CI_Utf8, but it's also done for consistency with iconv.
|
||||
// That's utilized by Utf8, but it's also done for consistency with iconv.
|
||||
mb_substitute_character('none');
|
||||
}
|
||||
else
|
||||
|
@ -135,9 +135,9 @@ class Utf8 {
|
|||
* @param string $str String to clean
|
||||
* @return string
|
||||
*/
|
||||
public static function clean_string($str)
|
||||
public function clean_string($str)
|
||||
{
|
||||
if (self::is_ascii($str) === FALSE)
|
||||
if ($this->is_ascii($str) === FALSE)
|
||||
{
|
||||
if (MB_ENABLED)
|
||||
{
|
||||
|
@ -164,9 +164,9 @@ class Utf8 {
|
|||
* @param string $str String to clean
|
||||
* @return string
|
||||
*/
|
||||
public static function safe_ascii_for_xml($str)
|
||||
public function safe_ascii_for_xml($str)
|
||||
{
|
||||
return self::remove_invisible_characters($str, FALSE);
|
||||
return $this->remove_invisible_characters($str, FALSE);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -180,7 +180,7 @@ class Utf8 {
|
|||
* @param string $encoding Input encoding
|
||||
* @return string $str encoded in UTF-8 or FALSE on failure
|
||||
*/
|
||||
public static function convert_to_utf8($str, $encoding)
|
||||
public function convert_to_utf8($str, $encoding)
|
||||
{
|
||||
if (MB_ENABLED)
|
||||
{
|
||||
|
@ -204,7 +204,7 @@ class Utf8 {
|
|||
* @param string $str String to check
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_ascii($str)
|
||||
public function is_ascii($str)
|
||||
{
|
||||
return (preg_match('/[^\x00-\x7F]/S', $str) === 0);
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ class LayoutManager
|
|||
private static function getVariables()
|
||||
{
|
||||
$vars = array();
|
||||
$vars['adminURL'] = Config::get('main')->SITE_URL.'admin/';
|
||||
$vars['adminURL'] = Config::get('main')->base_url.'admin/';
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ return array(
|
|||
'aliases' => array(),
|
||||
'dependencies' => array(),
|
||||
'events' => array(),
|
||||
'routes' => array('/^admin(|\/(?P<identifier>.*?)(|\/(?<page>.*?)(|\/(?P<subdata>.*?))))$/'),
|
||||
'routes' => array('admin(|\/(?P<identifier>.*?)(|\/(?<page>.*?)(|\/(?P<subdata>.*?))))'),
|
||||
'advertise' => array('admin' => array('identifier' => 'fuzeadmin', 'pages' => array(array('name' => 'TEST', 'page_path' => 'testPage', 'icon' => 'fa-plane')))),
|
||||
'listenFor' => array('admin'),
|
||||
'name' => 'FuzeWorks Admin Panel',
|
||||
|
|
|
@ -56,7 +56,7 @@ return array(
|
|||
// Routes that this module listens on. Any URL that matches this pattern will load this module
|
||||
// If the URL /example/ gets called, this module will be loaded
|
||||
// Everything after /example/ will be sent to the route() function in the matches array under the, in this example, 'data' key
|
||||
'routes' => array('/^example(|\/(?P<data>.*?))$/'),
|
||||
'routes' => array('example(|\/(?P<data>.*?))$'),
|
||||
|
||||
// Advertises some data with the key 'exampleAdvertisement'. This data will be sent to a module which listens for this key.
|
||||
// This allows for some data to be sent to a module which listens to this key.
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
"php": ">=5.4.0",
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"smarty/smarty": "~3.1"
|
||||
"smarty/smarty": "~3.1",
|
||||
"tracy/tracy": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "5.3.*",
|
||||
|
|
|
@ -30,7 +30,9 @@
|
|||
* @version Version 0.0.1
|
||||
*/
|
||||
use FuzeWorks\Core;
|
||||
use FuzeWorks\Router;
|
||||
use FuzeWorks\Factory;
|
||||
|
||||
define('ENVIRONMENT', 'PRODUCTION');
|
||||
|
||||
// Include framework
|
||||
require_once dirname(__FILE__).'/Core/System/class.core.php';
|
||||
|
@ -38,5 +40,5 @@ require_once dirname(__FILE__).'/Core/System/class.core.php';
|
|||
// Load it
|
||||
Core::init();
|
||||
|
||||
Router::setPath((isset($_GET['path']) ? $_GET['path'] : null));
|
||||
Router::route();
|
||||
$router = Factory::getInstance()->router;
|
||||
$router->route();
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
*/
|
||||
use FuzeWorks\Events;
|
||||
use FuzeWorks\Layout;
|
||||
use FuzeWorks\Factory;
|
||||
|
||||
/**
|
||||
* Class CoreTestAbstract.
|
||||
|
@ -49,5 +50,6 @@ abstract class CoreTestAbstract extends PHPUnit_Framework_TestCase
|
|||
Events::$listeners = array();
|
||||
Layout::reset();
|
||||
Events::enable();
|
||||
Factory::getInstance()->output->set_output('');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,13 +41,6 @@ require_once 'Core/System/class.core.php';
|
|||
ob_start();
|
||||
Core::init();
|
||||
|
||||
// Disable debugger
|
||||
$cfg = Config::get('error');
|
||||
$cfg->debug = false;
|
||||
$cfg->error_reporting = false;
|
||||
$cfg->log_to_file = false;
|
||||
$cfg->commit();
|
||||
|
||||
restore_error_handler();
|
||||
restore_exception_handler();
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
* @version Version 0.0.1
|
||||
*/
|
||||
use FuzeWorks\Layout;
|
||||
use FuzeWorks\Factory;
|
||||
|
||||
/**
|
||||
* Class LayoutTest.
|
||||
|
@ -122,6 +123,7 @@ class layoutTest extends CoreTestAbstract
|
|||
|
||||
ob_start();
|
||||
Layout::view('test', $directory);
|
||||
Factory::getInstance()->output->_display();
|
||||
$output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks.
|
||||
*
|
||||
* The FuzeWorks MVC PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2015 TechFuze
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
||||
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
||||
*
|
||||
* @link http://fuzeworks.techfuze.net
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 0.0.1
|
||||
*/
|
||||
|
||||
use FuzeWorks\Factory;
|
||||
|
||||
/**
|
||||
* Class OutputTest.
|
||||
*
|
||||
* Core testing suite, will test basic output class functionality
|
||||
*/
|
||||
class outputTest extends CoreTestAbstract {
|
||||
|
||||
public $output;
|
||||
protected $_output_data = '';
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->_output_data =<<<HTML
|
||||
<html>
|
||||
<head>
|
||||
<title>Basic HTML</title>
|
||||
</head>
|
||||
<body>
|
||||
Test
|
||||
</body>
|
||||
</html>
|
||||
HTML;
|
||||
|
||||
Factory::getInstance()->config->main->charset = 'UTF-8';
|
||||
$this->output = Factory::getInstance()->output;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
public function test_set_get_append_output()
|
||||
{
|
||||
$append = "<!-- comment /-->\n";
|
||||
|
||||
$this->assertEquals(
|
||||
$this->_output_data.$append,
|
||||
$this->output
|
||||
->set_output($this->_output_data)
|
||||
->append_output("<!-- comment /-->\n")
|
||||
->get_output()
|
||||
);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
public function test_get_content_type()
|
||||
{
|
||||
$this->assertEquals('text/html', $this->output->get_content_type());
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
public function test_get_header()
|
||||
{
|
||||
$this->assertNull($this->output->get_header('Non-Existent-Header'));
|
||||
|
||||
// TODO: Find a way to test header() values as well. Currently,
|
||||
// PHPUnit prevents this by not using output buffering.
|
||||
|
||||
$this->output->set_content_type('text/plain', 'WINDOWS-1251');
|
||||
$this->assertEquals(
|
||||
'text/plain; charset=WINDOWS-1251',
|
||||
$this->output->get_header('content-type')
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,142 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks.
|
||||
*
|
||||
* The FuzeWorks MVC PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2015 TechFuze
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
||||
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
||||
*
|
||||
* @link http://fuzeworks.techfuze.net
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 0.0.1
|
||||
*/
|
||||
use FuzeWorks\Router;
|
||||
|
||||
/**
|
||||
* Class RouterTest.
|
||||
*
|
||||
* This test will test the router
|
||||
*/
|
||||
class routerTest extends CoreTestAbstract
|
||||
{
|
||||
public function testParsePath()
|
||||
{
|
||||
|
||||
// Act and assert
|
||||
Router::setPath('a/b/c/d/');
|
||||
$this->assertEquals('a/b/c/d', Router::getPath());
|
||||
|
||||
Router::setPath('//a//b//c');
|
||||
$this->assertEquals('a/b/c', Router::getPath());
|
||||
|
||||
Router::setPath('/');
|
||||
$this->assertEquals('', Router::getPath());
|
||||
|
||||
Router::setPath('');
|
||||
$this->assertEquals('', Router::getPath());
|
||||
|
||||
Router::setPath(false);
|
||||
$this->assertEquals('', Router::getPath());
|
||||
|
||||
Router::setPath(null);
|
||||
$this->assertEquals('', Router::getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testParsePath
|
||||
*/
|
||||
public function testDoRoute()
|
||||
{
|
||||
|
||||
// Act
|
||||
Router::setPath('a/b/c/d/');
|
||||
Router::route(false);
|
||||
|
||||
// Assert
|
||||
// Whole route
|
||||
$this->assertEquals(array('a', 'b', 'c/d'), array(Router::getMatches()['controller'], Router::getMatches()['function'], Router::getMatches()['parameters']));
|
||||
$this->assertEquals('a', Router::getMatches()['controller']);
|
||||
|
||||
// Parameters
|
||||
$this->assertEquals('c/d', Router::getMatches()['parameters']);
|
||||
|
||||
// Function and controller
|
||||
$this->assertEquals('a', Router::getMatches()['controller']);
|
||||
$this->assertEquals('b', Router::getMatches()['function']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testDoRoute
|
||||
*/
|
||||
public function testOddRoutes()
|
||||
{
|
||||
|
||||
// Empty path
|
||||
Router::setPath(null);
|
||||
Router::route(false);
|
||||
$this->assertEquals(null, Router::getMatches()['controller']);
|
||||
|
||||
// Double slashes
|
||||
Router::setPath('a///b');
|
||||
Router::route(false);
|
||||
$this->assertEquals(array('a', 'b'), array(Router::getMatches()['controller'], Router::getMatches()['function']));
|
||||
|
||||
// Escaped path path
|
||||
Router::setPath('/a\/b\/c/');
|
||||
Router::route(false);
|
||||
$this->assertEquals(array('a\\', 'b\\', 'c'), array(Router::getMatches()['controller'], Router::getMatches()['function'], Router::getMatches()['parameters']));
|
||||
$this->assertNotEquals('a', Router::getMatches()['controller']);
|
||||
}
|
||||
|
||||
public function testCustomRoute()
|
||||
{
|
||||
Router::addRoute('/test1\/test2/', 'callable');
|
||||
$this->assertArraySubset(array('/test1\/test2/' => 'callable'), Router::getRoutes());
|
||||
}
|
||||
|
||||
public function testCustomRouteWithParameters()
|
||||
{
|
||||
Router::addRoute('/^b\/(?P<controller>[^\/]+)\/?(?P<function>.+?)$/', 'callable');
|
||||
Router::addRoute('/e\/(?P<function>[^\/]+)/', 'callable');
|
||||
Router::addRoute('/b\/b$/', 'callable');
|
||||
|
||||
Router::setPath('b/controller_a/function_a');
|
||||
Router::route(false);
|
||||
$this->assertEquals('controller_a', Router::getMatches()['controller']);
|
||||
$this->assertEquals('function_a', Router::getMatches()['function']);
|
||||
|
||||
Router::setPath('e/function_b/c');
|
||||
Router::route(false);
|
||||
$this->assertFalse(isset(Router::getMatches()['controller']));
|
||||
$this->assertEquals('function_b', Router::getMatches()['function']);
|
||||
|
||||
Router::setPath('b/b');
|
||||
Router::route(false);
|
||||
$this->assertFalse(isset(Router::getMatches()['controller']));
|
||||
$this->assertFalse(isset(Router::getMatches()['function']));
|
||||
|
||||
Router::setPath('a/b');
|
||||
Router::route(false);
|
||||
$this->assertEquals('a', Router::getMatches()['controller']);
|
||||
$this->assertEquals('b', Router::getMatches()['function']);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks.
|
||||
*
|
||||
* The FuzeWorks MVC PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2015 TechFuze
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
||||
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
||||
*
|
||||
* @link http://fuzeworks.techfuze.net
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 0.0.1
|
||||
*/
|
||||
|
||||
use FuzeWorks\Factory;
|
||||
|
||||
/**
|
||||
* Class URITest.
|
||||
*
|
||||
* Core testing suite, will test URI class functionality
|
||||
*/
|
||||
class uriTest extends CoreTestAbstract {
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->uri = new Mock_Core_URI();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
public function test_filter_uri_passing()
|
||||
{
|
||||
$this->uri->_set_permitted_uri_chars('a-z 0-9~%.:_\-');
|
||||
|
||||
$str = 'abc01239~%.:_-';
|
||||
$this->uri->filter_uri($str);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @expectedException FuzeWorks\UriException
|
||||
*/
|
||||
public function test_filter_uri_throws_error()
|
||||
{
|
||||
$this->uri->config->routing->enable_query_strings = false;
|
||||
$this->uri->_set_permitted_uri_chars('a-z 0-9~%.:_\-');
|
||||
$segment = '$this()'; // filter_uri() accepts by reference
|
||||
$this->uri->filter_uri($segment);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
public function test_segment()
|
||||
{
|
||||
$this->uri->segments = array(1 => 'controller');
|
||||
$this->assertEquals($this->uri->segment(1), 'controller');
|
||||
$this->assertEquals($this->uri->segment(2, 'default'), 'default');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
public function test_rsegment()
|
||||
{
|
||||
$this->uri->rsegments = array(1 => 'method');
|
||||
$this->assertEquals($this->uri->rsegment(1), 'method');
|
||||
$this->assertEquals($this->uri->rsegment(2, 'default'), 'default');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
public function test_uri_to_assoc()
|
||||
{
|
||||
$this->uri->segments = array('a', '1', 'b', '2', 'c', '3');
|
||||
|
||||
$this->assertEquals(
|
||||
array('a' => '1', 'b' => '2', 'c' => '3'),
|
||||
$this->uri->uri_to_assoc(1)
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('b' => '2', 'c' => '3'),
|
||||
$this->uri->uri_to_assoc(3)
|
||||
);
|
||||
|
||||
$this->uri->keyval = array(); // reset cache
|
||||
$this->uri->segments = array('a', '1', 'b', '2', 'c');
|
||||
|
||||
$this->assertEquals(
|
||||
array('a' => '1', 'b' => '2', 'c' => FALSE),
|
||||
$this->uri->uri_to_assoc(1)
|
||||
);
|
||||
|
||||
$this->uri->keyval = array(); // reset cache
|
||||
$this->uri->segments = array('a', '1');
|
||||
|
||||
// test default
|
||||
$this->assertEquals(
|
||||
array('a' => '1', 'b' => FALSE),
|
||||
$this->uri->uri_to_assoc(1, array('a', 'b'))
|
||||
);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
public function test_ruri_to_assoc()
|
||||
{
|
||||
$this->uri->rsegments = array('x', '1', 'y', '2', 'z', '3');
|
||||
|
||||
$this->assertEquals(
|
||||
array('x' => '1', 'y' => '2', 'z' => '3'),
|
||||
$this->uri->ruri_to_assoc(1)
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
array('y' => '2', 'z' => '3'),
|
||||
$this->uri->ruri_to_assoc(3)
|
||||
);
|
||||
|
||||
$this->uri->keyval = array(); // reset cache
|
||||
$this->uri->rsegments = array('x', '1', 'y', '2', 'z');
|
||||
|
||||
$this->assertEquals(
|
||||
array('x' => '1', 'y' => '2', 'z' => FALSE),
|
||||
$this->uri->ruri_to_assoc(1)
|
||||
);
|
||||
|
||||
$this->uri->keyval = array(); // reset cache
|
||||
$this->uri->rsegments = array('x', '1');
|
||||
|
||||
// test default
|
||||
$this->assertEquals(
|
||||
array('x' => '1', 'y' => FALSE),
|
||||
$this->uri->ruri_to_assoc(1, array('x', 'y'))
|
||||
);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
public function test_assoc_to_uri()
|
||||
{
|
||||
//$this->uri->config->set_item('uri_string_slashes', 'none');
|
||||
$this->assertEquals('a/1/b/2', $this->uri->assoc_to_uri(array('a' => '1', 'b' => '2')));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
public function test_slash_segment()
|
||||
{
|
||||
$this->uri->segments[1] = 'segment';
|
||||
$this->uri->rsegments[1] = 'segment';
|
||||
|
||||
$this->assertEquals('/segment/', $this->uri->slash_segment(1, 'both'));
|
||||
$this->assertEquals('/segment/', $this->uri->slash_rsegment(1, 'both'));
|
||||
|
||||
$a = '/segment';
|
||||
$this->assertEquals('/segment', $this->uri->slash_segment(1, 'leading'));
|
||||
$this->assertEquals('/segment', $this->uri->slash_rsegment(1, 'leading'));
|
||||
|
||||
$this->assertEquals('segment/', $this->uri->slash_segment(1, 'trailing'));
|
||||
$this->assertEquals('segment/', $this->uri->slash_rsegment(1, 'trailing'));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks.
|
||||
*
|
||||
* The FuzeWorks MVC PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2015 TechFuze
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
||||
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
||||
*
|
||||
* @link http://fuzeworks.techfuze.net
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 0.0.1
|
||||
*/
|
||||
use FuzeWorks\Events;
|
||||
use FuzeWorks\Router;
|
||||
use FuzeWorks\EventPriority;
|
||||
use FuzeWorks\Layout;
|
||||
|
||||
/**
|
||||
* Class RouterLoadCallableEventTest.
|
||||
*/
|
||||
class routerLoadCallableEventTest extends CoreTestAbstract
|
||||
{
|
||||
/**
|
||||
* Check if the event is fired when it should be.
|
||||
*/
|
||||
public function test_basic()
|
||||
{
|
||||
$mock = $this->getMock('MockEvent', array('mockMethod'));
|
||||
$mock->expects($this->once())->method('mockMethod');
|
||||
|
||||
Router::setPath('/');
|
||||
Events::addListener(function ($event) {
|
||||
$event->setCancelled(true);
|
||||
|
||||
}, 'layoutLoadViewEvent', EventPriority::HIGHEST);
|
||||
Events::addListener(array($mock, 'mockMethod'), 'routerLoadCallableEvent', EventPriority::NORMAL);
|
||||
|
||||
//Prevent ouputting HTML
|
||||
ob_start();
|
||||
Router::route();
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept and change.
|
||||
*/
|
||||
public function test_change()
|
||||
{
|
||||
Events::addListener(function ($event) {
|
||||
$event->setCancelled(true);
|
||||
|
||||
}, 'layoutLoadViewEvent', EventPriority::HIGHEST);
|
||||
Events::addListener(array($this, 'listener_change'), 'routerLoadCallableEvent', EventPriority::NORMAL);
|
||||
Router::setPath('x/y/z');
|
||||
Router::route(true);
|
||||
|
||||
Events::$listeners = array();
|
||||
Events::addListener(function ($event) {
|
||||
$event->setCancelled(true);
|
||||
|
||||
}, 'layoutLoadViewEvent', EventPriority::HIGHEST);
|
||||
Events::addListener(array($this, 'listener_change'), 'routerLoadCallableEvent', EventPriority::NORMAL);
|
||||
Router::setPath('x/y/z');
|
||||
Router::route(true);
|
||||
|
||||
$this->assertNotNull(Router::getCallable());
|
||||
$this->assertInstanceOf('\Application\Controller\Standard', Router::getCallable());
|
||||
}
|
||||
|
||||
// Change title from new to other
|
||||
public function listener_change($event)
|
||||
{
|
||||
|
||||
// This controller should not exist
|
||||
$this->assertEquals('x', $event->matches['controller']);
|
||||
$this->assertEquals('y', $event->matches['function']);
|
||||
|
||||
// It should exist now
|
||||
$event->matches['controller'] = 'standard';
|
||||
$event->matches['function'] = 'index';
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel events.
|
||||
*/
|
||||
public function test_cancel()
|
||||
{
|
||||
ob_start();
|
||||
// When the callable may execute, the callable will change to the controller
|
||||
// (because '' will trigger the default callable)
|
||||
Router::setPath('');
|
||||
Events::addListener(array($this, 'listener_cancel'), 'routerLoadCallableEvent', EventPriority::NORMAL);
|
||||
Router::route();
|
||||
|
||||
$this->assertTrue(is_callable(Router::getCallable()));
|
||||
|
||||
// When disabled, the default controller will be loaded and the callable will be overwritten
|
||||
// Remove the listener
|
||||
Events::$listeners = array();
|
||||
Events::addListener(function ($event) {
|
||||
$event->setCancelled(true);
|
||||
|
||||
}, 'layoutLoadViewEvent', EventPriority::HIGHEST);
|
||||
|
||||
Router::route();
|
||||
$this->assertFalse(is_callable(Router::getCallable()));
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
// Cancel all calls
|
||||
public function listener_cancel($event)
|
||||
{
|
||||
$event->setCancelled(true);
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks.
|
||||
*
|
||||
* The FuzeWorks MVC PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2015 TechFuze
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
||||
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
||||
*
|
||||
* @link http://fuzeworks.techfuze.net
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 0.0.1
|
||||
*/
|
||||
use FuzeWorks\Events;
|
||||
use FuzeWorks\Router;
|
||||
use FuzeWorks\EventPriority;
|
||||
|
||||
/**
|
||||
* Class RouterRouteEventTest.
|
||||
*/
|
||||
class routerRouteEventTest extends CoreTestAbstract
|
||||
{
|
||||
/**
|
||||
* Check if the event is fired when it should be.
|
||||
*/
|
||||
public function test_basic()
|
||||
{
|
||||
$mock = $this->getMock('MockEvent', array('mockMethod'));
|
||||
$mock->expects($this->once())->method('mockMethod');
|
||||
|
||||
Events::addListener(array($mock, 'mockMethod'), 'routerRouteEvent', EventPriority::NORMAL);
|
||||
Router::setPath('a/b/c');
|
||||
Router::route(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel events.
|
||||
*/
|
||||
public function test_cancel()
|
||||
{
|
||||
Router::setPath('x/y/z');
|
||||
|
||||
Events::addListener(array($this, 'listener_cancel'), 'routerRouteEvent', EventPriority::NORMAL);
|
||||
Router::route(false);
|
||||
|
||||
$this->assertNotEquals('x', Router::getMatches()['controller']);
|
||||
$this->assertNotEquals('y', Router::getMatches()['function']);
|
||||
$this->assertNotEquals('z', Router::getMatches()['parameters']);
|
||||
}
|
||||
|
||||
// Cancel all calls
|
||||
public function listener_cancel($event)
|
||||
{
|
||||
$event->setCancelled(true);
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks.
|
||||
*
|
||||
* The FuzeWorks MVC PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2015 TechFuze
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
||||
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
||||
*
|
||||
* @link http://fuzeworks.techfuze.net
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 0.0.1
|
||||
*/
|
||||
use FuzeWorks\Events;
|
||||
use FuzeWorks\Router;
|
||||
use FuzeWorks\EventPriority;
|
||||
|
||||
/**
|
||||
* Class RouterSetPathEventTest.
|
||||
*/
|
||||
class routerSetPathEventTest extends CoreTestAbstract
|
||||
{
|
||||
/**
|
||||
* Check if the event is fired when it should be.
|
||||
*/
|
||||
public function testRouterSetPathEvent()
|
||||
{
|
||||
$mock = $this->getMock('MockEvent', array('mockMethod'));
|
||||
$mock->expects($this->once())->method('mockMethod');
|
||||
|
||||
Events::addListener(array($mock, 'mockMethod'), 'routerSetPathEvent', EventPriority::NORMAL);
|
||||
Router::setPath('a/b/c');
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept and change.
|
||||
*/
|
||||
public function testRouterSetPathEvent_change()
|
||||
{
|
||||
Events::addListener(array($this, 'listener_change'), 'routerSetPathEvent', EventPriority::NORMAL);
|
||||
Router::setPath('a/b/c');
|
||||
|
||||
$this->assertEquals('x/y/z', Router::getPath());
|
||||
}
|
||||
|
||||
// Change title from new to other
|
||||
public function listener_change($event)
|
||||
{
|
||||
$this->assertEquals('a/b/c', $event->path);
|
||||
$event->path = 'x/y/z';
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel events.
|
||||
*/
|
||||
public function testLayoutFunctionCallEvent_cancel()
|
||||
{
|
||||
Router::setPath('a/b/c');
|
||||
|
||||
Events::addListener(array($this, 'listener_cancel'), 'routerSetPathEvent', EventPriority::NORMAL);
|
||||
Router::setPath('x/y/z');
|
||||
|
||||
$this->assertEquals('a/b/c', Router::getPath());
|
||||
}
|
||||
|
||||
// Cancel all calls
|
||||
public function listener_cancel($event)
|
||||
{
|
||||
$event->setCancelled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not cancel events.
|
||||
*/
|
||||
public function testLayoutFunctionCallEvent_dontcancel()
|
||||
{
|
||||
Router::setPath('a/b/c');
|
||||
|
||||
Events::addListener(array($this, 'listener_dontcancel'), 'routerSetPathEvent', EventPriority::NORMAL);
|
||||
Router::setPath('x/y/z');
|
||||
|
||||
$this->assertEquals('x/y/z', Router::getPath());
|
||||
}
|
||||
|
||||
// Cancel all calls
|
||||
public function listener_dontcancel($event)
|
||||
{
|
||||
$event->setCancelled(false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
use FuzeWorks\Uri;
|
||||
use FuzeWorks\Factory;
|
||||
|
||||
class Mock_Core_URI extends Uri {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = Factory::getInstance()->config;
|
||||
|
||||
// set predictable config values
|
||||
$this->config->main->index_page = 'index.php';
|
||||
$this->config->main->base_url = 'http://example.com/';
|
||||
$this->config->main->application_prefix = 'MY_';
|
||||
$this->config->routing->enable_query_strings = false;
|
||||
$this->config->routing->permitted_uri_chars = 'a-z 0-9~%.:_\-';
|
||||
|
||||
|
||||
if ($this->config->routing->enable_query_strings !== TRUE OR is_cli())
|
||||
{
|
||||
$this->_permitted_uri_chars = $this->config->routing->permitted_uri_chars;
|
||||
}
|
||||
}
|
||||
|
||||
public function _set_permitted_uri_chars($value)
|
||||
{
|
||||
$this->_permitted_uri_chars = $value;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue