Merge branch 'holiday-edits' into 'development'

Holiday edits

Closes #111, #106, #82, #63, #5, and #115

See merge request !56
This commit is contained in:
Abel Hoogeveen 2017-09-22 15:49:43 +02:00
commit 32999c8e34
88 changed files with 1475 additions and 3299 deletions

1
.gitignore vendored
View File

@ -16,3 +16,4 @@ vendor/
build/
doc
nbproject
._*

View File

@ -8,7 +8,7 @@ stages:
- deploy
build:composer:
image: php:5.6
image: php:7.1
stage: build
script:
- curl -sS https://getcomposer.org/installer | php
@ -18,16 +18,6 @@ build:composer:
paths:
- vendor/
test:5.6:
stage: test
image: php:5.6
script:
- vendor/bin/phpunit -c tests/phpunit.xml --coverage-text
cache:
key: "$CI_BUILD_REF/$CI_BUILD_REF_NAME"
paths:
- vendor/
test:7.0:
stage: test
image: php:7.0
@ -38,14 +28,23 @@ test:7.0:
paths:
- vendor/
test:7.1:
stage: test
image: php:7.1
script:
- vendor/bin/phpunit -c tests/phpunit.xml --coverage-text
cache:
key: "$CI_BUILD_REF/$CI_BUILD_REF_NAME"
paths:
- vendor/
release:
stage: deploy
image: php:5.6
image: php:7.1
only:
- master
script:
- vendor/bin/phpunit -c tests/phpunit.xml --coverage-text
- vendor/bin/apigen generate -s . -d 'build/phpdoc' --todo --title 'FuzeWorks Build' --exclude 'tests/*','build/*','vendor/*','CI/*'
artifacts:
name: "${CI_BUILD_NAME}_${CI_BUILD_REF_NAME}"
paths:

View File

@ -1,8 +1,8 @@
language: php
php:
- 7.1
- 7
- 5.6
script:
- php vendor/bin/phpunit -v -c tests/phpunit.xml --coverage-text

View File

@ -24,11 +24,11 @@
"tracy/tracy": "Allows for extensive debugging"
},
"require-dev": {
"phpunit/phpunit": "5.3.*",
"apigen/apigen": "^4.1",
"phpunit/phpunit": "6.2.*",
"mikey179/vfsStream": "1.1.*",
"smarty/smarty": "~3.1",
"latte/latte": "*"
"smarty/smarty": "3.1.*",
"latte/latte": "2.4.*",
"tracy/tracy": "2.4.*"
},
"autoload": {
"psr-4": {

View File

@ -30,12 +30,12 @@
* @version Version 1.0.0
*/
use FuzeWorks\Factory;
use FuzeWorks\Core;
use FuzeWorks\Logger;
use FuzeWorks\Exception\DatabaseException;
use FuzeWorks\Utf8;
use FuzeWorks\Language;
use FuzeWorks\Core;
use FuzeWorks\DatabaseTracyBridge;
use FuzeWorks\Exception\DatabaseException;
/**
* Database Driver Class
@ -175,7 +175,7 @@ abstract class FW_DB_driver {
*
* @var bool
*/
public $db_debug = FALSE;
public $db_debug = TRUE;
/**
* Benchmark time
@ -217,6 +217,14 @@ abstract class FW_DB_driver {
*/
public $queries = array();
/**
* Data of performed queries
*
* @see FW_DB_driver::$save_queries
* @var array
*/
public $query_data = array();
/**
* Query times
*
@ -375,8 +383,6 @@ abstract class FW_DB_driver {
}
}
$this->factory = Factory::getInstance();
Logger::log('Database Driver ' . get_class($this) . ' Initialized');
}
@ -614,7 +620,6 @@ abstract class FW_DB_driver {
{
if ($sql === '')
{
Logger::logError('Invalid query: '.$sql);
return ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE;
}
elseif ( ! is_bool($return_object))
@ -661,6 +666,7 @@ abstract class FW_DB_driver {
if ($this->save_queries === TRUE)
{
$this->query_times[] = 0;
$this->query_data[] = array('error' => $this->error(), 'rows' => 0);
}
// This will trigger a rollback if transactions are being used
@ -672,9 +678,6 @@ abstract class FW_DB_driver {
// Grab the error now, as we might run some additional queries before displaying the error
$error = $this->error();
// Log errors
Logger::logError('Query error: '.$error['message'].' - Invalid query: '.$sql);
if ($this->db_debug)
{
// We call this function in order to roll-back queries
@ -703,11 +706,6 @@ abstract class FW_DB_driver {
$time_end = microtime(TRUE);
$this->benchmark += $time_end - $time_start;
if ($this->save_queries === TRUE)
{
$this->query_times[] = $time_end - $time_start;
}
// Increment the query counter
$this->query_count++;
@ -727,6 +725,12 @@ abstract class FW_DB_driver {
$driver = $this->load_rdriver();
$RES = new $driver($this);
if ($this->save_queries === TRUE)
{
$this->query_times[] = $time_end - $time_start;
$this->query_data[] = array('error' => $this->error(), 'rows' => $RES->num_rows());
}
// Is query caching enabled? If so, we'll serialize the
// result object and save it to a cache file.
if ($this->cache_on === TRUE && $this->_cache_init())
@ -766,7 +770,7 @@ abstract class FW_DB_driver {
if ( ! class_exists($driver, FALSE))
{
require_once(Core::$coreDir . DS . 'Database'.DS.'DB_result.php');
require_once(Core::$coreDir . DS . 'database'.DS.'drivers'.DS.$this->dbdriver.'/'.$this->dbdriver.'_result.php');
require_once(Core::$coreDir . DS . 'Database'.DS.'drivers'.DS.$this->dbdriver.'/'.$this->dbdriver.'_result.php');
}
return $driver;
@ -1740,7 +1744,7 @@ abstract class FW_DB_driver {
* @param string the error message
* @param string any "swap" values
* @param bool whether to localize the message
* @return string sends the application/views/errors/error_db.php template
* @return string sends the application/layout/errors/error_db.php template
*/
public function display_error($error = '', $swap = '', $native = FALSE)
{
@ -1762,6 +1766,8 @@ abstract class FW_DB_driver {
// the backtrace until the source file is no longer in the
// database folder.
$trace = debug_backtrace();
$file = '';
$line = '';
foreach ($trace as $call)
{
if (isset($call['file'], $call['class']))
@ -1775,19 +1781,16 @@ abstract class FW_DB_driver {
if (strpos($call['file'], Core::$coreDir . DS . 'Database') === FALSE && strpos($call['class'], 'Loader') === FALSE)
{
// Found it - use a relative path for safety
$message[] = 'Filename: '.str_replace(array('Application', 'Core'), '', $call['file']);
$message[] = 'Line Number: '.$call['line'];
$file = str_replace(array('Application', 'Core'), '', $call['file']);
$line = $call['line'];
break;
}
}
}
Logger::logError($heading);
foreach ($message as $message) {
Logger::logError($message);
}
Logger::http_error(500);
exit(8); // EXIT_DATABASE
Logger::logError($heading . " | " . implode(' | ', $message), null, $file, $line);
throw new DatabaseException($heading . ": " . implode(' ', $this->error()), 1);
}
// --------------------------------------------------------------------

View File

@ -33,6 +33,7 @@
use FuzeWorks\Logger;
use FuzeWorks\Helpers;
use FuzeWorks\Libraries;
use Fuzeworks\Factory;
use FuzeWorks\Exception\DatabaseException;
/**

View File

@ -1,515 +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://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.0
*/
use FuzeWorks\Logger;
/**
* MS SQL Database Adapter Class
*
* Note: _DB is an extender class that the app controller
* creates dynamically based on whether the query builder
* class is being used or not.
*
* Converted from CodeIgniter.
*
* @package FuzeWorks
* @subpackage Drivers
* @category Database
* @author EllisLab Dev Team
* @link https://codeigniter.com/user_guide/database/
* @license http://opensource.org/licenses/MIT MIT License
*/
class FW_DB_mssql_driver extends FW_DB {
/**
* Database driver
*
* @var string
*/
public $dbdriver = 'mssql';
// --------------------------------------------------------------------
/**
* ORDER BY random keyword
*
* @var array
*/
protected $_random_keyword = array('NEWID()', 'RAND(%d)');
/**
* Quoted identifier flag
*
* Whether to use SQL-92 standard quoted identifier
* (double quotes) or brackets for identifier escaping.
*
* @var bool
*/
protected $_quoted_identifier = TRUE;
// --------------------------------------------------------------------
/**
* Class constructor
*
* Appends the port number to the hostname, if needed.
*
* @param array $params
* @return void
*/
public function __construct($params)
{
parent::__construct($params);
if ( ! empty($this->port))
{
$this->hostname .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port;
}
}
// --------------------------------------------------------------------
/**
* Non-persistent database connection
*
* @param bool $persistent
* @return resource
*/
public function db_connect($persistent = FALSE)
{
$this->conn_id = ($persistent)
? mssql_pconnect($this->hostname, $this->username, $this->password)
: mssql_connect($this->hostname, $this->username, $this->password);
if ( ! $this->conn_id)
{
return FALSE;
}
// ----------------------------------------------------------------
// Select the DB... assuming a database name is specified in the config file
if ($this->database !== '' && ! $this->db_select())
{
Logger::logError('Unable to select database: '.$this->database);
return ($this->db_debug === TRUE)
? $this->display_error('db_unable_to_select', $this->database)
: FALSE;
}
// Determine how identifiers are escaped
$query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
$query = $query->row_array();
$this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
$this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
return $this->conn_id;
}
// --------------------------------------------------------------------
/**
* Select the database
*
* @param string $database
* @return bool
*/
public function db_select($database = '')
{
if ($database === '')
{
$database = $this->database;
}
// Note: Escaping is required in the event that the DB name
// contains reserved characters.
if (mssql_select_db('['.$database.']', $this->conn_id))
{
$this->database = $database;
return TRUE;
}
return FALSE;
}
// --------------------------------------------------------------------
/**
* Execute the query
*
* @param string $sql an SQL query
* @return mixed resource if rows are returned, bool otherwise
*/
protected function _execute($sql)
{
return mssql_query($sql, $this->conn_id);
}
// --------------------------------------------------------------------
/**
* Begin Transaction
*
* @return bool
*/
protected function _trans_begin()
{
return $this->simple_query('BEGIN TRAN');
}
// --------------------------------------------------------------------
/**
* Commit Transaction
*
* @return bool
*/
protected function _trans_commit()
{
return $this->simple_query('COMMIT TRAN');
}
// --------------------------------------------------------------------
/**
* Rollback Transaction
*
* @return bool
*/
protected function _trans_rollback()
{
return $this->simple_query('ROLLBACK TRAN');
}
// --------------------------------------------------------------------
/**
* Affected Rows
*
* @return int
*/
public function affected_rows()
{
return mssql_rows_affected($this->conn_id);
}
// --------------------------------------------------------------------
/**
* Insert ID
*
* Returns the last id created in the Identity column.
*
* @return string
*/
public function insert_id()
{
$query = version_compare($this->version(), '8', '>=')
? 'SELECT SCOPE_IDENTITY() AS last_id'
: 'SELECT @@IDENTITY AS last_id';
$query = $this->query($query);
$query = $query->row();
return $query->last_id;
}
// --------------------------------------------------------------------
/**
* Set client character set
*
* @param string $charset
* @return bool
*/
protected function _db_set_charset($charset)
{
return (ini_set('mssql.charset', $charset) !== FALSE);
}
// --------------------------------------------------------------------
/**
* Version number query string
*
* @return string
*/
protected function _version()
{
return "SELECT SERVERPROPERTY('ProductVersion') AS ver";
}
// --------------------------------------------------------------------
/**
* List table query
*
* Generates a platform-specific query string so that the table names can be fetched
*
* @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
$sql = 'SELECT '.$this->escape_identifiers('name')
.' FROM '.$this->escape_identifiers('sysobjects')
.' WHERE '.$this->escape_identifiers('type')." = 'U'";
if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
$sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
.sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
return $sql.' ORDER BY '.$this->escape_identifiers('name');
}
// --------------------------------------------------------------------
/**
* List column query
*
* Generates a platform-specific query string so that the column names can be fetched
*
* @param string $table
* @return string
*/
protected function _list_columns($table = '')
{
return 'SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.Columns
WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
}
// --------------------------------------------------------------------
/**
* Returns an object with field data
*
* @param string $table
* @return array
*/
public function field_data($table)
{
$sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.Columns
WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
if (($query = $this->query($sql)) === FALSE)
{
return FALSE;
}
$query = $query->result_object();
$retval = array();
for ($i = 0, $c = count($query); $i < $c; $i++)
{
$retval[$i] = new stdClass();
$retval[$i]->name = $query[$i]->COLUMN_NAME;
$retval[$i]->type = $query[$i]->DATA_TYPE;
$retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;
$retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
}
return $retval;
}
// --------------------------------------------------------------------
/**
* Error
*
* Returns an array containing code and message of the last
* database error that has occured.
*
* @return array
*/
public function error()
{
// We need this because the error info is discarded by the
// server the first time you request it, and query() already
// calls error() once for logging purposes when a query fails.
static $error = array('code' => 0, 'message' => NULL);
$message = mssql_get_last_message();
if ( ! empty($message))
{
$error['code'] = $this->query('SELECT @@ERROR AS code')->row()->code;
$error['message'] = $message;
}
return $error;
}
// --------------------------------------------------------------------
/**
* Update statement
*
* Generates a platform-specific update string from the supplied data
*
* @param string $table
* @param array $values
* @return string
*/
protected function _update($table, $values)
{
$this->qb_limit = FALSE;
$this->qb_orderby = array();
return parent::_update($table, $values);
}
// --------------------------------------------------------------------
/**
* Truncate statement
*
* Generates a platform-specific truncate string from the supplied data
*
* If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
* @param string $table
* @return string
*/
protected function _truncate($table)
{
return 'TRUNCATE TABLE '.$table;
}
// --------------------------------------------------------------------
/**
* Delete statement
*
* Generates a platform-specific delete string from the supplied data
*
* @param string $table
* @return string
*/
protected function _delete($table)
{
if ($this->qb_limit)
{
return 'WITH fw_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM fw_delete';
}
return parent::_delete($table);
}
// --------------------------------------------------------------------
/**
* LIMIT
*
* Generates a platform-specific LIMIT clause
*
* @param string $sql SQL Query
* @return string
*/
protected function _limit($sql)
{
$limit = $this->qb_offset + $this->qb_limit;
// As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported,
// however an ORDER BY clause is required for it to work
if (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby))
{
$orderby = $this->_compile_order_by();
// We have to strip the ORDER BY clause
$sql = trim(substr($sql, 0, strrpos($sql, $orderby)));
// Get the fields to select from our subquery, so that we can avoid FW_rownum appearing in the actual results
if (count($this->qb_select) === 0)
{
$select = '*'; // Inevitable
}
else
{
// Use only field names and their aliases, everything else is out of our scope.
$select = array();
$field_regexp = ($this->_quoted_identifier)
? '("[^\"]+")' : '(\[[^\]]+\])';
for ($i = 0, $c = count($this->qb_select); $i < $c; $i++)
{
$select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)
? $m[1] : $this->qb_select[$i];
}
$select = implode(', ', $select);
}
return 'SELECT '.$select." FROM (\n\n"
.preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('FW_rownum').', ', $sql)
."\n\n) ".$this->escape_identifiers('FW_subquery')
."\nWHERE ".$this->escape_identifiers('FW_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
}
return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
}
// --------------------------------------------------------------------
/**
* Insert batch statement
*
* Generates a platform-specific insert string from the supplied data.
*
* @param string $table Table name
* @param array $keys INSERT keys
* @param array $values INSERT values
* @return string|bool
*/
protected function _insert_batch($table, $keys, $values)
{
// Multiple-value inserts are only supported as of SQL Server 2008
if (version_compare($this->version(), '10', '>='))
{
return parent::_insert_batch($table, $keys, $values);
}
return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
// --------------------------------------------------------------------
/**
* Close DB Connection
*
* @return void
*/
protected function _close()
{
mssql_close($this->conn_id);
}
}

View File

@ -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://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.0
*/
/**
* MS SQL Forge Class
*
* Converted from CodeIgniter.
*
* @package FuzeWorks
* @subpackage Drivers
* @category Database
* @author EllisLab Dev Team
* @link https://codeigniter.com/user_guide/database/
* @license http://opensource.org/licenses/MIT MIT License
*/
class FW_DB_mssql_forge extends FW_DB_forge {
/**
* CREATE TABLE IF statement
*
* @var string
*/
protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
/**
* DROP TABLE IF statement
*
* @var string
*/
protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
/**
* UNSIGNED support
*
* @var array
*/
protected $_unsigned = array(
'TINYINT' => 'SMALLINT',
'SMALLINT' => 'INT',
'INT' => 'BIGINT',
'REAL' => 'FLOAT'
);
// --------------------------------------------------------------------
/**
* ALTER TABLE
*
* @param string $alter_type ALTER type
* @param string $table Table name
* @param mixed $field Column definition
* @return string|string[]
*/
protected function _alter_table($alter_type, $table, $field)
{
if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
{
return parent::_alter_table($alter_type, $table, $field);
}
$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
$sqls = array();
for ($i = 0, $c = count($field); $i < $c; $i++)
{
$sqls[] = $sql.$this->_process_column($field[$i]);
}
return $sqls;
}
// --------------------------------------------------------------------
/**
* Field attribute TYPE
*
* Performs a data type mapping between different databases.
*
* @param array &$attributes
* @return void
*/
protected function _attr_type(&$attributes)
{
switch (strtoupper($attributes['TYPE']))
{
case 'MEDIUMINT':
$attributes['TYPE'] = 'INTEGER';
$attributes['UNSIGNED'] = FALSE;
return;
case 'INTEGER':
$attributes['TYPE'] = 'INT';
return;
default: return;
}
}
// --------------------------------------------------------------------
/**
* Field attribute AUTO_INCREMENT
*
* @param array &$attributes
* @param array &$field
* @return void
*/
protected function _attr_auto_increment(&$attributes, &$field)
{
if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
{
$field['auto_increment'] = ' IDENTITY(1,1)';
}
}
}

View File

@ -1,194 +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://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.0
*/
/**
* MSSQL Result Class
*
* This class extends the parent result class: FW_DB_result
*
* Converted from CodeIgniter.
*
* @package FuzeWorks
* @subpackage Drivers
* @category Database
* @author EllisLab Dev Team
* @link https://codeigniter.com/user_guide/database/
* @license http://opensource.org/licenses/MIT MIT License
*/
class FW_DB_mssql_result extends FW_DB_result {
/**
* Number of rows in the result set
*
* @return int
*/
public function num_rows()
{
return is_int($this->num_rows)
? $this->num_rows
: $this->num_rows = mssql_num_rows($this->result_id);
}
// --------------------------------------------------------------------
/**
* Number of fields in the result set
*
* @return int
*/
public function num_fields()
{
return mssql_num_fields($this->result_id);
}
// --------------------------------------------------------------------
/**
* Fetch Field Names
*
* Generates an array of column names
*
* @return array
*/
public function list_fields()
{
$field_names = array();
mssql_field_seek($this->result_id, 0);
while ($field = mssql_fetch_field($this->result_id))
{
$field_names[] = $field->name;
}
return $field_names;
}
// --------------------------------------------------------------------
/**
* Field data
*
* Generates an array of objects containing field meta-data
*
* @return array
*/
public function field_data()
{
$retval = array();
for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
$field = mssql_fetch_field($this->result_id, $i);
$retval[$i] = new stdClass();
$retval[$i]->name = $field->name;
$retval[$i]->type = $field->type;
$retval[$i]->max_length = $field->max_length;
}
return $retval;
}
// --------------------------------------------------------------------
/**
* Free the result
*
* @return void
*/
public function free_result()
{
if (is_resource($this->result_id))
{
mssql_free_result($this->result_id);
$this->result_id = FALSE;
}
}
// --------------------------------------------------------------------
/**
* Data Seek
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
* result set starts at zero.
*
* @param int $n
* @return bool
*/
public function data_seek($n = 0)
{
return mssql_data_seek($this->result_id, $n);
}
// --------------------------------------------------------------------
/**
* Result - associative array
*
* Returns the result set as an array
*
* @return array
*/
protected function _fetch_assoc()
{
return mssql_fetch_assoc($this->result_id);
}
// --------------------------------------------------------------------
/**
* Result - object
*
* Returns the result set as an object
*
* @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
{
$row = mssql_fetch_object($this->result_id);
if ($class_name === 'stdClass' OR ! $row)
{
return $row;
}
$class_name = new $class_name();
foreach ($row as $key => $value)
{
$class_name->$key = $value;
}
return $class_name;
}
}

View File

@ -1,73 +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://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.0
*/
/**
* MS SQL Utility Class
*
* Converted from CodeIgniter.
*
* @package FuzeWorks
* @subpackage Drivers
* @category Database
* @author EllisLab Dev Team
* @link https://codeigniter.com/user_guide/database/
* @license http://opensource.org/licenses/MIT MIT License
*/
class FW_DB_mssql_utility extends FW_DB_utility {
/**
* List databases statement
*
* @var string
*/
protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases
/**
* OPTIMIZE TABLE statement
*
* @var string
*/
protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE';
/**
* Export
*
* @param array $params Preferences
* @return bool
*/
protected function _backup($params = array())
{
// Currently unsupported
return $this->db->display_error('db_unsupported_feature');
}
}

View File

@ -1,492 +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://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.0
*/
use FuzeWorks\Logger;
use FuzeWorks\Exception\DatabaseException;
/**
* MySQL Database Adapter Class
*
* Note: _DB is an extender class that the app controller
* creates dynamically based on whether the query builder
* class is being used or not.
*
* Converted from CodeIgniter.
*
* @package FuzeWorks
* @subpackage Drivers
* @category Database
* @author EllisLab Dev Team
* @link https://codeigniter.com/user_guide/database/
* @license http://opensource.org/licenses/MIT MIT License
*/
class FW_DB_mysql_driver extends FW_DB {
/**
* Database driver
*
* @var string
*/
public $dbdriver = 'mysql';
/**
* Compression flag
*
* @var bool
*/
public $compress = FALSE;
/**
* DELETE hack flag
*
* Whether to use the MySQL "delete hack" which allows the number
* of affected rows to be shown. Uses a preg_replace when enabled,
* adding a bit more processing to all queries.
*
* @var bool
*/
public $delete_hack = TRUE;
/**
* Strict ON flag
*
* Whether we're running in strict SQL mode.
*
* @var bool
*/
public $stricton;
// --------------------------------------------------------------------
/**
* Identifier escape character
*
* @var string
*/
protected $_escape_char = '`';
// --------------------------------------------------------------------
/**
* Class constructor
*
* @param array $params
* @return void
*/
public function __construct($params)
{
parent::__construct($params);
if ( ! empty($this->port))
{
$this->hostname .= ':'.$this->port;
}
}
// --------------------------------------------------------------------
/**
* Non-persistent database connection
*
* @param bool $persistent
* @return resource
*/
public function db_connect($persistent = FALSE)
{
$client_flags = ($this->compress === FALSE) ? 0 : MYSQL_CLIENT_COMPRESS;
if ($this->encrypt === TRUE)
{
$client_flags = $client_flags | MYSQL_CLIENT_SSL;
}
// Error suppression is necessary mostly due to PHP 5.5+ issuing E_DEPRECATED messages
$this->conn_id = ($persistent === TRUE)
? mysql_pconnect($this->hostname, $this->username, $this->password, $client_flags)
: mysql_connect($this->hostname, $this->username, $this->password, TRUE, $client_flags);
// ----------------------------------------------------------------
// Select the DB... assuming a database name is specified in the config file
if ($this->database !== '' && ! $this->db_select())
{
Logger::logError('Unable to select database: '.$this->database);
return ($this->db_debug === TRUE)
? $this->display_error('db_unable_to_select', $this->database)
: FALSE;
}
if (isset($this->stricton) && is_resource($this->conn_id))
{
if ($this->stricton)
{
$this->simple_query('SET SESSION sql_mode = CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")');
}
else
{
$this->simple_query(
'SET SESSION sql_mode =
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
@@sql_mode,
"STRICT_ALL_TABLES,", ""),
",STRICT_ALL_TABLES", ""),
"STRICT_ALL_TABLES", ""),
"STRICT_TRANS_TABLES,", ""),
",STRICT_TRANS_TABLES", ""),
"STRICT_TRANS_TABLES", "")'
);
}
}
return $this->conn_id;
}
// --------------------------------------------------------------------
/**
* Reconnect
*
* Keep / reestablish the db connection if no queries have been
* sent for a length of time exceeding the server's idle timeout
*
* @return void
*/
public function reconnect()
{
if (mysql_ping($this->conn_id) === FALSE)
{
$this->conn_id = FALSE;
}
}
// --------------------------------------------------------------------
/**
* Select the database
*
* @param string $database
* @return bool
*/
public function db_select($database = '')
{
if ($database === '')
{
$database = $this->database;
}
if (mysql_select_db($database, $this->conn_id))
{
$this->database = $database;
return TRUE;
}
return FALSE;
}
// --------------------------------------------------------------------
/**
* Set client character set
*
* @param string $charset
* @return bool
*/
protected function _db_set_charset($charset)
{
return mysql_set_charset($charset, $this->conn_id);
}
// --------------------------------------------------------------------
/**
* Database version number
*
* @return string
*/
public function version()
{
if (isset($this->data_cache['version']))
{
return $this->data_cache['version'];
}
if ( ! $this->conn_id OR ($version = mysql_get_server_info($this->conn_id)) === FALSE)
{
return FALSE;
}
return $this->data_cache['version'] = $version;
}
// --------------------------------------------------------------------
/**
* Execute the query
*
* @param string $sql an SQL query
* @return mixed
*/
protected function _execute($sql)
{
return mysql_query($this->_prep_query($sql), $this->conn_id);
}
// --------------------------------------------------------------------
/**
* Prep the query
*
* If needed, each database adapter can prep the query string
*
* @param string $sql an SQL query
* @return string
*/
protected function _prep_query($sql)
{
// mysql_affected_rows() returns 0 for "DELETE FROM TABLE" queries. This hack
// modifies the query so that it a proper number of affected rows is returned.
if ($this->delete_hack === TRUE && preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
{
return trim($sql).' WHERE 1=1';
}
return $sql;
}
// --------------------------------------------------------------------
/**
* Begin Transaction
*
* @return bool
*/
protected function _trans_begin()
{
$this->simple_query('SET AUTOCOMMIT=0');
return $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
}
// --------------------------------------------------------------------
/**
* Commit Transaction
*
* @return bool
*/
protected function _trans_commit()
{
if ($this->simple_query('COMMIT'))
{
$this->simple_query('SET AUTOCOMMIT=1');
return TRUE;
}
return FALSE;
}
// --------------------------------------------------------------------
/**
* Rollback Transaction
*
* @return bool
*/
protected function _trans_rollback()
{
if ($this->simple_query('ROLLBACK'))
{
$this->simple_query('SET AUTOCOMMIT=1');
return TRUE;
}
return FALSE;
}
// --------------------------------------------------------------------
/**
* Platform-dependant string escape
*
* @param string
* @return string
*/
protected function _escape_str($str)
{
return mysql_real_escape_string($str, $this->conn_id);
}
// --------------------------------------------------------------------
/**
* Affected Rows
*
* @return int
*/
public function affected_rows()
{
return mysql_affected_rows($this->conn_id);
}
// --------------------------------------------------------------------
/**
* Insert ID
*
* @return int
*/
public function insert_id()
{
return mysql_insert_id($this->conn_id);
}
// --------------------------------------------------------------------
/**
* List table query
*
* Generates a platform-specific query string so that the table names can be fetched
*
* @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
$sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
}
return $sql;
}
// --------------------------------------------------------------------
/**
* Show column query
*
* Generates a platform-specific query string so that the column names can be fetched
*
* @param string $table
* @return string
*/
protected function _list_columns($table = '')
{
return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
}
// --------------------------------------------------------------------
/**
* Returns an object with field data
*
* @param string $table
* @return array
*/
public function field_data($table)
{
if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
{
return FALSE;
}
$query = $query->result_object();
$retval = array();
for ($i = 0, $c = count($query); $i < $c; $i++)
{
$retval[$i] = new stdClass();
$retval[$i]->name = $query[$i]->Field;
sscanf($query[$i]->Type, '%[a-z](%d)',
$retval[$i]->type,
$retval[$i]->max_length
);
$retval[$i]->default = $query[$i]->Default;
$retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
}
return $retval;
}
// --------------------------------------------------------------------
/**
* Error
*
* Returns an array containing code and message of the last
* database error that has occured.
*
* @return array
*/
public function error()
{
return array('code' => mysql_errno($this->conn_id), 'message' => mysql_error($this->conn_id));
}
// --------------------------------------------------------------------
/**
* FROM tables
*
* Groups tables in FROM clauses if needed, so there is no confusion
* about operator precedence.
*
* @return string
*/
protected function _from_tables()
{
if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
{
return '('.implode(', ', $this->qb_from).')';
}
return implode(', ', $this->qb_from);
}
// --------------------------------------------------------------------
/**
* Close DB Connection
*
* @return void
*/
protected function _close()
{
// Error suppression to avoid annoying E_WARNINGs in cases
// where the connection has already been closed for some reason.
@mysql_close($this->conn_id);
}
}

View File

@ -1,240 +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://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.0
*/
/**
* MySQL Forge Class
*
* Converted from CodeIgniter.
*
* @package FuzeWorks
* @category Database
* @author EllisLab Dev Team
* @link https://codeigniter.com/user_guide/database/
* @license http://opensource.org/licenses/MIT MIT License
*/
class FW_DB_mysql_forge extends FW_DB_forge {
/**
* CREATE DATABASE statement
*
* @var string
*/
protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';
/**
* CREATE TABLE keys flag
*
* Whether table keys are created from within the
* CREATE TABLE statement.
*
* @var bool
*/
protected $_create_table_keys = TRUE;
/**
* UNSIGNED support
*
* @var array
*/
protected $_unsigned = array(
'TINYINT',
'SMALLINT',
'MEDIUMINT',
'INT',
'INTEGER',
'BIGINT',
'REAL',
'DOUBLE',
'DOUBLE PRECISION',
'FLOAT',
'DECIMAL',
'NUMERIC'
);
/**
* NULL value representation in CREATE/ALTER TABLE statements
*
* @var string
*/
protected $_null = 'NULL';
// --------------------------------------------------------------------
/**
* CREATE TABLE attributes
*
* @param array $attributes Associative array of table attributes
* @return string
*/
protected function _create_table_attr($attributes)
{
$sql = '';
foreach (array_keys($attributes) as $key)
{
if (is_string($key))
{
$sql .= ' '.strtoupper($key).' = '.$attributes[$key];
}
}
if ( ! empty($this->db->char_set) && ! strpos($sql, 'CHARACTER SET') && ! strpos($sql, 'CHARSET'))
{
$sql .= ' DEFAULT CHARACTER SET = '.$this->db->char_set;
}
if ( ! empty($this->db->dbcollat) && ! strpos($sql, 'COLLATE'))
{
$sql .= ' COLLATE = '.$this->db->dbcollat;
}
return $sql;
}
// --------------------------------------------------------------------
/**
* ALTER TABLE
*
* @param string $alter_type ALTER type
* @param string $table Table name
* @param mixed $field Column definition
* @return string|string[]
*/
protected function _alter_table($alter_type, $table, $field)
{
if ($alter_type === 'DROP')
{
return parent::_alter_table($alter_type, $table, $field);
}
$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
for ($i = 0, $c = count($field); $i < $c; $i++)
{
if ($field[$i]['_literal'] !== FALSE)
{
$field[$i] = ($alter_type === 'ADD')
? "\n\tADD ".$field[$i]['_literal']
: "\n\tMODIFY ".$field[$i]['_literal'];
}
else
{
if ($alter_type === 'ADD')
{
$field[$i]['_literal'] = "\n\tADD ";
}
else
{
$field[$i]['_literal'] = empty($field[$i]['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE ";
}
$field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]);
}
}
return array($sql.implode(',', $field));
}
// --------------------------------------------------------------------
/**
* Process column
*
* @param array $field
* @return string
*/
protected function _process_column($field)
{
$extra_clause = isset($field['after'])
? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';
if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)
{
$extra_clause = ' FIRST';
}
return $this->db->escape_identifiers($field['name'])
.(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))
.' '.$field['type'].$field['length']
.$field['unsigned']
.$field['null']
.$field['default']
.$field['auto_increment']
.$field['unique']
.(empty($field['comment']) ? '' : ' COMMENT '.$field['comment'])
.$extra_clause;
}
// --------------------------------------------------------------------
/**
* Process indexes
*
* @param string $table (ignored)
* @return string
*/
protected function _process_indexes($table)
{
$sql = '';
for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
if (is_array($this->keys[$i]))
{
for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
{
if ( ! isset($this->fields[$this->keys[$i][$i2]]))
{
unset($this->keys[$i][$i2]);
continue;
}
}
}
elseif ( ! isset($this->fields[$this->keys[$i]]))
{
unset($this->keys[$i]);
continue;
}
is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
$sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
.' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
$this->keys = array();
return $sql;
}
}

View File

@ -1,196 +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://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.0
*/
/**
* MySQL Result Class
*
* This class extends the parent result class: FW_DB_result
*
* Converted from CodeIgniter.
*
* @package FuzeWorks
* @category Database
* @author EllisLab Dev Team
* @link https://codeigniter.com/user_guide/database/
* @license http://opensource.org/licenses/MIT MIT License
*/
class FW_DB_mysql_result extends FW_DB_result {
/**
* Class constructor
*
* @param object &$driver_object
* @return void
*/
public function __construct(&$driver_object)
{
parent::__construct($driver_object);
// Required, due to mysql_data_seek() causing nightmares
// with empty result sets
$this->num_rows = mysql_num_rows($this->result_id);
}
// --------------------------------------------------------------------
/**
* Number of rows in the result set
*
* @return int
*/
public function num_rows()
{
return $this->num_rows;
}
// --------------------------------------------------------------------
/**
* Number of fields in the result set
*
* @return int
*/
public function num_fields()
{
return mysql_num_fields($this->result_id);
}
// --------------------------------------------------------------------
/**
* Fetch Field Names
*
* Generates an array of column names
*
* @return array
*/
public function list_fields()
{
$field_names = array();
mysql_field_seek($this->result_id, 0);
while ($field = mysql_fetch_field($this->result_id))
{
$field_names[] = $field->name;
}
return $field_names;
}
// --------------------------------------------------------------------
/**
* Field data
*
* Generates an array of objects containing field meta-data
*
* @return array
*/
public function field_data()
{
$retval = array();
for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
$retval[$i] = new stdClass();
$retval[$i]->name = mysql_field_name($this->result_id, $i);
$retval[$i]->type = mysql_field_type($this->result_id, $i);
$retval[$i]->max_length = mysql_field_len($this->result_id, $i);
$retval[$i]->primary_key = (int) (strpos(mysql_field_flags($this->result_id, $i), 'primary_key') !== FALSE);
}
return $retval;
}
// --------------------------------------------------------------------
/**
* Free the result
*
* @return void
*/
public function free_result()
{
if (is_resource($this->result_id))
{
mysql_free_result($this->result_id);
$this->result_id = FALSE;
}
}
// --------------------------------------------------------------------
/**
* Data Seek
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
* result set starts at zero.
*
* @param int $n
* @return bool
*/
public function data_seek($n = 0)
{
return $this->num_rows
? mysql_data_seek($this->result_id, $n)
: FALSE;
}
// --------------------------------------------------------------------
/**
* Result - associative array
*
* Returns the result set as an array
*
* @return array
*/
protected function _fetch_assoc()
{
return mysql_fetch_assoc($this->result_id);
}
// --------------------------------------------------------------------
/**
* Result - object
*
* Returns the result set as an object
*
* @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
{
return mysql_fetch_object($this->result_id, $class_name);
}
}

View File

@ -1,208 +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://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.0
*/
/**
* MySQL Utility Class
*
* Converted from CodeIgniter.
*
* @package FuzeWorks
* @category Database
* @author EllisLab Dev Team
* @link https://codeigniter.com/user_guide/database/
* @license http://opensource.org/licenses/MIT MIT License
*/
class FW_DB_mysql_utility extends FW_DB_utility {
/**
* List databases statement
*
* @var string
*/
protected $_list_databases = 'SHOW DATABASES';
/**
* OPTIMIZE TABLE statement
*
* @var string
*/
protected $_optimize_table = 'OPTIMIZE TABLE %s';
/**
* REPAIR TABLE statement
*
* @var string
*/
protected $_repair_table = 'REPAIR TABLE %s';
// --------------------------------------------------------------------
/**
* Export
*
* @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
if (count($params) === 0)
{
return FALSE;
}
// Extract the prefs for simplicity
extract($params);
// Build the output
$output = '';
// Do we need to include a statement to disable foreign key checks?
if ($foreign_key_checks === FALSE)
{
$output .= 'SET foreign_key_checks = 0;'.$newline;
}
foreach ( (array) $tables as $table)
{
// Is the table in the "ignore" list?
if (in_array($table, (array) $ignore, TRUE))
{
continue;
}
// Get the table schema
$query = $this->db->query('SHOW CREATE TABLE '.$this->db->escape_identifiers($this->db->database.'.'.$table));
// No result means the table name was invalid
if ($query === FALSE)
{
continue;
}
// Write out the table schema
$output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline;
if ($add_drop === TRUE)
{
$output .= 'DROP TABLE IF EXISTS '.$this->db->protect_identifiers($table).';'.$newline.$newline;
}
$i = 0;
$result = $query->result_array();
foreach ($result[0] as $val)
{
if ($i++ % 2)
{
$output .= $val.';'.$newline.$newline;
}
}
// If inserts are not needed we're done...
if ($add_insert === FALSE)
{
continue;
}
// Grab all the data from the current table
$query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table));
if ($query->num_rows() === 0)
{
continue;
}
// Fetch the field names and determine if the field is an
// integer type. We use this info to decide whether to
// surround the data with quotes or not
$i = 0;
$field_str = '';
$is_int = array();
while ($field = mysql_fetch_field($query->result_id))
{
// Most versions of MySQL store timestamp as a string
$is_int[$i] = in_array(strtolower(mysql_field_type($query->result_id, $i)),
array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'),
TRUE);
// Create a string of field names
$field_str .= $this->db->escape_identifiers($field->name).', ';
$i++;
}
// Trim off the end comma
$field_str = preg_replace('/, $/' , '', $field_str);
// Build the insert string
foreach ($query->result_array() as $row)
{
$val_str = '';
$i = 0;
foreach ($row as $v)
{
// Is the value NULL?
if ($v === NULL)
{
$val_str .= 'NULL';
}
else
{
// Escape the data if it's not an integer
$val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v;
}
// Append a comma
$val_str .= ', ';
$i++;
}
// Remove the comma at the end of the string
$val_str = preg_replace('/, $/' , '', $val_str);
// Build the INSERT string
$output .= 'INSERT INTO '.$this->db->protect_identifiers($table).' ('.$field_str.') VALUES ('.$val_str.');'.$newline;
}
$output .= $newline.$newline;
}
// Do we need to include a statement to re-enable foreign key checks?
if ($foreign_key_checks === FALSE)
{
$output .= 'SET foreign_key_checks = 1;'.$newline;
}
return $output;
}
}

View File

@ -32,7 +32,6 @@
use FuzeWorks\Logger;
use FuzeWorks\Exception\DatabaseException;
use PDOException;
/**
* PDO Database Adapter Class

View File

@ -30,8 +30,6 @@
* @version Version 1.0.0
*/
use \Exception;
/**
* PDO Result Class
*

View File

@ -151,6 +151,15 @@ class Configurator
return $this;
}
/**
* Set the email to send logs to from Tracy
* @param string
*/
public function setDebugEmail($email)
{
$this->parameters['debugEmail'] = $email;
}
/**
* Detects debug mode by IP address.
* @param string|array IP addresses or computer names whitelist detection
@ -180,7 +189,7 @@ class Configurator
* Due to the static nature of FuzeWorks, this is not yet possible.
* When issue #101 is completed, this should be resolved.
*
* @return void
* @return FuzeWorks\Factory
*/
public function createContainer()
{
@ -204,10 +213,16 @@ class Configurator
if (class_exists('Tracy\Debugger', true))
{
Debugger::enable(!$this->parameters['debugMode'], realpath($this->parameters['logDir']));
if (isset($this->parameters['debugEmail']))
{
Debugger::$email = $this->parameters['debugEmail'];
}
Logger::$useTracy = true;
}
// Then load the framework
Core::init();
return Factory::getInstance();
}
}

View File

@ -100,7 +100,7 @@ class Core
register_shutdown_function(array('\FuzeWorks\Core', 'shutdown'));
// Load core functionality
new Factory();
$container = new Factory();
// Load the config file of the FuzeWorks core
$config = Config::get('core');
@ -111,15 +111,6 @@ class Core
Events::disable();
}
// Build all the registers for correct operation, if modules are enabled
if ($config->enable_modules)
{
Modules::buildRegister($config->registry_caching,
$config->registry_caching_method,
$config->registry_caching_time
);
}
// And fire the coreStartEvent
$event = Events::fireEvent('coreStartEvent');
if ($event->isCancelled()) {
@ -127,7 +118,7 @@ class Core
}
// And initialize multiple classes
Layout::init();
$container->layout->init();
Language::init();
}

View File

@ -31,6 +31,7 @@
*/
namespace FuzeWorks;
use FuzeWorks\Exception\DatabaseException;
use FW_DB;
/**
@ -50,6 +51,12 @@ class Database
* @var type FW_DB|null
*/
protected static $defaultDB = null;
/**
* Array of all the non-default databases
* @var array FW_DB|null
*/
protected static $databases = array();
/**
* The default database forge.
@ -57,12 +64,29 @@ class Database
*/
protected static $defaultForge = null;
/**
* Array of all the non-default databases forges.
* @var array FW_DB_forge|null
*/
protected static $forges = array();
/**
* The default database utility.
* @var type FW_DB_utility|null
*/
protected static $defaultUtil = null;
/**
* Register with the TracyBridge upon startup
*/
public function __construct()
{
if (class_exists('Tracy\Debugger', true))
{
DatabaseTracyBridge::register();
}
}
/**
* Retrieve a database using a DSN or the default configuration.
*
@ -76,7 +100,6 @@ class Database
* default one. $newInstance will also make sure that the loaded database is not default one.
* This behaviour will be changed in the future.
*
* @todo Change $newInstance behaviour related to self::$defaultDB
*
* If $queryBuilder = false is provided, the database will load without a queryBuilder.
* By default the queryBuilder will load.
@ -84,48 +107,88 @@ class Database
* @param string $parameters
* @param bool $newInstance
* @param bool $queryBuilder
* @return FW_DB
* @return FW_DB|bool
*/
public static function get($parameters = '', $newInstance = false, $queryBuilder = null)
{
if (!$newInstance && is_object(self::$defaultDB) && ! empty(self::$defaultDB->conn_id))
// Fire the event to allow settings to be changed
$event = Events::fireEvent('databaseLoadDriverEvent', $parameters, $newInstance, $queryBuilder);
if ($event->isCancelled())
{
return false;
}
// If an instance already exists and is requested, return it
if (isset($event->database) && empty($event->parameters))
{
return self::$defaultDB = $event->database;
}
elseif (isset($event->database) && !empty($event->parameters))
{
return self::$databases[$event->parameters] = $event->database;
}
elseif (empty($event->parameters) && !$event->newInstance && is_object(self::$defaultDB) && ! empty(self::$defaultDB->conn_id))
{
return $reference = self::$defaultDB;
}
elseif (!empty($event->parameters) && !$event->newInstance && isset(self::$databases[$event->parameters]))
{
return $reference = self::$databases[$event->parameters];
}
// If a new instance is required, load it
require_once (Core::$coreDir . DS . 'Database'.DS.'DB.php');
if ($newInstance)
if ($event->newInstance === TRUE)
{
return DB($parameters, $queryBuilder);
$database = DB($event->parameters, $event->queryBuilder);
}
elseif (empty($event->parameters) && $event->newInstance === FALSE)
{
$database = self::$defaultDB = DB($event->parameters, $event->queryBuilder);
}
else
{
return self::$defaultDB = DB($parameters, $queryBuilder);
$database = self::$databases[$event->parameters] = DB($event->parameters, $event->queryBuilder);
}
// Tie it into the Tracy Bar if available
if (class_exists('\Tracy\Debugger', true))
{
DatabaseTracyBridge::registerDatabase($database);
}
return $database;
}
/**
* Retrieves a database forge from the provided or default database.
*
* If no database is provided, the default database will be used.
* @todo Change $newInstance behaviour with default instances.
*
*
* @param FW_DB $database
* @param bool $newInstance
* @param FW_DB|null $database
* @param bool $newInstance
* @return FW_DB_forge
*/
public static function getForge($database = null, $newInstance = false)
{
// Fire the event to allow settings to be changed
$event = Events::fireEvent('databaseLoadForgeEvent', $database, $newInstance);
if ($event->isCancelled())
{
return false;
}
// First check if we're talking about the default forge and that one is already set
if (is_object($database) && $database === self::$defaultDB && is_object(self::$defaultForge))
if (is_object($event->forge) && ($event->forge instanceof FW_DB_forge) )
{
return $event->forge;
}
elseif (is_object($event->database) && $event->database === self::$defaultDB && is_object(self::$defaultForge))
{
return $reference = self::$defaultForge;
}
if ( ! is_object($database) OR ! ($database instanceof FW_DB))
elseif ( ! is_object($event->database) OR ! ($event->database instanceof FW_DB))
{
isset(self::$defaultDB) OR self::get('', false);
$database =& self::$defaultDB;
@ -142,6 +205,10 @@ class Database
require_once($driver_path);
$class = 'FW_DB_'.$database->dbdriver.'_'.$database->subdriver.'_forge';
}
else
{
throw new DatabaseException("Could not load forge. Driver file does not exist.", 1);
}
}
else
{
@ -149,7 +216,7 @@ class Database
}
// Create a new instance of set the default database
if ($newInstance)
if ($event->newInstance)
{
return new $class($database);
}
@ -163,23 +230,31 @@ class Database
* Retrieves a database utility from the provided or default database.
*
* If no database is provided, the default database will be used.
* @todo Change $newInstance behaviour with default instances.
*
*
* @param FW_DB $database
* @param FW_DB|null $database
* @param bool $newInstance
* @return FW_DB_utility
*/
public static function getUtil($database = null, $newInstance = false)
{
// First check if we're talking about the default util and that one is already set
if (is_object($database) && $database === self::$defaultDB && is_object(self::$defaultUtil))
// Fire the event to allow settings to be changed
$event = Events::fireEvent('databaseLoadUtilEvent', $database, $newInstance);
if ($event->isCancelled())
{
return false;
}
// First check if we're talking about the default util and that one is already set
if (is_object($event->util) && ($event->util instanceof FW_DB_utility))
{
return $event->util;
}
elseif (is_object($event->database) && $event->database === self::$defaultDB && is_object(self::$defaultUtil))
{
echo "CALLED";
return $reference = self::$defaultUtil;
}
if ( ! is_object($database) OR ! ($database instanceof FW_DB))
if ( ! is_object($event->database) OR ! ($event->database instanceof FW_DB))
{
isset(self::$defaultDB) OR self::get('', false);
$database = & self::$defaultDB;
@ -189,7 +264,7 @@ class Database
require_once(Core::$coreDir . DS . 'Database'.DS.'drivers'.DS.$database->dbdriver.DS.$database->dbdriver.'_utility.php');
$class = 'FW_DB_'.$database->dbdriver.'_utility';
if ($newInstance)
if ($event->newInstance)
{
return new $class($database);
}

View File

@ -0,0 +1,142 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2017 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 - 2017, 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://techfuze.net/fuzeworks
* @since Version 1.0.4
*
* @version Version 1.0.4
*/
namespace FuzeWorks;
use Tracy\IBarPanel;
use Tracy\Debugger;
/**
* DatabaseTracyBridge Class.
*
* This class provides a bridge between FuzeWorks\Database and Tracy Debugging tool.
*
* This class registers in Tracy, and creates a Bar object which contains information about database sessions.
* It hooks into database usage and provides the information on the Tracy Bar panel.
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2017, Techfuze. (http://techfuze.net)
*/
class DatabaseTracyBridge implements IBarPanel
{
public static $databases = array();
protected $results = array();
public static function register()
{
$class = new self();
$bar = Debugger::getBar();
$bar->addPanel($class);
}
public static function registerDatabase($database)
{
self::$databases[] = $database;
}
protected function getResults()
{
if (!empty($this->results))
{
return $this->results;
}
// First prepare global variables
$results = array();
$results['dbCount'] = 0;
$results['queryCount'] = 0;
$results['queryTimings'] = 0.0;
$results['errorsFound'] = false;
// Go through all databases
foreach (self::$databases as $database) {
// Increase total databases
$results['dbCount']++;
// First determine the ID
if (!empty($database->dsn))
{
$databaseId = $database->dsn;
}
elseif (!empty($database->username) && !empty($database->database) && !empty($database->hostname))
{
$databaseId = $database->username . '@' . $database->hostname . '/' . $database->database;
}
else
{
$databaseId = spl_object_hash($database);
}
// Go through all queries
foreach ($database->queries as $key => $query) {
$results['queryCount']++;
$results['queryTimings'] += $database->query_times[$key];
$results['queries'][$databaseId][$key]['query'] = $query;
$results['queries'][$databaseId][$key]['timings'] = $database->query_times[$key];
$results['queries'][$databaseId][$key]['data'] = $database->query_data[$key];
// If errors are found, set this at the top of the array
if ($database->query_data[$key]['error']['code'] != 0)
{
$results['errorsFound'] = true;
}
}
}
// Limit the amount in order to keep things readable
$results['queryCountProvided'] = 0;
foreach ($results['queries'] as $id => $database) {
$results['queries'][$id] = array_reverse(array_slice($database, -10));
$results['queryCountProvided'] += count($results['queries'][$id]);
}
$results = array_slice($results, -10);
return $this->results = $results;
}
public function getTab()
{
$results = $this->getResults();
ob_start(function () {});
require dirname(__DIR__) . '/Layout/layout.tracydatabasetab.php';
return ob_get_clean();
}
public function getPanel()
{
// Parse the panel
$results = $this->getResults();
ob_start(function () {});
require dirname(__DIR__) . '/Layout/layout.tracydatabasepanel.php';
return ob_get_clean();
}
}

View File

@ -0,0 +1,85 @@
<?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 - 2017, 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://techfuze.net/fuzeworks
* @since Version 1.0.4
*
* @version Version 1.0.4
*/
namespace FuzeWorks\Event;
use FuzeWorks\Event;
/**
* Event that gets loaded when a database driver is loaded
*
* Use this to cancel the loading of a database, or change the provided database
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2017, Techfuze. (http://techfuze.net)
*/
class DatabaseLoadDriverEvent extends Event
{
/**
* A possible database that can be loaded.
*
* Provide a database in this variable and it will be loaded. It shall be identified as default if
* the parameters variable is empty. If there is a string in parameters this database shall be identified as
* such.
*
* @var FW_DB|null
*/
public $database = null;
/**
* Parameters of the database to be loaded
*
* @var string
*/
public $parameters;
/**
* Whether a database instance shall be cloned if existing
*
* @var bool
*/
public $newInstance;
/**
* Whether to attach the queryBuilder to the database driver
*
* @var null|bool
*/
public $queryBuilder;
public function init($parameters = '', $newInstance = false, $queryBuilder = null)
{
$this->parameters = $parameters;
$this->newInstance = $newInstance;
$this->queryBuilder = $queryBuilder;
}
}

View File

@ -0,0 +1,77 @@
<?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 - 2017, 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://techfuze.net/fuzeworks
* @since Version 1.0.4
*
* @version Version 1.0.4
*/
namespace FuzeWorks\Event;
use FuzeWorks\Event;
/**
* Event that gets loaded when a database forge is loaded
*
* Use this to cancel the loading of a forge, or change the provided database
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2017, Techfuze. (http://techfuze.net)
*/
class DatabaseLoadForgeEvent extends Event
{
/**
* A possible forge that can be loaded.
*
* Provide a forge in this variable and it will be loaded.
*
* @var FW_DB_forge|null
*/
public $forge = null;
/**
* Database to be used by the forge.
*
* If no database is provided, FuzeWorks\Database shall provide the default database
*
* @var FW_DB|null
*/
public $database = null;
/**
* Whether a database instance shall be cloned if existing
*
* @var bool
*/
public $newInstance;
public function init($database = null, $newInstance = false)
{
$this->database = $database;
$this->newInstance = $newInstance;
}
}

View File

@ -0,0 +1,77 @@
<?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 - 2017, 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://techfuze.net/fuzeworks
* @since Version 1.0.4
*
* @version Version 1.0.4
*/
namespace FuzeWorks\Event;
use FuzeWorks\Event;
/**
* Event that gets loaded when a database utility is loaded
*
* Use this to cancel the loading of a util, or change the provided database
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2017, Techfuze. (http://techfuze.net)
*/
class DatabaseLoadUtilEvent extends Event
{
/**
* A possible util that can be loaded.
*
* Provide a util in this variable and it will be loaded.
*
* @var FW_DB_util|null
*/
public $util = null;
/**
* Database to be used by the util.
*
* If no database is provided, FuzeWorks\Database shall provide the default database
*
* @var FW_DB_utility|null
*/
public $database = null;
/**
* Whether a database instance shall be cloned if existing
*
* @var bool
*/
public $newInstance;
public function init($database = null, $newInstance = false)
{
$this->database = $database;
$this->newInstance = $newInstance;
}
}

View File

@ -35,24 +35,24 @@ namespace FuzeWorks\Event;
use FuzeWorks\Event;
/**
* Event that gets loaded when a view is loaded.
* Event that gets loaded when a layout is loaded.
*
* Use this to cancel the loading of a view, or change the file or engine of a view
* Use this to cancel the loading of a layout, or change the file or engine of a layout
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
*/
class LayoutLoadViewEvent extends Event
class LayoutLoadEvent extends Event
{
/**
* The directory of the view to be loaded.
* The directory of the layout to be loaded.
*
* @var string
*/
public $directory;
/**
* The file of the view to be loaded.
* The file of the layout to be loaded.
*
* @var string
*/

View File

@ -37,8 +37,8 @@ use FuzeWorks\Exception\ModuleException;
/**
* Class Events.
*
* FuzeWorks is built in a way that almost every core-event can be manipulated by modules. This class provides various ways to hook into the core (or other modules)
* and manipulate the outcome of the functions. Modules and core actions can 'fire' an event and modules can 'hook' into that event. Let's take a look at the example below:
* FuzeWorks is built in a way that almost every core-event can be manipulated. This class provides various ways to hook into the core or other components
* and manipulate the outcome of the functions. Components and core actions can 'fire' an event and components can 'hook' into that event. Let's take a look at the example below:
*
* If we want to add the current time at the end of each page title, we need to hook to the corresponding event. Those events are found in the 'events' directory in the system directory.
* The event that will be fired when the title is changing is called layoutSetTitleEvent. So if we want our module to hook to that event, we add the following to the constructor:
@ -71,13 +71,6 @@ class Events
*/
private static $enabled = true;
/**
* A register with all the events and associated modules which should be loaded upon eventFire.
*
* @var array
*/
public static $register;
/**
* Adds a function as listener.
*
@ -134,11 +127,7 @@ class Events
throw new EventException('Unknown priority '.$priority);
}
if (!isset(self::$listeners[$eventName])) {
return;
}
if (!isset(self::$listeners[$eventName][$priority])) {
if (!isset(self::$listeners[$eventName]) || !isset(self::$listeners[$eventName][$priority])) {
return;
}
@ -164,47 +153,56 @@ class Events
*/
public static function fireEvent($input)
{
if (is_string($input)) {
// If the input is a string
$eventClass = $input;
$eventName = $input;
if (!class_exists($eventClass)) {
// Check if the file even exists
$file = Core::$coreDir . DS . 'Events' . DS . 'event.'.$eventName.'.php';
if (file_exists($file)) {
// Load the file
$eventClass = "\FuzeWorks\Event\\".$eventClass;
include_once $file;
} else {
// No event arguments? Looks like a notify-event
if (func_num_args() == 1) {
// Load notify-event-class
$eventClass = '\FuzeWorks\Event\NotifierEvent';
} else {
// No notify-event: we tried all we could
throw new EventException('Event '.$eventName.' could not be found!');
}
}
}
$event = new $eventClass($this);
} elseif (is_object($input)) {
// First try and see if the object is an Event
if (is_object($input))
{
$eventName = get_class($input);
$eventName = explode('\\', $eventName);
$eventName = end($eventName);
$event = $input;
} else {
// INVALID EVENT
return false;
}
// Otherwise try to load an event based on the input string
elseif (is_string($input))
{
$eventClass = ucfirst($input);
$eventName = $input;
// Try a direct class
if (class_exists($eventClass, true))
{
$event = new $eventClass();
}
// Try a core event
elseif (class_exists("\FuzeWorks\Event\\".$eventClass, true))
{
$class = "\FuzeWorks\Event\\".$eventClass;
$event = new $class();
}
// Try a notifier event
elseif (func_num_args() == 1)
{
$class = "\FuzeWorks\Event\NotifierEvent";
$event = new $class();
}
// Or throw an exception on failure
else
{
throw new EventException('Event '.$eventName.' could not be found!', 1);
}
}
else
{
throw new EventException('Event could not be loaded. Invalid variable provided.', 1);
}
if (self::$enabled)
{
Logger::newLevel("Firing Event: '".$eventName."'");
Logger::log('Initializing Event');
Logger::newLevel("Firing Event: '".$eventName."'");
}
if (func_num_args() > 1) {
call_user_func_array(array($event, 'init'), array_slice(func_get_args(), 1));
}
@ -216,14 +214,6 @@ class Events
Logger::log('Checking for Listeners');
// Read the event register for listeners
$register = self::$register;
if (isset($register[$eventName])) {
for ($i = 0; $i < count($register[$eventName]); ++$i) {
Modules::get($register[$eventName][$i]);
}
}
//There are listeners for this event
if (isset(self::$listeners[$eventName])) {
//Loop from the highest priority to the lowest
@ -234,6 +224,7 @@ class Events
Logger::newLevel('Found listeners with priority '.EventPriority::getPriority($priority));
//Fire the event to each listener
foreach ($listeners as $callback) {
// @codeCoverageIgnoreStart
if (is_callable($callback)) {
Logger::newLevel('Firing function');
} elseif (!is_string($callback[0])) {
@ -241,11 +232,9 @@ class Events
} else {
Logger::newLevel('Firing '.implode('->', $callback));
}
try {
call_user_func($callback, $event);
} catch (ModuleException $e) {
Logger::exceptionHandler($e);
}
// @codeCoverageIgnoreEnd
call_user_func($callback, $event);
Logger::stopLevel();
}

View File

@ -1,45 +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://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.1
*/
namespace FuzeWorks\Exception;
/**
* Class ModuleException.
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
*/
class ModuleException extends Exception
{
}
?>

View File

@ -94,7 +94,6 @@ class Factory
$this->instances['Events'] = new Events();
$this->instances['Models'] = new Models();
$this->instances['Layout'] = new Layout();
$this->instances['Modules'] = new Modules();
$this->instances['Libraries'] = new Libraries();
$this->instances['Helpers'] = new Helpers();
$this->instances['Database'] = new Database();

View File

@ -0,0 +1,255 @@
<?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://techfuze.net/fuzeworks
* @since Version 1.0.3
*
* @version Version 1.0.3
*/
namespace FuzeWorks;
use Tracy\IBarPanel;
use Tracy\Debugger;
/**
* GitTracyBridge Class.
*
* This class provides adds a panel to the Tracy Bar showing the current git branch
*
* This class registers in Tracy, and creates a Bar object which contains the Git version.
* @author Copyright (c) 2015 Jakub Vyvážil
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2017, Techfuze. (http://techfuze.net)
*/
class GitTracyBridge implements IBarPanel {
/**
* Register the bar
*/
public static function register()
{
$class = new self();
$bar = Debugger::getBar();
$bar->addPanel($class);
}
/**
* Renders HTML code for custom tab.
*
* @return string
*/
public function getTab()
{
$style = '';
if ($this->getBranchName() === 'master' || $this->getBranchName() === 'staging') {
$style = 'background:#dd4742;color:white;padding:3px 4px 4px';
}
$icon = '<svg viewBox="10 10 512 512"><path fill="#f03c2e" d="M 502.34111,278.80364 278.79809,502.34216 c -12.86794,12.87712 -33.74784,12.87712 -46.63305,0 l -46.4152,-46.42448 58.88028,-58.88364 c 13.68647,4.62092 29.3794,1.51948 40.28378,-9.38732 10.97012,-10.9748 14.04307,-26.80288 9.30465,-40.537 l 56.75401,-56.74844 c 13.73383,4.73404 29.56829,1.67384 40.53842,-9.31156 15.32297,-15.3188 15.32297,-40.15196 0,-55.48356 -15.3341,-15.3322 -40.16175,-15.3322 -55.50254,0 -11.52454,11.53592 -14.37572,28.47172 -8.53182,42.6722 l -52.93386,52.93048 0,-139.28512 c 3.73267,-1.84996 7.25863,-4.31392 10.37114,-7.41756 15.32295,-15.3216 15.32295,-40.15196 0,-55.49696 -15.32296,-15.3166 -40.16844,-15.3166 -55.48025,0 -15.32296,15.345 -15.32296,40.17536 0,55.49696 3.78727,3.78288 8.17299,6.64472 12.85234,8.5604 l 0,140.57336 c -4.67935,1.91568 -9.05448,4.75356 -12.85234,8.56264 -11.60533,11.60168 -14.39801,28.6378 -8.4449,42.89232 L 162.93981,433.11336 9.6557406,279.83948 c -12.8743209,-12.88768 -12.8743209,-33.768 0,-46.64456 L 233.20978,9.65592 c 12.87017,-12.87456 33.74338,-12.87456 46.63305,0 l 222.49828,222.50316 c 12.87852,12.87876 12.87852,33.76968 0,46.64456"/></svg>';
$label = '<span class="tracy-label" style="'.$style.'">'.$this->getBranchName().'</span>';
return $icon.$label;
}
/**
* Renders HTML code for custom panel.
*
* @return string
*/
public function getPanel()
{
if ($this->isUnderVersionControl()) {
$title = '<h1>GIT</h1>';
$warning = '';
$cntTable = '';
if ($this->getBranchName() === 'master' || $this->getBranchName() === 'staging') {
$warning = '<p style="color: #dd4742; font-weight: 700;">You are working in '.$this->getBranchName().' branch</p>';
}
// commit message
if ($this->getLastCommitMessage() !== null) {
$cntTable .= '<tr><td>Last commit</td><td> '.$this->getLastCommitMessage().' </td></tr>';
}
// heads
if ($this->getHeads() !== null) {
$cntTable .= '<tr><td>Branches</td><td> '.$this->getHeads().' </td></tr>';
}
// remotes
if ($this->getRemotes() !== null) {
$cntTable .= '<tr><td>Remotes</td><td> '.$this->getRemotes().' </td></tr>';
}
// tags
if ($this->getTags() !== null && !empty($this->getTags())) {
$cntTable .= '<tr><td>Tags</td><td> '.$this->getTags().' </td></tr>';
}
$content = '<div class=\"tracy-inner tracy-InfoPanel\"><table><tbody>'.
$cntTable.
'</tbody></table></div>';
return $title.$warning.$content;
}
}
protected function getBranchName()
{
$dir = $this->getDirectory();
$head = $dir.'/.git/HEAD';
if ($dir && is_readable($head)) {
$branch = file_get_contents($head);
if (strpos($branch, 'ref:') === 0) {
$parts = explode('/', $branch);
return substr($parts[2], 0, -1);
}
return '('.substr($branch, 0, 7).'&hellip;)';
}
return 'not versioned';
}
protected function getLastCommitMessage()
{
$dir = $this->getDirectory();
$fileMessage = $dir.'/.git/COMMIT_EDITMSG';
if ($dir && is_readable($fileMessage)) {
$message = file_get_contents($fileMessage);
return $message;
}
return null;
}
protected function getHeads()
{
$dir = $this->getDirectory();
$files = scandir($dir.'/.git/refs/heads');
$message = '';
if ($dir && is_array($files)) {
foreach ($files as $file) {
if ($file !== '.' && $file !== '..') {
if ($file === $this->getBranchName()) {
$message .= '<strong>'.$file.' </strong>';
} else {
$message .= $file.' <br>';
}
}
}
return $message;
}
return null;
}
protected function getRemotes()
{
$dir = $this->getDirectory();
try {
$files = scandir($dir.'/.git/refs/remotes');
} catch (\ErrorException $e) {
return null;
}
$message = '';
if ($dir && is_array($files)) {
foreach ($files as $file) {
if ($file !== '.' && $file !== '..') {
$message .= $file.' ';
}
}
return $message;
}
return null;
}
protected function getTags()
{
$dir = $this->getDirectory();
$files = scandir($dir.'/.git/refs/tags');
$message = '';
if ($dir && is_array($files)) {
foreach ($files as $file) {
if ($file !== '.' && $file !== '..') {
$message .= $file.' ';
}
}
return $message;
}
return null;
}
private function getDirectory()
{
$scriptPath = $_SERVER['SCRIPT_FILENAME'];
$dir = realpath(dirname($scriptPath));
while ($dir !== false && !is_dir($dir.'/.git')) {
flush();
$currentDir = $dir;
$dir .= '/..';
$dir = realpath($dir);
// Stop recursion to parent on root directory
if ($dir === $currentDir) {
break;
}
}
return $dir;
}
private function isUnderVersionControl()
{
$dir = $this->getDirectory();
$head = $dir.'/.git/HEAD';
if ($dir && is_readable($head)) {
return true;
}
return false;
}
}

View File

@ -4,7 +4,7 @@
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2015 TechFuze
* Copyright (C) 2017 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
@ -20,14 +20,14 @@
* 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) 2013 - 2017, 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://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.0
* @version Version 1.0.4
*/
namespace FuzeWorks;
@ -43,8 +43,7 @@ use FuzeWorks\Exception\LayoutException;
* Layout and Template Manager for FuzeWorks.
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @todo Make Object, remove static stuff
* @copyright Copyright (c) 2013 - 2017, Techfuze. (http://techfuze.net)
*/
class Layout
{
@ -53,60 +52,60 @@ class Layout
*
* @var null|string
*/
public static $file = null;
public $file = null;
/**
* The directory of the file to be loaded by the layout manager.
*
* @var string
*/
public static $directory;
public $directory;
/**
* All assigned currently assigned to the template.
*
* @var array Associative Assigned Variable Array
*/
private static $assigned_variables = array();
private $assigned_variables = array();
/**
* All engines that can be used for templates.
*
* @var array of engines
*/
private static $engines = array();
private $engines = array();
/**
* All file extensions that can be used and are bound to a template engine.
*
* @var array of names of engines
*/
private static $file_extensions = array();
private $file_extensions = array();
/**
* whether the template engines are already called.
*
* @var bool True if loaded
*/
private static $engines_loaded = false;
private $engines_loaded = false;
/**
* The currently selected template engine.
*
* @var string name of engine
*/
private static $current_engine;
private $current_engine;
public static function init()
public function init()
{
self::$directory = Core::$appDir . DS .'Views';
$this->directory = Core::$appDir . DS .'Layout';
}
/**
* 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.
* PHP for example uses .php files. Providing this function with 'home/dashboard' will load the home/layout.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.
*
@ -116,18 +115,18 @@ class Layout
*
* @throws LayoutException On error
*/
public static function view($file, $directory = null, $directOutput = false)
public function display($file, $directory = null, $directOutput = false)
{
$output = Factory::getInstance()->output;
$directory = (is_null($directory) ? self::$directory : $directory);
$directory = (is_null($directory) ? $this->directory : $directory);
if ($directOutput === true)
{
echo self::get($file, $directory);
echo $this->get($file, $directory);
}
else
{
$output->append_output(self::get($file, $directory));
$output->append_output($this->get($file, $directory));
}
return;
@ -137,7 +136,7 @@ class Layout
* Retrieve a template file using a string and a directory.
*
* 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.
* PHP for example uses .php files. Providing this function with 'home/dashboard' will load the home/layout.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.
*
@ -148,37 +147,37 @@ class Layout
*
* @throws LayoutException On error
*/
public static function get($file, $directory = null)
public function get($file, $directory = null)
{
$directory = (is_null($directory) ? self::$directory : $directory);
$directory = (is_null($directory) ? $this->directory : $directory);
Logger::newLevel("Loading template file '".$file."' in '".$directory."'");
// First load the template engines
self::loadTemplateEngines();
$this->loadTemplateEngines();
// First retrieve the filepath
if (is_null(self::$current_engine)) {
self::setFileFromString($file, $directory, array_keys(self::$file_extensions));
if (is_null($this->current_engine)) {
$this->setFileFromString($file, $directory, array_keys($this->file_extensions));
} else {
self::setFileFromString($file, $directory, self::$current_engine->getFileExtensions());
$this->setFileFromString($file, $directory, $this->current_engine->getFileExtensions());
}
// Then assign some basic variables for the template
self::$assigned_variables['wwwDir'] = Config::get('main')->base_url;
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();
$this->assigned_variables['wwwDir'] = Config::get('main')->base_url;
$this->assigned_variables['siteURL'] = Config::get('main')->base_url;
$this->assigned_variables['serverName'] = Config::get('main')->server_name;
$this->assigned_variables['adminMail'] = Config::get('main')->administrator_mail;
$this->assigned_variables['contact'] = Config::get('contact')->toArray();
// Select an engine if one is not already selected
if (is_null(self::$current_engine)) {
self::$current_engine = self::getEngineFromExtension(self::getExtensionFromFile(self::$file));
if (is_null($this->current_engine)) {
$this->current_engine = $this->getEngineFromExtension($this->getExtensionFromFile($this->file));
}
self::$current_engine->setDirectory(self::$directory);
$this->current_engine->setDirectory($this->directory);
// And run an Event to see what other parts have to say about it
$event = Events::fireEvent('layoutLoadViewEvent', self::$file, self::$directory, self::$current_engine, self::$assigned_variables);
$event = Events::fireEvent('layoutLoadEvent', $this->file, $this->directory, $this->current_engine, $this->assigned_variables);
// The event has been cancelled
if ($event->isCancelled()) {
@ -186,14 +185,14 @@ class Layout
}
// And refetch the data from the event
self::$current_engine = $event->engine;
self::$assigned_variables = $event->assigned_variables;
$this->current_engine = $event->engine;
$this->assigned_variables = $event->assigned_variables;
Logger::stopLevel();
// And finally run it
if (file_exists($event->file)) {
return self::$current_engine->get($event->file, self::$assigned_variables);
return $this->current_engine->get($event->file, $this->assigned_variables);
}
throw new LayoutException('The requested file was not found', 1);
@ -206,10 +205,10 @@ class Layout
*
* @return object Template Engine
*/
public static function getEngineFromExtension($extension)
public function getEngineFromExtension($extension)
{
if (isset(self::$file_extensions[strtolower($extension)])) {
return self::$engines[ self::$file_extensions[strtolower($extension)]];
if (isset($this->file_extensions[strtolower($extension)])) {
return $this->engines[ $this->file_extensions[strtolower($extension)]];
}
throw new LayoutException('Could not get Template Engine. No engine has corresponding file extension', 1);
@ -222,13 +221,13 @@ class Layout
*
* @return string Extension of the file
*/
public static function getExtensionFromFile($fileString)
public function getExtensionFromFile($fileString)
{
return substr($fileString, strrpos($fileString, '.') + 1);
}
/**
* Converts a view string to a file using the directory and the used extensions.
* Converts a layout string to a file using the directory and the used extensions.
*
* It will detect whether the file exists and choose a file according to the provided extensions
*
@ -240,9 +239,9 @@ class Layout
*
* @throws LayoutException On error
*/
public static function getFileFromString($string, $directory, $extensions = array())
public function getFileFromString($string, $directory, $extensions = array())
{
$directory = preg_replace('#/+#', '/', (!is_null($directory) ? $directory : self::$directory).'/');
$directory = preg_replace('#/+#', '/', (!is_null($directory) ? $directory : $this->directory).'/');
if (strpbrk($directory, "\\/?%*:|\"<>") === TRUE || strpbrk($string, "\\/?%*:|\"<>") === TRUE)
{
@ -254,30 +253,30 @@ class Layout
}
// Set the file name and location
$viewSelector = explode('/', $string);
if (count($viewSelector) == 1) {
$viewSelector = 'view.'.$viewSelector[0];
$layoutSelector = explode('/', $string);
if (count($layoutSelector) == 1) {
$layoutSelector = 'layout.'.$layoutSelector[0];
} else {
// Get last file
$file = end($viewSelector);
$file = end($layoutSelector);
// Reset to start
reset($viewSelector);
reset($layoutSelector);
// Remove last value
array_pop($viewSelector);
array_pop($layoutSelector);
$viewSelector[] = 'view.'.$file;
$layoutSelector[] = 'layout.'.$file;
// And create the final value
$viewSelector = implode('/', $viewSelector);
$layoutSelector = implode('/', $layoutSelector);
}
// Then try and select a file
$fileSelected = false;
$selectedFile = null;
foreach ($extensions as $extension) {
$file = $directory.$viewSelector.'.'.strtolower($extension);
$file = $directory.$layoutSelector.'.'.strtolower($extension);
$file = preg_replace('#/+#', '/', $file);
if (file_exists($file) && !$fileSelected) {
$selectedFile = $file;
@ -297,7 +296,7 @@ class Layout
}
/**
* Converts a view string to a file using the directory and the used extensions.
* Converts a layout string to a file using the directory and the used extensions.
* It also sets the file variable of this class.
*
* It will detect whether the file exists and choose a file according to the provided extensions
@ -310,10 +309,10 @@ class Layout
*
* @throws LayoutException On error
*/
public static function setFileFromString($string, $directory, $extensions = array())
public function setFileFromString($string, $directory, $extensions = array())
{
self::$file = self::getFileFromString($string, $directory, $extensions);
self::$directory = preg_replace('#/+#', '/', (!is_null($directory) ? $directory : self::$directory).'/');
$this->file = $this->getFileFromString($string, $directory, $extensions);
$this->directory = preg_replace('#/+#', '/', (!is_null($directory) ? $directory : $this->directory).'/');
}
/**
@ -321,9 +320,9 @@ class Layout
*
* @return null|string Path to the file
*/
public static function getFile()
public function getFile()
{
return self::$file;
return $this->file;
}
/**
@ -331,9 +330,9 @@ class Layout
*
* @param string $file Path to the file
*/
public static function setFile($file)
public function setFile($file)
{
self::$file = $file;
$this->file = $file;
}
/**
@ -341,9 +340,9 @@ class Layout
*
* @return null|string Path to the directory
*/
public static function getDirectory()
public function getDirectory()
{
return self::$directory;
return $this->directory;
}
/**
@ -351,9 +350,9 @@ class Layout
*
* @param string $directory Path to the directory
*/
public static function setDirectory($directory)
public function setDirectory($directory)
{
self::$directory = $directory;
$this->directory = $directory;
}
/**
@ -362,9 +361,9 @@ class Layout
* @param string $key Key of the variable
* @param mixed $value Value of the variable
*/
public static function assign($key, $value)
public function assign($key, $value)
{
self::$assigned_variables[$key] = $value;
$this->assigned_variables[$key] = $value;
}
/**
@ -372,9 +371,9 @@ class Layout
*
* @param string $title title of the template
*/
public static function setTitle($title)
public function setTitle($title)
{
self::$assigned_variables['title'] = $title;
$this->assigned_variables['title'] = $title;
}
/**
@ -382,13 +381,13 @@ class Layout
*
* @return string title of the template
*/
public static function getTitle()
public function getTitle()
{
if (!isset(self::$assigned_variables['title']))
if (!isset($this->assigned_variables['title']))
{
return false;
}
return self::$assigned_variables['title'];
return $this->assigned_variables['title'];
}
/**
@ -400,11 +399,11 @@ class Layout
*
* @throws \FuzeWorks\LayoutException on error
*/
public static function setEngine($name)
public function setEngine($name)
{
self::loadTemplateEngines();
if (isset(self::$engines[$name])) {
self::$current_engine = self::$engines[$name];
$this->loadTemplateEngines();
if (isset($this->engines[$name])) {
$this->current_engine = $this->engines[$name];
Logger::log('Set the Template Engine to '.$name);
return true;
@ -419,11 +418,11 @@ class Layout
*
* @return object Object that implements \FuzeWorks\TemplateEngine
*/
public static function getEngine($name)
public function getEngine($name)
{
self::loadTemplateEngines();
if (isset(self::$engines[$name])) {
return self::$engines[$name];
$this->loadTemplateEngines();
if (isset($this->engines[$name])) {
return $this->engines[$name];
}
throw new LayoutException('Could not return engine. Engine does not exist', 1);
}
@ -439,17 +438,17 @@ class Layout
*
* @throws \FuzeWorks\LayoutException On error
*/
public static function registerEngine($engineClass, $engineName, $engineFileExtensions = array())
public function registerEngine($engineClass, $engineName, $engineFileExtensions = array())
{
// First check if the engine already exists
if (isset(self::$engines[$engineName])) {
if (isset($this->engines[$engineName])) {
throw new LayoutException("Could not register engine. Engine '".$engineName."' already registered", 1);
}
// Then check if the object is correct
if ($engineClass instanceof TemplateEngine) {
// Install it
self::$engines[$engineName] = $engineClass;
$this->engines[$engineName] = $engineClass;
// Then define for what file extensions this Template Engine will work
if (!is_array($engineFileExtensions)) {
@ -458,12 +457,12 @@ class Layout
// Then install them
foreach ($engineFileExtensions as $extension) {
if (isset(self::$file_extensions[strtolower($extension)])) {
if (isset($this->file_extensions[strtolower($extension)])) {
throw new LayoutException('Could not register engine. File extension already bound to engine', 1);
}
// And add it
self::$file_extensions[strtolower($extension)] = $engineName;
$this->file_extensions[strtolower($extension)] = $engineName;
}
// And log it
@ -478,17 +477,17 @@ class Layout
/**
* Load the template engines by sending a layoutLoadEngineEvent.
*/
public static function loadTemplateEngines()
public function loadTemplateEngines()
{
if (!self::$engines_loaded) {
if (!$this->engines_loaded) {
Events::fireEvent('layoutLoadEngineEvent');
// Load the engines provided in this file
self::registerEngine(new PHPEngine(), 'PHP', array('php'));
self::registerEngine(new JsonEngine(), 'JSON', array('json'));
self::registerEngine(new SmartyEngine(), 'Smarty', array('tpl'));
self::registerEngine(new LatteEngine(), 'Latte', array('latte'));
self::$engines_loaded = true;
$this->registerEngine(new PHPEngine(), 'PHP', array('php'));
$this->registerEngine(new JsonEngine(), 'JSON', array('json'));
$this->registerEngine(new SmartyEngine(), 'Smarty', array('tpl'));
$this->registerEngine(new LatteEngine(), 'Latte', array('latte'));
$this->engines_loaded = true;
}
}
@ -503,11 +502,11 @@ class Layout
public static function __callStatic($name, $params)
{
// First load the template engines
self::loadTemplateEngines();
$this->loadTemplateEngines();
if (!is_null(self::$current_engine)) {
if (!is_null($this->current_engine)) {
// Call user func array here
return call_user_func_array(array(self::$current_engine, $name), $params);
return call_user_func_array(array($this->current_engine, $name), $params);
}
throw new LayoutException('Could not access Engine. Engine not loaded', 1);
}
@ -515,20 +514,20 @@ class Layout
/**
* Resets the layout manager to its default state.
*/
public static function reset()
public function reset()
{
if (!is_null(self::$current_engine)) {
self::$current_engine->reset();
if (!is_null($this->current_engine)) {
$this->current_engine->reset();
}
// Unload the engines
self::$engines = array();
self::$engines_loaded = false;
self::$file_extensions = array();
$this->engines = array();
$this->engines_loaded = false;
$this->file_extensions = array();
self::$current_engine = null;
self::$assigned_variables = array();
self::$directory = Core::$appDir . DS . 'Views';
$this->current_engine = null;
$this->assigned_variables = array();
$this->directory = Core::$appDir . DS . 'Layout';
Logger::log('Reset the layout manager to its default state');
}
}

View File

@ -120,6 +120,7 @@ class Logger {
if (self::$useTracy)
{
LoggerTracyBridge::register();
GitTracyBridge::register();
}
}
@ -168,9 +169,14 @@ class Logger {
$errstr = $error['message'];
// Log it!
$thisType = self::getType($errno);
Factory::getInstance()->output->set_output('');
self::errorHandler($errno, $errstr, $errfile, $errline);
self::http_error('500');
if ($thisType == 'ERROR')
{
self::http_error('500');
}
}
}
@ -211,8 +217,8 @@ class Logger {
self::logError('Exception thrown: ' . $message . ' | ' . $code, null, $file, $line);
// And return a 500 because this error was fatal
self::http_error('500');
// And return a 500 because this error was fatal
self::http_error('500');
}
/**
@ -239,7 +245,7 @@ class Logger {
}
$logs = self::$Logs;
require(dirname(__DIR__) . '/views/view.' . self::$logger_template . '.php');
require(dirname(__DIR__) . '/Layout/layout.' . self::$logger_template . '.php');
}
/**
@ -250,7 +256,7 @@ class Logger {
{
ob_start(function () {});
$logs = self::$Logs;
require(dirname(__DIR__) . '/views/view.logger_cli.php');
require(dirname(__DIR__) . '/Layout/layout.logger_cli.php');
$contents = ob_get_clean();
$file = Core::$logDir .DS. 'Logs'.DS.'log_latest.php';
if (is_writable($file))
@ -458,9 +464,9 @@ class Logger {
* Calls an HTTP error, sends it as a header, and loads a template if required to do so.
*
* @param int $errno HTTP error code
* @param bool $view true to view error on website
* @param bool $layout true to layout error on website
*/
public static function http_error($errno = 500, $view = true) {
public static function http_error($errno = 500, $layout = true) {
$http_codes = array(
400 => 'Bad Request',
401 => 'Unauthorized',
@ -501,22 +507,23 @@ class Logger {
self::log('Sending header HTTP/1.1 ' . $errno . ' ' . $http_codes[$errno]);
header('HTTP/1.1 ' . $errno . ' ' . $http_codes[$errno]);
// Do we want the error-view with it?
if ($view == false) {
// Do we want the error-layout with it?
if ($layout == false) {
return;
}
// Load the view
$view = 'errors/' . $errno;
self::log('Loading view ' . $view);
// Load the layout
$layout = 'errors/' . $errno;
self::log('Loading layout ' . $layout);
// Try and load the view, if impossible, load HTTP code instead.
// Try and load the layout, if impossible, load HTTP code instead.
$factory = Factory::getInstance();
try {
Layout::reset();
Layout::view($view);
$factory->Layout->reset();
$factory->Layout->display($layout);
} catch (LayoutException $exception) {
// No error page could be found, just echo the result
Factory::getInstance()->output->set_output("<h1>$errno</h1><h3>" . $http_codes[$errno] . '</h3>');
$factory->output->set_output("<h1>$errno</h1><h3>" . $http_codes[$errno] . '</h3>');
}
}

View File

@ -73,7 +73,7 @@ class LoggerTracyBridge implements IBarPanel {
public function getTab()
{
ob_start(function () {});
require dirname(__DIR__) . '/views/view.tracyloggertab.php';
require dirname(__DIR__) . '/Layout/layout.tracyloggertab.php';
return ob_get_clean();
}
@ -101,7 +101,7 @@ class LoggerTracyBridge implements IBarPanel {
// Parse the panel
ob_start(function () {});
require dirname(__DIR__) . '/views/view.tracyloggerpanel.php';
require dirname(__DIR__) . '/Layout/layout.tracyloggerpanel.php';
return ob_get_clean();
}

View File

@ -1,204 +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://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.0
*/
namespace FuzeWorks;
/**
* Trait Module.
*
* Contains all the methods modules should have
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @deprecated
*/
trait Module
{
/**
* @var null|string Relative path to the module
*/
protected static $modulePath = null;
/**
* @var string Internal name of the module
*/
protected static $moduleName = 'placeholder';
/**
* @var string name used in the mod array
*/
protected static $linkName = 'placeholder';
/**
* @var moduleInfo object of the module
*/
protected static $cfg;
/**
* @var array Advertisements send from other modules
*/
protected static $advertisements = array();
/**
* Returns the name of the module.
*
* @return string Returns the name of the module
*/
public static function getModuleName()
{
return self::$moduleName;
}
/**
* Returns the path to the module.
*
* @return null|string
*/
public static function getModulePath()
{
return self::$modulePath;
}
/**
* Returns the config of the module (moduleInfo.php).
*
* @return stdClass module config
*/
public static function getModuleConfig()
{
return self::$cfg;
}
/**
* Changes the path to the location of the module.
*
* This function can only be executed once, because when the path has been set this function won't save changes anymore.
* This prevents modules or other systems to mess with modules and their stability.
*
* @param string $modulePath
*/
public static function setModulePath($modulePath = null)
{
// Only allow one change of this variable from outside
if (self::$modulePath === null) {
self::$modulePath = $modulePath;
}
}
/**
* Set the link name of the module. The link name is the address in the module array so that the module can self reference.
*
* @param string link name
*/
public static function setModuleLinkName($linkName)
{
self::$linkName = $linkName;
}
/**
* The name that is required to load itself, eg 'exampleauthor/examplemodulename' or 'techfuze/cms'.
*
* @param string module name
*/
public static function setModuleName($modName)
{
self::$moduleName = $modName;
}
/**
* Add the moduleInfo.php to the module for direct interaction.
*
* @param stdClass module config
*/
public static function setModuleConfig($config)
{
self::$cfg = $config;
}
/**
* Set a value in the modules moduleInfo.php.
*
* @param mixed config Key
* @param mixed config value
*/
public static function setConfigValue($key, $value)
{
$file = self::getModulePath().'moduleInfo.php';
self::$cfg->$key = $value;
// Check if the module path is set yet
if (self::getModulePath() == null) {
Logger::logWarning('Could not write module config. ModulePath is not set', get_class($this));
return false;
}
if (file_exists($file) && is_writable($file)) {
$config = var_export($this->cfg, true);
file_put_contents($file, "<?php return $config ;");
}
}
/**
* Set the advertisements send by other modules.
*
* @param array $advertisements Advertisement data
*/
public static function setAdvertisements($advertiseName, $advertiseData)
{
self::$advertisements[$advertiseName] = $advertiseData;
}
/**
* Get the advertisements with a specific name.
*
* @param string $advertiseName AdvertisementName
*
* @return array AdvertisementData
*/
public static function getAdvertisements($advertiseName)
{
return self::$advertisements[$advertiseName];
}
/**
* Return a value from the module configuration.
*
* @param mixed config Key
*
* @return mixed config value
*/
public static function getConfigValue($key)
{
return self::$cfg->$key;
}
}

View File

@ -1,598 +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://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.0
*/
namespace FuzeWorks;
use FuzeWorks\Exception\ModuleException;
use stdClass;
/**
* Modules Class.
*
* @author Abel Hoogeveen <abel@techfuze.net>
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
* @deprecated
*/
class Modules
{
/**
* A register of all the existing module headers.
*
* The module headers contain information required to loading the module
*
* @var array
*/
private static $register;
/**
* A register which holds all the module advertisements by key.
*
* @var array
*/
private static $advertiseRegister = array();
/**
* An array of all the loaded modules.
*
* @var array
*/
public static $modules = array();
/**
* An array with the names of all modules that are loaded, and should not be loaded again.
*
* @var array of module names
*/
private static $loaded_modules = array();
/**
* An array which holds the routes to module to load them quickly.
*
* @var array
*/
private static $module_routes = array();
/**
* Retrieves a module and returns it.
* If a module is already loaded, it returns a reference to the loaded version.
*
* @param string $name Name of the module
*
* @return \FuzeWorks\Module Module The module
*
* @throws \FuzeWorks\ModuleException
*/
public static function get($name)
{
// Where the modules are
$path = Core::$appDir . DS . 'Modules/';
// Check if the requested module is registered
if (isset(self::$register[$name])) {
if (!empty(self::$register[$name])) {
// Load the moduleInfo
$cfg = (object) self::$register[$name];
// Check if the module is disabled
if (isset($cfg->meta)) {
throw new ModuleException("Could not load module. Module '".$name."' is not enabled", 1);
}
// Check if the module is already loaded. If so, only return a reference, if not, load the module
if (in_array(strtolower($name), self::$loaded_modules)) {
// return the link
$c = self::$modules[strtolower($cfg->module_name)];
return $c;
} else {
// Load the module
$file = $cfg->directory.'/'.$cfg->module_file;
// Load the dependencies before the module loads
$deps = (isset($cfg->dependencies) ? $cfg->dependencies : array());
for ($i = 0; $i < count($deps); ++$i) {
self::get($deps[$i]);
}
// Check if the file exists
if (file_exists($file)) {
// And load it
include_once $file;
$class_name = $cfg->module_class;
$msg = "Loading Module '".ucfirst((isset($cfg->name) ? $cfg->name : $cfg->module_name))."'";
$msg .= (isset($cfg->version) ? '; version: '.$cfg->version : '');
$msg .= (isset($cfg->author) ? '; made by '.$cfg->author : '');
$msg .= (isset($cfg->website) ? '; from '.$cfg->website : '');
Logger::log($msg);
} else {
// Throw Exception if the file does not exist
throw new ModuleException("Could not load module. Module '".$name."' class file was not found.", 1);
return false;
}
// If it is an abstract module, load an StdClass for the module address
if (isset($cfg->abstract)) {
if ($cfg->abstract) {
$CLASS = new stdClass();
return self::$modules[strtolower($cfg->module_name)] = &$CLASS;
}
}
// Load the module class
$class_name = $cfg->module_class;
$CLASS = new $class_name();
// Apply default methods
if (method_exists($CLASS, 'setModulePath')) {
$CLASS::setModulePath($cfg->directory);
}
if (method_exists($CLASS, 'setModuleLinkName')) {
$CLASS::setModuleLinkName(strtolower($cfg->module_name));
}
if (method_exists($CLASS, 'setModuleName')) {
$CLASS::setModuleName($name);
}
// Send all advertisements
if (isset($cfg->listenFor)) {
$listenFor = $cfg->listenFor;
if (method_exists($CLASS, 'setAdvertisements')) {
foreach ($listenFor as $advertiseName) {
if (isset(self::$advertiseRegister[$advertiseName])) {
$CLASS::setAdvertisements($advertiseName, self::$advertiseRegister[$advertiseName]);
}
}
} else {
throw new ModuleException("Could not load module. Module '".$name."' listens for advertisement but does not implement setAdvertisements() method.", 1);
}
}
// Send the moduleConfig if possible
if (method_exists($CLASS, 'setModuleConfig')) {
// Append the config file to the module CFG (accessable through $this->cfg)
if (file_exists($cfg->directory.'/'.'config.'.strtolower($cfg->module_name).'.php')) {
$data = (object) include $cfg->directory.'/'.'config.'.strtolower($cfg->module_name).'.php';
foreach ($data as $key => $value) {
$cfg->$key = $value;
}
}
$CLASS::setModuleConfig($cfg);
}
// And finally check if it can be loaded
if (!method_exists($CLASS, 'onLoad')) {
throw new ModuleException("Could not load module. Module '".$name."' does not have an onLoad() method", 1);
}
// Prepare onLoad call
$args = func_get_args();
array_shift($args);
// And call onLoad
call_user_func_array(array($CLASS, 'onLoad'), $args);
// Add to the loaded modules
self::$loaded_modules[] = strtolower($name);
// Return a reference
return self::$modules[strtolower($cfg->module_name)] = &$CLASS;
}
} else {
throw new ModuleException("Could not load module. Module '".$name."' has an invalid config", 1);
}
} else {
throw new ModuleException("Module not found: '".$name."'", 1);
}
}
/**
* Set the value of a module config or moduleInfo.php.
*
* @param string $file File to edit
* @param string $key Key to edit
* @param mixed $value Value to set
*/
private static function setModuleValue($file, $key, $value)
{
if (file_exists($file) && is_writable($file)) {
$cfg = include $file;
$cfg[$key] = $value;
$config = var_export($cfg, true);
file_put_contents($file, "<?php return $config ;");
}
}
/**
* Add a module using a moduleInfo.php file.
*
* @param string Path to moduleInfo.php file
*
* @throws FuzeWorks\ModuleException
*/
public static function addModule($moduleInfo_file)
{
$file = $moduleInfo_file;
$directory = dirname($file);
if (file_exists($file)) {
$cfg = (object) include $file;
$cfg->directory = $directory;
// Define the module name
$name = '';
$name .= (!empty($cfg->author) ? strtolower($cfg->author).'/' : '');
$name .= strtolower($cfg->module_name);
Logger::log("Adding module: '".$name."'");
if (isset(self::$register[$name])) {
Logger::logError("Module '".$name."' can not be added. Module is already loaded");
return false;
}
// Check whether the module is enabled or no
if (isset($cfg->enabled)) {
if ($cfg->enabled) {
// Copy all the data into the register and enable
self::$register[$name] = (array) $cfg;
Logger::log("[ON] '".$name."'");
} else {
// If not, copy all the basic data so that it can be enabled in the future
$cfg2 = new StdClass();
$cfg2->module_name = $cfg->module_name;
$cfg2->directory = $cfg->directory;
$cfg2->meta = $cfg;
self::$register[$name] = (array) $cfg2;
Logger::log("[OFF] '".$name."'");
}
} else {
// Copy all the data into the register and enable
self::$register[$name] = (array) $cfg;
Logger::log("[ON] '".$name."'");
}
} else {
throw new ModuleException("Could not add module. '$moduleInfo_file' does not exist", 1);
}
}
/**
* Enables a module when it is disabled.
*
* @param string Module name
* @param bool true for permanent enable
*
* @throws FuzeWorks\ModuleException
*/
public static function enableModule($name, $permanent = true)
{
if (isset(self::$register[$name])) {
// Change the register
$info = (object) self::$register[$name];
// Do nothing if it is already enabled
if (isset($info->enabled)) {
if ($info->enabled) {
Logger::logWarning("Could not enable module '".$name."'. Module is already enabled.");
return false;
}
}
// Otherwise move data from meta to the module config
$info = $info->meta;
$info->enabled = true;
self::$register[$name] = (array) $info;
Logger::log("Enabled module '".$name."'");
// Enable it permanently if so desired
if ($permanent) {
$file = $info->directory.'/moduleInfo.php';
self::setModuleValue($file, 'enabled', true);
}
// Reload the eventRegister
Events::buildEventRegister();
} else {
throw new ModuleException("Could not enable module '".$name."'. Module does not exist.", 1);
}
}
/**
* Disableds a module when it is enabled.
*
* @param string Module name
* @param bool true for permanent disable
*
* @throws FuzeWorks\ModuleException
*/
public static function disableModule($name, $permanent = true)
{
if (isset(self::$register[$name])) {
$info = (object) self::$register[$name];
// Do nothing if it is already disabled
if (isset($info->meta)) {
Logger::logWarning("Could not disable module '".$name."'. Module is already disabled.");
return false;
}
$disabled = new StdClass();
$disabled->meta = $info;
$disabled->directory = $info->directory;
$disabled->module_name = $info->module_name;
self::$register[$name] = (array) $disabled;
Logger::log("Disabled module '".$name."'");
if ($permanent) {
$file = $info->directory.'/moduleInfo.php';
self::setModuleValue($file, 'enabled', false);
}
// Reload the eventRegister
Events::buildEventRegister();
// Remove the existence of the module
unset(self::$modules[strtolower($cfg->module_name)]);
} else {
throw new ModuleException("Could not disable module '".$name."'. Module does not exist.", 1);
}
}
/**
* Create a register with all the module headers from all the existing modules.
*
* Used to correctly load all modules
* @param bool $cache true if loading from cache
* @param string $cachingMethod the driver used in the caching library
* @param int $cachingTime The time the registers are cached
*/
public static function buildRegister($cache = false, $cachingMethod = 'file', $cachingTime = 300)
{
// First check if the caching engine can be used
if ($cache)
{
// Retrieve the cache if possible
$cache = Factory::getInstance()->libraries->getDriver('cache');
$cacheData = $cache->$cachingMethod->get('moduleRegisters');
if ( ! is_bool($cacheData) )
{
// Separate the data
$moduleRegister = $cacheData['moduleRegister'];
$eventRegister = $cacheData['eventRegister'];
$routeRegister = $cacheData['routeRegister'];
$advertiseRegister = $cacheData['advertiseRegister'];
// And register it all
Logger::newLevel("Loadig Module Headers from Cache");
self::$register = $moduleRegister;
Events::$register = $eventRegister;
self::$advertiseRegister = $advertiseRegister;
self::$module_routes = $routeRegister;
foreach ($routeRegister as $route => $name) {
Factory::getInstance()->router->addRoute($route, array('callable' => array('\FuzeWorks\Modules', 'moduleCallable')), true);
}
Logger::stopLevel();
return true;
}
}
Logger::newLevel('Loading Module Headers', 'Core');
// Get all the module directories
$dir = Core::$appDir . DS . 'Modules/';
$mod_dirs = array();
$mod_dirs = array_values(array_diff(scandir($dir), array('..', '.')));
// Build the module and event register
$register = array();
$event_register = array();
// Cycle through all module directories
for ($i = 0; $i < count($mod_dirs); ++$i) {
$mod_dir = $dir.$mod_dirs[$i].'/';
// If a moduleInfo.php exists, load it
if (file_exists($mod_dir.'/moduleInfo.php')) {
// Load the configuration file
$cfg = (object) include $mod_dir.'/moduleInfo.php';
// Set enabled for now
$enabled = true;
// Define the module name
$name = '';
$name .= (!empty($cfg->author) ? strtolower($cfg->author).'/' : '');
$name .= strtolower($cfg->module_name);
// Get the module directory
$cfg->directory = $mod_dir;
// Check whether the module is disabled
if (isset($cfg->enabled)) {
if (!$cfg->enabled) {
// If disabled, set the variable
$enabled = false;
// If disabled, a holder will be placed so it might be enabled in the future
$mock = new StdClass();
$mock->module_name = $cfg->module_name;
$mock->directory = $cfg->directory;
$mock->meta = $cfg;
$mock->aliases = $cfg->aliases;
// Important, change the configuration to the mock, so we can duplicate it afterwards
$cfg = $mock;
}
}
// Copy all the data into the register and enable
$register[$name] = (array) $cfg;
// Log the name for enabled and disabled
if (!$enabled) {
Logger::newLevel("[OFF] '".$name."'");
} else {
Logger::newLevel("[ON] '".$name."'");
}
// And possibly some aliases
if (isset($cfg->aliases)) {
foreach ($cfg->aliases as $alias) {
$register[$alias] = (array) $cfg;
unset($register[$alias]['events']);
Logger::log("&nbsp;&nbsp;&nbsp;'".$alias."' (alias of '".$name."')");
}
}
// If not enabled, log it, wrap it and off to the next one
if (!$enabled) {
Logger::stopLevel();
continue;
}
// Otherwise continue and add routing paths
if (isset($cfg->routes)) {
// Get routes and add them
foreach ($cfg->routes as $route) {
// Create the route and callable and parse them
$callable = array('\FuzeWorks\Modules', 'moduleCallable');
Factory::getInstance()->router->addRoute($route, array('callable' => $callable), true);
self::$module_routes[$route] = $name;
}
}
// And for the events
if (isset($cfg->events)) {
// Get the events and add them
foreach ($cfg->events as $event) {
// First check if the event already exists, if so, append it
if (isset($event_register[$event])) {
$event_register[$event][] = $name;
} else {
$event_register[$event] = array($name);
}
// Log the event
Logger::Log('Event added: \''.$event.'\'');
}
}
// And check for an advertisement tag
if (isset($cfg->advertise)) {
// Cycle through advertisements
foreach ($cfg->advertise as $advertiseName => $advertiseData) {
// Log advertisement
Logger::log('Advertisement added: \''.$advertiseName.'\'');
// Add to advertiseRegister
self::$advertiseRegister[$advertiseName][$name] = $advertiseData;
}
}
Logger::stopLevel();
} else {
// If no details are specified, create a basic mock module
$name = $mod_dirs[$i];
// Build a default mock module config
$mock = new stdClass();
$mock->module_class = ucfirst($name);
$mock->module_file = 'class.'.strtolower($name).'.php';
$mock->module_name = $name;
$mock->dependencies = array();
$mock->versions = array();
$mock->directory = $mod_dir;
// Apply it
$register[$name] = (array) $mock;
Logger::newLevel("[ON] '".$name."'");
Logger::stopLevel();
}
}
if ($cache)
{
Logger::log("Saving registry to cache");
$cacheData = array(
'moduleRegister' => $register,
'eventRegister' => $event_register,
'routeRegister' => self::$module_routes,
'advertiseRegister' => self::$advertiseRegister
);
$cache->$cachingMethod->save('moduleRegisters', $cacheData, $cachingTime);
}
// And apply the registers to their dedicate location
self::$register = $register;
Events::$register = $event_register;
Logger::stopLevel();
}
/**
* The Module Callable.
*
* When a module listens for a specific routing path, this callable get's called.
* After this the module can handle the request with the route() function in the module's root directory
*
* @param array Regex matches
*/
public static function moduleCallable($matches = array())
{
// First detect what module is attached to this route
Logger::newLevel('Module callable called!');
// Get the route
$route = !empty($matches['route']) ? $matches['route'] : null;
// See if the route exists
if (isset(self::$module_routes[$route])) {
Logger::log("Module '".self::$module_routes[$route]."' matched given route");
// Load the module
$mod = self::get(self::$module_routes[$route]);
unset($matches['route']);
$mod->route($matches);
} else {
Logger::logError('Route did not match known module. Fatal error');
return Logger::http_error(500);
}
Logger::stopLevel();
}
}

View File

@ -395,7 +395,7 @@ class Output {
* with any server headers and profile data. It also stops benchmark
* timers so the page rendering speed and memory usage can be shown.
*
* Note: All "view" data is automatically put into $this->final_output
* Note: All "layout" data is automatically put into $this->final_output
* by controller class.
*
* @uses Output::$final_output

View File

@ -75,13 +75,13 @@ class LatteEngine implements TemplateEngine
* Handle and retrieve a template file.
*
* @param string $file Template File
* @param array $assigned_variables All the variables used in this view
* @param array $assigned_variables All the variables used in this layout
*
* @return string Output of the template
*/
public function get($file, $assigned_variables)
{
$this->latte->render($file, $assigned_variables);
return $this->latte->renderToString($file, $assigned_variables);
}
/**

View File

@ -51,7 +51,7 @@ interface TemplateEngine
* Handle and retrieve a template file.
*
* @param string $file Template File
* @param array $assigned_variables All the variables used in this view
* @param array $assigned_variables All the variables used in this layout
*
* @return string Output of the template
*/

View File

@ -356,6 +356,8 @@ class URI {
{
throw new UriException('The URI you submitted has disallowed characters.', 1);
}
return true;
}
// --------------------------------------------------------------------

View File

@ -0,0 +1,51 @@
<style class="tracy-debug">
#tracy-debug td.nette-DbConnectionPanel-sql { background: white !important }
#tracy-debug .nette-DbConnectionPanel-source { color: #BBB !important }
#tracy-debug .nette-DbConnectionPanel-explain td { white-space: pre }
#tracy-debug .fuzeworks-DbDescriptor th { background: #FDF5CE !important }
</style>
<h1 title="Database">Queries: <?php
echo $results['queryCount'], ($results['queryTimings'] ? sprintf(', time: %0.3f ms', $results['queryTimings'] * 1000) : ''); ?></h1>
<div class="tracy-inner">
<table>
<?php
foreach ($results['queries'] as $database => $queries): ?>
<tr class='fuzeworks-DbDescriptor'>
<th>Database:</th>
<th><?= htmlSpecialChars($database, ENT_QUOTES, 'UTF-8') ?></th>
<th>#</th>
</tr>
<tr><th>Time&nbsp;ms</th><th>SQL Query</th><th>Rows</th></tr>
<?php foreach ($queries as $query): ?>
<tr>
<td>
<?php if ($query['data']['error']['code'] != 0): ?>
<span title="<?= htmlSpecialChars($query['data']['error']['message'], ENT_IGNORE | ENT_QUOTES, 'UTF-8') ?>">ERROR</span>
<br /><a class="tracy-toggle tracy-collapsed" data-tracy-ref="^tr .nette-DbConnectionPanel-explain">explain</a>
<?php elseif ($query['timings'] !== 0): echo sprintf('%0.3f', $query['timings'] * 1000); endif ?>
</td>
<td class="nette-DbConnectionPanel-sql"><?= htmlSpecialChars($query['query'], ENT_QUOTES, 'UTF-8') ?>
<?php if ($query['data']['error']['code'] !== 0): ?>
<table class="tracy-collapsed nette-DbConnectionPanel-explain">
<tr>
<th>Code</th>
<th>Message</th>
</tr>
<tr>
<td><?= htmlSpecialChars($query['data']['error']['code'], ENT_NOQUOTES, 'UTF-8') ?></td>
<td><?= htmlSpecialChars($query['data']['error']['message'], ENT_NOQUOTES, 'UTF-8') ?></td>
</tr>
</table>
<?php endif ?>
</td>
<td> <?= htmlSpecialChars($query['data']['rows'], ENT_QUOTES, 'UTF-8') ?> </td>
</tr>
<?php endforeach;
endforeach; ?>
</table>
<?php if ($results['queryCountProvided'] < $results['queryCount']): ?><p>...and more</p><?php endif ?>
</div>

View File

@ -0,0 +1,19 @@
<?php
if ($results['queryCount'] && !$results['errorsFound'])
{
$color = "#6ba9e6";
}
elseif ($results['queryCount'] && $results['errorsFound'])
{
$color = "#990000";
}
else
{
$color = "#aaa";
}
?>
<span title="Database">
<svg viewBox="0 0 2048 2048"><path fill="<?= $color ?>" d="M1024 896q237 0 443-43t325-127v170q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-170q119 84 325 127t443 43zm0 768q237 0 443-43t325-127v170q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-170q119 84 325 127t443 43zm0-384q237 0 443-43t325-127v170q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-170q119 84 325 127t443 43zm0-1152q208 0 385 34.5t280 93.5 103 128v128q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-128q0-69 103-128t280-93.5 385-34.5z"/>
</svg><span class="tracy-label"><?= ($results['queryTimings'] ? sprintf('%0.1fms/', $results['queryTimings'] * 1000) : '') . $results['queryCount'] ?></span>
</span>

View File

@ -1,38 +1,11 @@
<style class="tracy-debug">
#tracy-debug .fuzeworks-LoggerPanel table {
font: 9pt/1.5 Consolas, monospace;
}
#tracy-debug .fuzeworks-LoggerPanel .error td {
background: #FF3300 !important;
}
#tracy-debug .fuzeworks-LoggerPanel .warning td {
background: #FFFF66 !important;
}
#tracy-debug .fuzeworks-LoggerPanel .debug td {
background: #33CC33 !important;
}
#tracy-debug .fuzeworks-LoggerPanel .info td {
background: #BDE678 !important;
}
#tracy-debug .fuzeworks-LoggerPanel .cinfo td {
background: #BDE622 !important;
}
#tracy-debug .fuzeworks-LoggerPanel pre, #tracy-debug .fuzeworks-LoggerPanel code {
display: inline;
background: transparent;
}
</style>
<div class="fuzeworks-LoggerPanel">
<h1> FuzeWorks - Logger</h1>
<h1> Logger</h1>
<div class="tracy-inner">
<table>

View File

@ -15,7 +15,6 @@ return array(
'subdriver'=> '',
'dbprefix' => '',
'pconnect' => FALSE,
'db_debug' => FALSE,
'cache_on' => FALSE,
'cachedir' => 'Application/Cache',
'char_set' => 'utf8',

View File

@ -38,7 +38,7 @@ use FuzeWorks\Logger;
$container = require('bootstrap.php');
// Load the test abstract
require_once 'abstract.coreTestAbstract.php';
require_once 'core/abstract.coreTestAbstract.php';
// Reset error and exception handlers
ob_start();

View File

@ -12,6 +12,7 @@ $parameters = array(
$configurator->setParameters($parameters);
$configurator->setDebugMode(true);
//$configurator->setDebugEmail('example@mail.com');
$configurator->setTimeZone('Europe/Amsterdam');
$configurator->setTempDirectory(__DIR__ . '/temp');
$configurator->setLogDirectory(__DIR__ . '/temp');

View File

@ -29,6 +29,7 @@
*
* @version Version 1.0.1
*/
use PHPUnit\Framework\TestCase;
use FuzeWorks\Events;
use FuzeWorks\Layout;
use FuzeWorks\Factory;
@ -39,7 +40,7 @@ use FuzeWorks\LoggerTracyBridge;
*
* Provides the event tests with some basic functionality
*/
abstract class CoreTestAbstract extends PHPUnit_Framework_TestCase
abstract class CoreTestAbstract extends TestCase
{
/**
* Remove all listeners before the next test starts.
@ -55,7 +56,7 @@ abstract class CoreTestAbstract extends PHPUnit_Framework_TestCase
LoggerTracyBridge::register();
// Reset the layout manager
Layout::reset();
Factory::getInstance()->layout->reset();
// Re-enable events, in case they have been disabled
Events::enable();

View File

@ -0,0 +1,77 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2017 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://techfuze.net/fuzeworks
* @since Version 1.0.4
*
* @version Version 1.0.4
*/
use FuzeWorks\EventPriority;
/**
* Class EventPriorityTest.
*
* This test will test the EventPriority class
*/
class eventPriorityTest extends CoreTestAbstract
{
public function testPriorities()
{
$this->assertEquals(EventPriority::LOWEST, 5);
$this->assertEquals(EventPriority::LOW, 4);
$this->assertEquals(EventPriority::NORMAL, 3);
$this->assertEquals(EventPriority::HIGH, 2);
$this->assertEquals(EventPriority::HIGHEST, 1);
$this->assertEquals(EventPriority::MONITOR, 0);
}
public function testGetPriority()
{
$this->assertEquals(EventPriority::getPriority(5), 'EventPriority::LOWEST');
$this->assertEquals(EventPriority::getPriority(4), 'EventPriority::LOW');
$this->assertEquals(EventPriority::getPriority(3), 'EventPriority::NORMAL');
$this->assertEquals(EventPriority::getPriority(2), 'EventPriority::HIGH');
$this->assertEquals(EventPriority::getPriority(1), 'EventPriority::HIGHEST');
$this->assertEquals(EventPriority::getPriority(0), 'EventPriority::MONITOR');
}
public function testGetInvalidPriority()
{
$this->assertFalse(EventPriority::getPriority(99));
}
public function testHighestPriority()
{
$this->assertEquals(EventPriority::getHighestPriority(), EventPriority::MONITOR);
}
public function testLowestPriority()
{
$this->assertEquals(EventPriority::getLowestPriority(), EventPriority::LOWEST);
}
}

View File

@ -0,0 +1,80 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2017 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://techfuze.net/fuzeworks
* @since Version 1.0.4
*
* @version Version 1.0.4
*/
use FuzeWorks\Events;
use FuzeWorks\Event;
use FuzeWorks\EventPriority;
/**
* Class EventTest.
*
* This test will test the Event class
*/
class eventTest extends CoreTestAbstract
{
public function testFireEvent()
{
$event = Events::fireEvent('testEvent');
$this->assertInstanceOf('FuzeWorks\Event', $event);
}
public function testCancelEvent()
{
Events::addListener(array($this, 'listener_cancel'), 'testCancelEvent', EventPriority::NORMAL);
$event = Events::fireEvent('testCancelEvent');
$this->assertTrue($event->isCancelled());
}
public function testUncancelEvent()
{
Events::addListener(array($this, 'listener_cancel'), 'testUncancelEvent', EventPriority::HIGH);
Events::addListener(array($this, 'listener_uncancel'), 'testUncancelEvent', EventPriority::LOW);
$event = Events::fireEvent('testUncancelEvent');
$this->assertFalse($event->isCancelled());
}
public function listener_cancel($event)
{
$event->setCancelled(true);
return $event;
}
public function listener_uncancel($event)
{
$this->assertTrue($event->isCancelled());
$event->setCancelled(false);
return $event;
}
}

View File

@ -27,9 +27,10 @@
* @link http://techfuze.net/fuzeworks
* @since Version 0.0.1
*
* @version Version 1.0.0
* @version Version 1.0.4
*/
use FuzeWorks\Router;
use FuzeWorks\Event;
use FuzeWorks\Events;
use FuzeWorks\EventPriority;
@ -42,7 +43,7 @@ class eventsTest extends CoreTestAbstract
{
public function testFireEvent()
{
$mock = $this->getMock('MockEventListener', array('mockMethod'));
$mock = $this->getMockBuilder(Observer::class)->setMethods(['mockMethod'])->getMock();
$mock->expects($this->once())->method('mockMethod');
Events::addListener(array($mock, 'mockMethod'), 'mockEvent', EventPriority::NORMAL);
@ -54,9 +55,9 @@ class eventsTest extends CoreTestAbstract
*/
public function testObjectEvent()
{
$event = $this->getMock('MockEvent');
$event = $this->getMockBuilder(MockEvent::class)->getMock();
$listener = $this->getMock('MockEventListener', array('mockListener'));
$listener = $this->getMockBuilder(Observer::class)->setMethods(['mockListener'])->getMock();
$listener->expects($this->once())->method('mockListener')->with($this->equalTo($event));
Events::addListener(array($listener, 'mockListener'), get_class($event), EventPriority::NORMAL);
@ -68,7 +69,7 @@ class eventsTest extends CoreTestAbstract
*/
public function testVariablePassing()
{
$event = $this->getMock('MockEvent');
$event = $this->getMockBuilder(MockEvent::class)->getMock();
$event->key = 'value';
$eventName = get_class($event);
@ -87,7 +88,7 @@ class eventsTest extends CoreTestAbstract
public function testVariableChanging()
{
// First prepare the event
$event = $this->getMock('MockEvent');
$event = $this->getMockBuilder(MockEvent::class)->getMock();
$event->key = 1;
$eventName = get_class($event);
@ -115,11 +116,29 @@ class eventsTest extends CoreTestAbstract
/**
* @depends testFireEvent
* @expectedException FuzeWorks\Exception\EventException
*/
public function testRemoveListener()
public function testInvalidTypeEvent()
{
Events::fireEvent(array('x', 'y', 'z'));
}
/**
* @depends testFireEvent
* @expectedException FuzeWorks\Exception\EventException
*/
public function testInvalidClassEvent()
{
Events::fireEvent('nonExistingEvent', 'x', 'y', 'z');
}
/**
* @depends testFireEvent
*/
public function testAddAndRemoveListener()
{
// First add the listener, expect it to be never called
$listener = $this->getMock('MockEventListener', array('mockListener'));
$listener = $this->getMockBuilder(Observer::class)->setMethods(['mockListener'])->getMock();
$listener->expects($this->never())->method('mockListener');
Events::addListener(array($listener, 'mockListener'), 'mockEvent', EventPriority::NORMAL);
@ -130,10 +149,63 @@ class eventsTest extends CoreTestAbstract
Events::fireEvent('mockEvent');
}
/**
* @depends testAddAndRemoveListener
* @expectedException FuzeWorks\Exception\EventException
*/
public function testAddInvalidPriorityListener()
{
Events::addListener('fakeCallable', 'mockEvent', 99);
}
/**
* @depends testAddAndRemoveListener
* @expectedException FuzeWorks\Exception\EventException
*/
public function testAddInvalidCallableListener()
{
Events::addListener(array('nonExistingClass', 'nonExistingMethod'), 'mockEvent', EventPriority::NORMAL);
}
/**
* @depends testAddAndRemoveListener
* @expectedException FuzeWorks\Exception\EventException
*/
public function testAddInvalidNameListener()
{
Events::addListener(function($e) {}, '', EventPriority::NORMAL);
}
/**
* @depends testAddAndRemoveListener
* @expectedException FuzeWorks\Exception\EventException
*/
public function testRemoveInvalidPriorityListener()
{
Events::removeListener('fakeCallable', 'mockEvent', 99);
}
/**
* @depends testAddAndRemoveListener
*/
public function testRemoveUnsetEventListener()
{
$this->assertNull(Events::removeListener('fakeCallable', 'emptyListenerArray', EventPriority::NORMAL));
}
/**
* @depends testAddAndRemoveListener
*/
public function testRemoveUnsetListener()
{
Events::addListener(function($e) {}, 'mockEvent', EventPriority::NORMAL);
$this->assertNull(Events::removeListener(function($x) {echo "Called"; }, 'mockEvent', EventPriority::NORMAL));
}
public function testDisable()
{
// First add the listener, expect it to be never called
$listener = $this->getMock('MockEventListener', array('mockListener'));
$listener = $this->getMockBuilder(Observer::class)->setMethods(['mockListener'])->getMock();
$listener->expects($this->never())->method('mockListener');
Events::addListener(array($listener, 'mockListener'), 'mockEvent', EventPriority::NORMAL);
@ -147,7 +219,7 @@ class eventsTest extends CoreTestAbstract
public function testReEnable()
{
// First add the listener, expect it to be never called
$listener = $this->getMock('MockEventListener', array('mockListener'));
$listener = $this->getMockBuilder(Observer::class)->setMethods(['mockListener'])->getMock();
$listener->expects($this->once())->method('mockListener');
Events::addListener(array($listener, 'mockListener'), 'mockEvent', EventPriority::NORMAL);
@ -164,3 +236,14 @@ class eventsTest extends CoreTestAbstract
Events::fireEvent('mockEvent');
}
}
class Observer
{
public function mockMethod() {}
public function mockListener($event) {}
}
class MockEvent extends Event
{
}

View File

@ -43,7 +43,6 @@ use FuzeWorks\Exception\LayoutException;
use FuzeWorks\Exception\LibraryException;
use FuzeWorks\Exception\LoggerException;
use FuzeWorks\Exception\ModelException;
use FuzeWorks\Exception\ModuleException;
use FuzeWorks\Exception\RouterException;
use FuzeWorks\Exception\SecurityException;
use FuzeWorks\Exception\UriException;
@ -160,14 +159,6 @@ class exceptionTestTest extends CoreTestAbstract
throw new ModelException("Exception Test Run", 1);
}
/**
* @expectedException FuzeWorks\Exception\ModuleException
*/
public function testModuleException()
{
throw new ModuleException("Exception Test Run", 1);
}
/**
* @expectedException FuzeWorks\Exception\RouterException
*/

View File

@ -70,7 +70,7 @@ class factoryTest extends CoreTestAbstract
public function testObjectsSameInstance()
{
// Create mock
$mock = $this->getMock('MockInstance');
$mock = $this->getMockBuilder(MockFactory::class)->setMethods(['mockListener'])->getMock();
// Test not set
$this->assertNull(Factory::getInstance()->mock);
@ -96,7 +96,7 @@ class factoryTest extends CoreTestAbstract
public function testObjectsDifferentInstance()
{
// Create mock
$mock = $this->getMock('MockInstance');
$mock = $this->getMockBuilder(MockFactory::class)->getMock();
// Test not set
$this->assertNull(Factory::getInstance()->mock);
@ -175,3 +175,7 @@ class factoryTest extends CoreTestAbstract
}
}
class MockFactory {
}

View File

@ -178,6 +178,7 @@ class inputTest extends CoreTestAbstract
$this->assertEquals("Hello, i try to <script>alert('Hack');</script> your site", $harm);
$this->assertEquals("Hello, i try to [removed]alert&#40;'Hack'&#41;;[removed] your site", $harmless);
unset($_POST['foo']);
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST['foo']['bar'] = 'baz';
$barArray = array('bar' => 'baz');

View File

@ -39,12 +39,21 @@ use FuzeWorks\Factory;
*/
class layoutTest extends CoreTestAbstract
{
protected $factory;
public function setUp()
{
// Load the factory first
$this->factory = Factory::getInstance();
}
public function testGetFileExtensions()
{
// Test getting php files
$this->assertEquals('php', Layout::getExtensionFromFile('class.test.php'));
$this->assertEquals('php', Layout::getExtensionFromFile('class.test.org.php'));
$this->assertEquals('random', Layout::getExtensionFromFile('class.test.something.random'));
$this->assertEquals('php', $this->factory->layout->getExtensionFromFile('class.test.php'));
$this->assertEquals('php', $this->factory->layout->getExtensionFromFile('class.test.org.php'));
$this->assertEquals('random', $this->factory->layout->getExtensionFromFile('class.test.something.random'));
}
/**
@ -56,19 +65,19 @@ class layoutTest extends CoreTestAbstract
$extensions = array('php', 'json');
// Basic path
Layout::setFileFromString('test', 'tests/layout/testGetFilePath/', $extensions);
$this->assertEquals('tests/layout/testGetFilePath/view.test.php', Layout::getFile());
$this->assertEquals('tests/layout/testGetFilePath/', Layout::getDirectory());
$this->factory->layout->setFileFromString('test', 'tests/layout/testGetFilePath/', $extensions);
$this->assertEquals('tests/layout/testGetFilePath/layout.test.php', $this->factory->layout->getFile());
$this->assertEquals('tests/layout/testGetFilePath/', $this->factory->layout->getDirectory());
// Alternate file extension
Layout::setFileFromString('JSON', 'tests/layout/testGetFilePath/', $extensions);
$this->assertEquals('tests/layout/testGetFilePath/view.JSON.json', Layout::getFile());
$this->assertEquals('tests/layout/testGetFilePath/', Layout::getDirectory());
$this->factory->layout->setFileFromString('JSON', 'tests/layout/testGetFilePath/', $extensions);
$this->assertEquals('tests/layout/testGetFilePath/layout.JSON.json', $this->factory->layout->getFile());
$this->assertEquals('tests/layout/testGetFilePath/', $this->factory->layout->getDirectory());
// Complex deeper path
Layout::setFileFromString('Deeper/test', 'tests/layout/testGetFilePath/', $extensions);
$this->assertEquals('tests/layout/testGetFilePath/Deeper/view.test.php', Layout::getFile());
$this->assertEquals('tests/layout/testGetFilePath/', Layout::getDirectory());
$this->factory->layout->setFileFromString('Deeper/test', 'tests/layout/testGetFilePath/', $extensions);
$this->assertEquals('tests/layout/testGetFilePath/Deeper/layout.test.php', $this->factory->layout->getFile());
$this->assertEquals('tests/layout/testGetFilePath/', $this->factory->layout->getDirectory());
}
/**
@ -80,7 +89,7 @@ class layoutTest extends CoreTestAbstract
// Extensions to be used in this test
$extensions = array('php', 'json');
Layout::setFileFromString('test?\/<>', 'test|?/*<>', $extensions);
$this->factory->layout->setFileFromString('test?\/<>', 'test|?/*<>', $extensions);
}
/**
@ -89,7 +98,7 @@ class layoutTest extends CoreTestAbstract
public function testMissingDirectory()
{
// Directory that does not exist
Layout::setFileFromString('test', 'tests/layout/doesNotExist/', array('php'));
$this->factory->layout->setFileFromString('test', 'tests/layout/doesNotExist/', array('php'));
}
/**
@ -97,7 +106,7 @@ class layoutTest extends CoreTestAbstract
*/
public function testMissingFile()
{
Layout::setFileFromString('test', 'tests/layout/testMissingFile/', array('php'));
$this->factory->layout->setFileFromString('test', 'tests/layout/testMissingFile/', array('php'));
}
/**
@ -105,7 +114,7 @@ class layoutTest extends CoreTestAbstract
*/
public function testUnknownFileExtension()
{
Layout::setFileFromString('test', 'tests/layout/testUnknownFileExtension/', array('php'));
$this->factory->layout->setFileFromString('test', 'tests/layout/testUnknownFileExtension/', array('php'));
}
public function testLayoutGet()
@ -113,16 +122,16 @@ class layoutTest extends CoreTestAbstract
// Directory of these tests
$directory = 'tests/layout/testLayoutGet/';
$this->assertEquals('Retrieved Data', Layout::get('test', $directory));
$this->assertEquals('Retrieved Data', $this->factory->layout->get('test', $directory));
}
public function testLayoutView()
public function testLayoutDisplay()
{
// Directory of these tests
$directory = 'tests/layout/testLayoutGet/';
ob_start();
Layout::view('test', $directory);
$this->factory->layout->display('test', $directory);
Factory::getInstance()->output->_display();
$output = ob_get_contents();
ob_end_clean();
@ -133,29 +142,29 @@ class layoutTest extends CoreTestAbstract
public function testReset()
{
// First the the variables
Layout::setTitle('Test Title');
Layout::setDirectory('tests/layout/testLayoutGet');
$this->factory->layout->setTitle('Test Title');
$this->factory->layout->setDirectory('tests/layout/testLayoutGet');
// Test if they are actually set
$this->assertEquals('Test Title', Layout::getTitle());
$this->assertEquals('tests/layout/testLayoutGet', Layout::getDirectory());
$this->assertEquals('Test Title', $this->factory->layout->getTitle());
$this->assertEquals('tests/layout/testLayoutGet', $this->factory->layout->getDirectory());
// Reset the layout system
Layout::reset();
$this->factory->layout->reset();
// Test for default values
$this->assertFalse(Layout::getTitle());
$this->assertTrue(strpos(Layout::getDirectory(), 'application/Views') !== false);
$this->assertFalse($this->factory->layout->getTitle());
$this->assertTrue(strpos($this->factory->layout->getDirectory(), 'application/Layout') !== false);
}
public function testGetEngineFromExtension()
{
Layout::loadTemplateEngines();
$this->factory->layout->loadTemplateEngines();
// Test all the default engines
$this->assertInstanceOf('FuzeWorks\TemplateEngine\PHPEngine', Layout::getEngineFromExtension('php'));
$this->assertInstanceOf('FuzeWorks\TemplateEngine\JsonEngine', Layout::getEngineFromExtension('json'));
$this->assertInstanceOf('FuzeWorks\TemplateEngine\SmartyEngine', Layout::getEngineFromExtension('tpl'));
$this->assertInstanceOf('FuzeWorks\TemplateEngine\PHPEngine', $this->factory->layout->getEngineFromExtension('php'));
$this->assertInstanceOf('FuzeWorks\TemplateEngine\JsonEngine', $this->factory->layout->getEngineFromExtension('json'));
$this->assertInstanceOf('FuzeWorks\TemplateEngine\SmartyEngine', $this->factory->layout->getEngineFromExtension('tpl'));
}
/**
@ -164,7 +173,7 @@ class layoutTest extends CoreTestAbstract
*/
public function testGetEngineFromExtensionFail()
{
Layout::getEngineFromExtension('faulty');
$this->factory->layout->getEngineFromExtension('faulty');
}
/**
@ -179,13 +188,13 @@ class layoutTest extends CoreTestAbstract
$mock->method('get')->willReturn('output');
// And listen for usage
$mock->expects($this->once())->method('get')->with('tests/layout/testCustomEngine/view.test.test');
$mock->expects($this->once())->method('get')->with('tests/layout/testCustomEngine/layout.test.test');
// Register the engine
Layout::registerEngine($mock, 'Custom', array('test'));
$this->factory->layout->registerEngine($mock, 'Custom', array('test'));
// And run the engine
$this->assertEquals('output', Layout::get('test', 'tests/layout/testCustomEngine/'));
$this->assertEquals('output', $this->factory->layout->get('test', 'tests/layout/testCustomEngine/'));
}
/**
@ -194,27 +203,27 @@ class layoutTest extends CoreTestAbstract
*/
public function testInvalidCustomEngine()
{
$mock = $this->getMock('MockEngine');
$mock = $this->getMockBuilder(MockEngine::class)->getMock();
// Does not implement FuzeWorks\TemplateEngine\TemplateEngine, this should fail
Layout::registerEngine($mock, 'Custom', array('test'));
$this->factory->layout->registerEngine($mock, 'Custom', array('test'));
}
public function testEnginesLoadView()
public function testEnginesLoadLayout()
{
// Directory of these tests
$directory = 'tests/layout/testEngines/';
// First the PHP Engine
$this->assertEquals('PHP Template Check', Layout::get('php', $directory));
Layout::reset();
$this->assertEquals('PHP Template Check', $this->factory->layout->get('php', $directory));
$this->factory->layout->reset();
// Then the JSON Engine
$this->assertEquals('JSON Template Check', json_decode(Layout::get('json', $directory), true)[0]);
Layout::reset();
$this->assertEquals('JSON Template Check', json_decode($this->factory->layout->get('json', $directory), true)[0]);
$this->factory->layout->reset();
// And the Smarty Engine
$this->assertEquals('Smarty Template Check', Layout::get('smarty', $directory));
$this->assertEquals('Smarty Template Check', $this->factory->layout->get('smarty', $directory));
}
public function testEngineVariables()
@ -223,17 +232,21 @@ class layoutTest extends CoreTestAbstract
$directory = 'tests/layout/testEngineVariables/';
// First the PHP Engine
Layout::assign('key', 'value');
$this->assertEquals('value', Layout::get('php', $directory));
Layout::reset();
$this->factory->layout->assign('key', 'value');
$this->assertEquals('value', $this->factory->layout->get('php', $directory));
$this->factory->layout->reset();
// Then the JSON Engine
Layout::assign('key', 'value');
$this->assertEquals('value', json_decode(Layout::get('json', $directory), true)['data']['key']);
Layout::reset();
$this->factory->layout->assign('key', 'value');
$this->assertEquals('value', json_decode($this->factory->layout->get('json', $directory), true)['data']['key']);
$this->factory->layout->reset();
// And the Smarty Engine
Layout::assign('key', 'value');
$this->assertEquals('value', Layout::get('smarty', $directory));
$this->factory->layout->assign('key', 'value');
$this->assertEquals('value', $this->factory->layout->get('smarty', $directory));
}
}
class MockEngine {
}

View File

@ -137,7 +137,7 @@ class securityTest extends CoreTestAbstract
$xss_clean_return = $this->security->xss_clean($harm_string, TRUE);
// $this->assertTrue($xss_clean_return);
$this->assertTrue($xss_clean_return);
}
// --------------------------------------------------------------------

View File

@ -51,7 +51,7 @@ class uriTest extends CoreTestAbstract {
$this->uri->_set_permitted_uri_chars('a-z 0-9~%.:_\-');
$str = 'abc01239~%.:_-';
$this->uri->filter_uri($str);
$this->assertTrue($this->uri->filter_uri($str));
}
// --------------------------------------------------------------------

View File

@ -0,0 +1,59 @@
<?php
/**
* FuzeWorks.
*
* The FuzeWorks MVC PHP FrameWork
*
* Copyright (C) 2017 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 - 2017, 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://techfuze.net/fuzeworks
* @since Version 1.0.4
*
* @version Version 1.0.4
*/
use FuzeWorks\Factory;
use FuzeWorks\Exception\DatabaseException;
/**
* Class databaseTest.
*
* Core testing suite. Will test databases, querybuilders and frequently used drivers.
*/
class databaseTest extends CoreTestAbstract
{
protected $factory;
public function setUp()
{
$this->factory = Factory::getInstance();
}
/**
* @expectedException FuzeWorks\Exception\DatabaseException
*/
public function testInvalidDb()
{
$this->factory->database->get('unknown://unknown:password@unknown/database');
}
}

View File

@ -43,10 +43,14 @@ class coreStartEventTest extends CoreTestAbstract
*/
public function testCoreStartEvent()
{
$mock = $this->getMock('MockEvent', array('mockMethod'));
$mock = $this->getMockBuilder(MockStartEvent::class)->setMethods(['mockMethod'])->getMock();
$mock->expects($this->once())->method('mockMethod');
Events::addListener(array($mock, 'mockMethod'), 'coreStartEvent', EventPriority::NORMAL);
Core::init();
}
}
class MockStartEvent {
public function mockMethod() {}
}

View File

@ -30,26 +30,35 @@
* @version Version 1.0.0
*/
use FuzeWorks\Events;
use FuzeWorks\Layout;
use FuzeWorks\Factory;
use FuzeWorks\EventPriority;
/**
* Class LayoutLoadViewEventTest.
* Class LayoutLoadEventTest.
*/
class layoutLoadViewEventTest extends CoreTestAbstract
class layoutLoadEventTest extends CoreTestAbstract
{
protected $factory;
public function setUp()
{
// Load the factory first
$this->factory = Factory::getInstance();
}
/**
* Check if the event is fired when it should be.
*/
public function test_basic()
{
$mock = $this->getMock('MockEvent', array('mockMethod'));
$mock = $this->getMockBuilder(MockLayoutEventTest::class)->setMethods(['mockMethod'])->getMock();
$mock->expects($this->once())->method('mockMethod');
Events::addListener(array($mock, 'mockMethod'), 'layoutLoadViewEvent', EventPriority::NORMAL);
Events::addListener(array($mock, 'mockMethod'), 'layoutLoadEvent', EventPriority::NORMAL);
// And run the test
Layout::get('home');
$this->factory->layout->get('home');
}
/**
@ -59,8 +68,8 @@ class layoutLoadViewEventTest extends CoreTestAbstract
*/
public function test_change()
{
Events::addListener(array($this, 'listener_change'), 'layoutLoadViewEvent', EventPriority::NORMAL);
Layout::get('home');
Events::addListener(array($this, 'listener_change'), 'layoutLoadEvent', EventPriority::NORMAL);
$this->factory->layout->get('home');
}
// Change title from new to other
@ -68,11 +77,11 @@ class layoutLoadViewEventTest extends CoreTestAbstract
{
// This controller should not exist
$this->assertTrue(strpos($event->file, 'application/Views/view.home.php') !== false);
$this->assertTrue(strpos($event->directory, 'application/Views/') !== false);
$this->assertTrue(strpos($event->file, 'application/Layout/layout.home.php') !== false);
$this->assertTrue(strpos($event->directory, 'application/Layout/') !== false);
// It should exist now
$event->file = $event->directory . 'view.test.not_found';
$event->file = $event->directory . 'layout.test.not_found';
return $event;
}
@ -84,8 +93,8 @@ class layoutLoadViewEventTest extends CoreTestAbstract
{
// Listen for the event and cancel it
Events::addListener(array($this, 'listener_cancel'), 'layoutLoadViewEvent', EventPriority::NORMAL);
$this->assertFalse(Layout::get('home'));
Events::addListener(array($this, 'listener_cancel'), 'layoutLoadEvent', EventPriority::NORMAL);
$this->assertFalse($this->factory->layout->get('home'));
}
// Cancel all calls
@ -94,3 +103,7 @@ class layoutLoadViewEventTest extends CoreTestAbstract
$event->setCancelled(true);
}
}
class MockLayoutEventTest {
public function MockMethod() {}
}