Initial commit

This commit is contained in:
Joey Kimsey
2024-08-04 21:15:59 -04:00
parent c9d1fb983f
commit 0d469501ee
695 changed files with 70184 additions and 71 deletions

367
vendor/bedrock/classes/config.php vendored Normal file
View File

@ -0,0 +1,367 @@
<?php
/**
* classes/config.php
*
* This class handles all the hard-coded configurations.
*
* @version 3.0
* @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com/Core
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/
namespace TheTempusProject\Bedrock\Classes;
use TheTempusProject\Canary\Canary as Debug;
use TheTempusProject\Bedrock\Functions\Check;
use TheTempusProject\Bedrock\Functions\Input;
class Config {
public static $config = false;
private static $location = false;
private static $initialized = false;
/**
* Default constructor which will attempt to load the config from the location specified.
*
* @param {string} [$location]
* @return {null|object}
*/
public function __construct( $location = '' ) {
if ( self::$initialized !== false ) {
Debug::log( 'Config already initialized.' );
return $this;
}
if ( empty( $location ) ) {
$location = CONFIG_JSON;
}
self::$initialized = $this->load( $location );
if ( self::$initialized !== false ) {
Debug::log( 'Config initialization succeeded.' );
return $this;
}
Debug::warn( 'Config initialization failed.' );
}
/**
* Attempts to retrieve then set the configuration from a file.
* @note This function will reset the config every time it is used.
*
* @param {string} $location
* @return {bool}
*/
public function load( $location ) {
self::$config = $this->getConfigFile( $location );
self::$location = $location;
if ( self::$config === false || empty( self::$config ) ) {
Debug::warn( 'Config load failed.' );
return false;
}
Debug::log( 'Config load succeeded.' );
return true;
}
/**
* Opens and decodes the config json from the location provided.
*
* @param {string} [$location]
* @return {bool|array}
*/
public function getConfigFile( $location ) {
if ( file_exists( $location ) ) {
Debug::debug( "Config json found: $location" );
return json_decode( file_get_contents( $location ), true );
} else {
Debug::warn( "Config json not found: $location" );
return false;
}
}
/**
* Add a new config option for the specified category.
*
* NOTE: Use a default option when using this function to
* aid in fail safe execution.
*
* @param {string} [$category] - The primary category to add the option to.
* @param {string} [$node] - The name of the new option.
* @param {wild} [$value] - The desired value for the new option.
* @param {bool} [$createMissing] - Whether or not to create missing options.
* @param {bool} [$save] - Whether or not to save the config.
* @param {bool} [$saveDefault] - Whether or not to save the default config.
* @return {bool}
*/
public function update( $category, $node, $value, $createMissing = false, $save = false, $saveDefault = false ) {
// @todo: createMissing is unused here
if ( self::$config === false ) {
Debug::warn( 'Config not loaded.' );
return false;
}
if ( !Check::simpleName( $category ) ) {
Debug::warn( "Category name invalid: $categoryName" );
return false;
}
if ( !isset( self::$config[$category] ) ) {
Debug::warn( "No such category: $category" );
return false;
}
if ( !Check::simpleName( $node ) ) {
Debug::warn( "Node name invalid: $categoryName" );
return false;
}
if ( !isset( self::$config[$category][$node] ) ) {
Debug::warn( 'Config not found.' );
return false;
}
if ( $value === 'true' ) {
$value = true;
}
if ( $value === 'false' ) {
$value = false;
}
self::$config[$category][$node]['value'] = $value;
if ( $save ) {
$this->save( $saveDefault );
}
return true;
}
public function updateFromForm( $save = false, $saveDefault = false ) {
if ( self::$config === false ) {
Debug::warn( 'Config not loaded.' );
return;
}
foreach ( self::$config as $category => $fields ) {
if ( empty( self::$config[ $category ] ) ) {
Debug::warn( "Config category not found: $category" );
continue;
}
foreach ( self::$config[ $category ] as $field => $node ) {
$name = $category . '/' . $field;
if ( empty( $node ) ) {
continue;
}
if ( !empty( $node['protected'] ) ) {
continue;
}
$fieldname = str_ireplace( '/', '-', $name );
if ( Input::exists( $fieldname ) ) {
$this->update( $category, $field, Input::post( $fieldname ) );
}
}
}
if ( $save ) {
return $this->save( $saveDefault );
}
return true;
}
/**
* Saves the current config.
*
* @param {bool} [$default] - Whether or not to save a default copy.
* @return {bool}
*/
public function save( $default = false ) {
if ( self::$config === false ) {
Debug::warn( 'Config not loaded.' );
return false;
}
if ( self::$location === false ) {
Debug::warn( 'Config location not set.' );
return false;
}
if ( $default ) {
$locationArray = explode( '.', self::$location );
$locationArray[] = 'bak';
$backupLoction = implode( '.', $locationArray );
if ( !file_put_contents( $backupLoction, json_encode( self::$config ) ) ) {
return false;
}
}
if ( file_put_contents( self::$location, json_encode( self::$config ) ) ) {
return true;
}
return false;
}
/**
* Adds a new category to the $config array.
*
* @param {string} [$categoryName]
* @return {bool}
*/
public function addCategory( $categoryName ) {
if ( self::$config === false ) {
self::$config = [];
}
if ( !Check::simpleName( $categoryName ) ) {
Debug::warn( "Category name invalid: $categoryName" );
return false;
}
if ( isset( self::$config[$categoryName] ) ) {
Debug::warn( "Category already exists: $categoryName" );
return false;
}
self::$config[$categoryName] = [];
return true;
}
/**
* Removes an existing category from the $config array.
*
* @param {string} [$categoryName]
* @param {string} [$save]
* @return {bool}
*/
public function removeCategory( $categoryName, $save = false, $saveDefault = true ) {
if ( self::$config === false ) {
Debug::warn( 'Config not loaded.' );
return;
}
if ( !isset( self::$config[$categoryName] ) ) {
Debug::warn( "Config does not have category: $categoryName" );
return true;
}
unset( self::$config[$categoryName] );
if ( $save ) {
$this->save( $saveDefault );
}
return true;
}
/**
* Add a new config node for the specified category.
*
* @param {string} [$category] - The primary category to add the option to.
* @param {string} [$node] - The name of the new option.
* @param {wild} [$value] - The desired value for the new option.
* @return {bool}
*/
public function add( $category, $node, $details, $updateExisting = false ) {
if ( self::$config === false ) {
Debug::warn( 'Config not loaded.' );
return false;
}
if ( !Check::simpleName( $category ) ) {
Debug::warn( "Category name invalid: $category" );
return false;
}
if ( !isset( self::$config[$category] ) ) {
Debug::warn( "No such category: $category" );
return false;
}
if ( !Check::simpleName( $node ) ) {
Debug::warn( "Category Node name invalid: $node" );
return false;
}
if ( isset( self::$config[$category][$node] ) ) {
if ( $updateExisting ) {
$details = array_replace(self::$config[$category][$node], $details );
} else {
Debug::warn( "Config already exists: $node" );
return false;
}
}
if ( !isset( $details['value'] ) ) {
$details['value'] = $details['default'];
}
self::$config[$category][$node] = $details;
return true;
}
public function generate( $location, $mods = [] ) {
self::$location = $location;
if ( !empty( $mods ) ) {
foreach ( $mods as $category => $node ) {
$this->addCategory( $category );
foreach ( $node as $name => $details ) {
$this->add( $category, $name, $details, true );
}
}
}
if ( $this->save( true ) ) {
Debug::info( 'config file generated successfully.' );
return true;
}
return false;
}
/**
* Retrieves the config option for $name.
*
* @param {string} [$name] - Must be in <category>/<option> format.
* @return {WILD}
*/
public static function get( $name ) {
$data = explode( '/', $name );
if ( count( $data ) != 2 ) {
Debug::warn( "Config not properly formatted: $name" );
return;
}
if ( self::$config === false ) {
Debug::warn( 'Config not loaded.' );
return;
}
$category = $data[0];
$field = $data[1];
if ( !isset( self::$config[$category][$field] ) ) {
Debug::warn( "Config not found: $name" );
return;
}
$node = self::$config[$category][$field];
if ( !isset( $node['type'] ) ) {
$node['type'] = 'text';
}
if ( !isset( $node['pretty'] ) ) {
$node['pretty'] = $node;
}
if ( !isset( $node['default'] ) ) {
$node['default'] = '';
}
if ( !isset( $node['value'] ) ) {
$node['value'] = $node['default'];
}
if ( !isset( $node['protected'] ) ) {
$node['protected'] = false;
}
return $node;
}
/**
* Retrieves the config option for $name and if the result is bool, converts it to a string.
*
* @param {string} [$name] - Must be in <category>/<option> format.
* @return {WILD}
*/
public static function getString( $name ) {
$result = self::getValue( $name );
if ( is_bool( $result ) ) {
$result = ( $result ? 'true' : 'false' );
}
return $result;
}
public static function getValue( $name ) {
$node = self::get( $name );
if ( empty( $node ) ) {
return;
}
if ( !isset( $node['value'] ) ) {
Debug::warn( 'Node Value not set.' );
return;
}
return $node['value'];
}
public static function getDefault( $name ) {
$node = self::get( $name );
if ( empty( $node ) ) {
return;
}
if ( !isset( $node['default'] ) ) {
Debug::warn( 'Node default not set.' );
return;
}
return $node['default'];
}
}

56
vendor/bedrock/classes/controller.php vendored Normal file
View File

@ -0,0 +1,56 @@
<?php
/**
* core/controller.php
*
* The controller handles our main template and provides the
* model and view functions which are the backbone of the tempus
* project. Used to hold and keep track of many of the variables
* that support the applications execution.
*
* @version 3.0
* @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com/Core
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/
namespace TheTempusProject\Bedrock\Classes;
use TheTempusProject\Canary\Canary as Debug;
use TheTempusProject\Bedrock\Functions\Session;
use TheTempusProject\Houdini\Classes\Issues;
class Controller {
public static $title = null;
public static $pageDescription = null;
public static $template = null;
/**
* Check for issues stored in sessions and add them to current issues.
*/
public static function checkSessions() {
$success = Session::checkFlash( 'success' );
$notice = Session::checkFlash( 'notice' );
$error = Session::checkFlash( 'error' );
$info = Session::checkFlash( 'info' );
if ( !empty( $success ) ) {
Issues::add( 'success', $success );
}
if ( !empty( $notice ) ) {
Issues::add( 'notice', $notice );
}
if ( !empty( $error ) ) {
Issues::add( 'error', $error );
}
if ( !empty( $info ) ) {
Issues::add( 'info', $info );
}
}
public function __construct() {
Debug::log( 'Controller Constructing: ' . get_class( $this ) );
self::checkSessions();
}
public function __destruct() {
Debug::log( 'Controller Destructing: ' . get_class( $this ) );
}
}

View File

@ -0,0 +1,78 @@
<?php
/**
* classes/custom_exception.php
*
* This class is used exclusively when throwing predefined exceptions.
* It will intercept framework thrown exceptions and deal with them however
* you choose; in most cases by logging them and taking appropriate responses
* such as redirecting to error pages.
*
* @version 3.0
* @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com/Core
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/
namespace TheTempusProject\Bedrock\Classes;
use Exception;
use TheTempusProject\Hermes\Functions\Redirect;
use TheTempusProject\Canary\Canary as Debug;
class CustomException extends Exception {
private $originFunction = null;
private $exceptionName = null;
private $originClass = null;
private $data = null;
/**
* This function allows the application to deal with errors
* in a dynamic way by letting you customize the response
*
* @param string $type - The type of the exception being called/thrown.
* @param string $data - Any additional data being passed with the exception.
*
* @example - throw new CustomException('model'); - Calls the model-missing exception
*/
public function __construct( $type, $data = null ) {
$this->originFunction = debug_backtrace()[1]['function'];
$this->originClass = debug_backtrace()[1]['class'];
$this->exceptionName = $type;
$this->data = $data;
switch ( $type ) {
case 'model':
Debug::error( 'Model not found: ' . $data );
break;
case 'dbConnection':
Debug::error( 'Error Connecting to the database: ' . $data );
break;
case 'DB':
Debug::error( 'Unspecified database error: ' . $data );
break;
case 'view':
Debug::error( 'View not found: ' . $data );
break;
case 'controller':
Debug::error( 'Controller not found: ' . $data );
Redirect::to( 404 );
break;
case 'defaultController':
Debug::error( 'DEFAULT Controller not found: ' . $data );
Redirect::to( 404 );
break;
case 'method':
Debug::error( 'Method not found: ' . $data );
Redirect::to( 404 );
break;
case 'simpleView':
Debug::error( 'View not found: ' . $data );
break;
case 'defaultMethod':
Debug::error( 'DEFAULT Method not found: ' . $data );
Redirect::to( 404 );
break;
default:
Debug::error( 'Default exception: ' . $data );
break;
}
}
}

745
vendor/bedrock/classes/database.php vendored Normal file
View File

@ -0,0 +1,745 @@
<?php
/**
* classes/database.php
*
* Defines all interactions with the database.
*
* @todo - Add more than just MySQL
*
* @version 3.0
* @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com/Core
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/
namespace TheTempusProject\Bedrock\Classes;
use PDO;
use PDOException;
use TheTempusProject\Houdini\Classes\Pagination;
use TheTempusProject\Canary\Canary as Debug;
class Database {
public static $instance = null;
private $pdo = null;
private $query = null;
private $error = false;
private $results = null;
private $count = 0;
private $maxQuery = 0;
private $totalResults = 0;
private $errorMessage = null;
private $tableBuff = null;
private $fieldBuff = null;
private $queryStatus = false;
/**
* Checks the DB connection with the provided information.
*
* @param string $host - Database Host.
* @param string $db - Database Name.
* @param string $user - Database Username.
* @param string $pass - Database Password.
*
* @return bool
*/
public static function check( $host = null, $db = null, $user = null, $pass = null ) {
if ( empty( $host ) || empty( $db ) || empty( $user ) || empty( $pass ) ) {
Debug::error( 'check::db: one or more parameters are missing.' );
return false;
}
try {
Debug::log( 'Attempting to connect to DB with supplied credentials.' );
$test = new PDO( 'mysql:host=' . $host . ';dbname=' . $db, $user, $pass );
} catch ( PDOException $Exception ) {
Debug::error( 'Cannot connect to DB with provided credentials: ' . $Exception->getMessage() );
return false;
}
return true;
}
/**
* Checks the current database in the configuration file for version verification.
*
* @return boolean
*
* @todo - Update this function to be more effective.
*/
public static function mysql() {
self::connect();
$dbVersion = self::$db->version();
preg_match( '@[0-9]+\.[0-9]+\.[0-9]+@', $dbVersion, $version );
if ( version_compare( $version[0], '10.0.0', '>' ) ) {
return true;
}
self::addError( "MySQL Version is too low! Current version is $version[0]. Version 10.0.0 or higher is required." );
return false;
}
/**
* Automatically open the DB connection with settings from our global config.
*/
private function __construct( $host = null, $name = null, $user = null, $pass = null ) {
Debug::debug( 'Class initialized: ' . get_class( $this ) );
if ( isset( $host ) && isset( $name ) && isset( $user ) && isset( $pass ) ) {
try {
Debug::log( 'Attempting to connect to DB with supplied credentials.' );
$this->pdo = new PDO( 'mysql:host=' . $host . ';dbname=' . $name, $user, $pass );
} catch ( PDOException $Exception ) {
$this->error = true;
$this->errorMessage = $Exception->getMessage();
}
}
if ( !$this->enabled() ) {
$this->error = true;
$this->errorMessage = 'Database disabled in config.';
}
if ( $this->error === false ) {
try {
Debug::debug( 'Attempting to connect to DB with config credentials.' );
$this->pdo = new PDO( 'mysql:host=' . Config::getValue( 'database/dbHost' ) . ';dbname=' . Config::getValue( 'database/dbName' ), Config::getValue( 'database/dbUsername' ), Config::getValue( 'database/dbPassword' ) );
} catch ( PDOException $Exception ) {
$this->error = true;
$this->errorMessage = $Exception->getMessage();
}
}
if ( $this->error !== false ) {
new CustomException( 'dbConnection', $this->errorMessage );
return;
}
$this->maxQuery = Config::getValue( 'database/dbMaxQuery' );
// @TODO add a toggle for this
$this->pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
Debug::debug( 'DB connection successful' );
return;
}
/**
* Checks whether the DB is enabled via the config file.
*
* @return bool - whether the db module is enabled or not.
*/
public function enabled( $type = '' ) {
if ( Config::getValue( 'database/dbEnabled' ) === true ) {
return true;
}
return false;
}
public function lastId() {
return $this->pdo->lastInsertId();
}
/**
* Checks to see if there is already a DB instance open, and if not; create one.
*
* @return function - Returns the PDO DB connection.
*/
public static function getInstance( $host = null, $name = null, $user = null, $pass = null, $new = false ) {
// used to force a new connection
if ( !empty( $host ) && !empty( $name ) && !empty( $user ) && !empty( $pass ) ) {
self::$instance = new self( $host, $name, $user, $pass );
}
if ( empty( self::$instance ) || $new ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Returns the DB version.
*
* @return bool|string
*/
public function version() {
if ( !$this->enabled() ) {
$this->error = true;
$this->errorMessage = 'Database disabled';
return false;
}
$sql = 'select version()';
if ( $this->query = $this->pdo->prepare( $sql ) ) {
try {
$this->query->execute();
} catch ( PDOException $Exception ) {
$this->error = true;
$this->errorMessage = $Exception->getMessage();
Debug::error( 'DB Version Error' );
Debug::error( $this->errorMessage );
return false;
}
return $this->query->fetchColumn();
}
return false;
}
/**
* Checks the database to see if the specified table exists.
*
* @param string $name - The name of the table to check for.
*
* @return boolean
*/
protected function tableExists( $name ) {
$name = Config::getValue( 'database/dbPrefix' ) . $name;
$this->raw( "SHOW TABLES LIKE '$name'" );
if ( $this->error ) {
Debug::error( var_export( $this->errorMessage, true ) );
return false;
}
if ( $this->count === 0 ) {
return false;
}
return true;
}
/**
* Checks first that the table exists, then checks if the specified
* column exists in the table.
*
* @param string $table - The table to search.
* @param string $column - The column to look for.
*
* @return boolean
*
* @todo - Is it necessary to check the current $fields list too?
*/
protected function columnExists( $table, $column ) {
if ( !$this->tableExists( $table ) ) {
return false;
}
$table = Config::getValue( 'database/dbPrefix' ) . $table;
$this->raw( "SHOW COLUMNS FROM `$table` LIKE '$column'" );
if ( !$this->error && $this->count === 0 ) {
return false;
}
return true;
}
/**
* Execute a raw DB query.
*
* @param string $data the query to execute
*
* @return bool
*/
public function raw( $data ) {
$this->queryReset();
if ( !$this->enabled() ) {
$this->error = true;
$this->errorMessage = 'Database disabled';
return false;
}
$this->query = $this->pdo->prepare( $data );
try {
$this->query->execute();
} catch ( PDOException $Exception ) {
$this->error = true;
$this->errorMessage = $Exception->getMessage();
Debug::warn( 'DB Raw Query Error' );
Debug::warn( $this->errorMessage );
return false;
}
// @todo i think this will cause an error some circumstances
$this->count = $this->query->rowCount();
return true;
}
/**
* The actual Query function. This function takes our setup queries
* and send them to the database. it then properly sets our instance
* variables with the proper info from the DB, as secondary constructor
* for almost all objects in this class.
*
* @param string $sql - The SQL to execute.
* @param array $params - Any bound parameters for the query.
*
* @return object
*/
public function query( $sql, $params = [], $noFetch = false ) {
$this->queryReset();
if ( $this->pdo == false ) {
Debug::warn( 'DB::query - no database connection established' );
$this->error = true;
$this->errorMessage = 'DB::query - no database connection established';
return $this;
}
$this->query = $this->pdo->prepare( $sql );
if ( !empty( $params ) ) {
$x = 0;
foreach ( $params as $param ) {
$x++;
if ( is_array( $param ) ) {
dv( $param );
}
$this->query->bindValue( $x, $param );
}
}
try {
$this->query->execute();
} catch ( PDOException $Exception ) {
$this->error = true;
$this->errorMessage = $Exception->getMessage();
Debug::error( 'DB Query Error' );
Debug::error( $this->errorMessage );
return $this;
}
if ( $noFetch === true ) {
$this->results = null;
$this->count = 1;
} else {
$this->results = $this->query->fetchAll( PDO::FETCH_OBJ );
$this->count = $this->query->rowCount();
}
return $this;
}
/**
* This function resets the values used for creating or modifying tables.
* Essentially a cleaner function.
*/
public function queryReset( $includeBuffers = false ) {
$this->results = null;
$this->count = 0;
$this->error = false;
$this->errorMessage = null;
$this->query = null;
if ( $includeBuffers ) {
$this->tableBuff = null;
$this->fieldBuff = null;
$this->queryStatus = false;
}
}
/**
* The action function builds all of our SQL.
*
* @todo : Clean this up.
*
* @param string $action - The type of action being carried out.
* @param string $tableName - The table name being used.
* @param array $where - The parameters for the action
* @param string $by - The key to sort by.
* @param string $direction - The direction to sort the results.
* @param array $limit - The result limit of the query.
*
* @return bool
*/
public function action( $action, $tableName, $where, $by = null, $direction = 'DESC', $reqLimit = null ) {
$this->totalResults = 0; // since this is how we paginate, it can't be reset when we exceed the max
if ( !$this->enabled() ) {
$this->error = true;
$this->errorMessage = 'Database disabled';
return $this;
}
$whereCount = count( $where );
if ( $whereCount < 3 ) {
Debug::error( 'DB::action - Not enough arguments supplied for "where" clause' );
$this->error = true;
$this->errorMessage = 'DB::action - Not enough arguments supplied for "where" clause';
return $this;
}
if ( $action == 'DELETE' ) {
$noFetch = true;
}
$tableName = Config::getValue( 'database/dbPrefix' ) . $tableName;
$sql = "{$action} FROM `{$tableName}` WHERE ";
$validOperators = ['=', '!=', '>', '<', '>=', '<=', 'LIKE', 'IS'];
$validDelimiters = ['AND', 'OR'];
$values = [];
while ( $whereCount > 2 ) {
$whereCount = $whereCount - 3;
$field = array_shift( $where );
$operator = array_shift( $where );
array_push( $values, array_shift( $where ) );
if ( !in_array( $operator, $validOperators ) ) {
Debug::error( 'DB::action - Invalid operator.' );
$this->error = true;
$this->errorMessage = 'DB::action - Invalid operator.';
return $this;
}
$sql .= "{$field} {$operator} ?";
if ( $whereCount > 0 ) {
$delimiter = array_shift( $where );
if ( !in_array( $delimiter, $validDelimiters ) ) {
Debug::error( 'DB::action - Invalid delimiter.' );
$this->error = true;
$this->errorMessage = 'DB::action - Invalid delimiter.';
return $this;
}
$sql .= " {$delimiter} ";
$whereCount--;
}
}
if ( isset( $by ) ) {
$sql .= " ORDER BY {$by} {$direction}";
}
$sqlPreLimit = $sql;
if ( !empty( $reqLimit ) ) {
$lim = implode(',',$reqLimit);
$sql .= " LIMIT {$lim}";
}
if ( isset( $values ) ) {
if ( !empty( $noFetch ) ) {
$error = $this->query( $sql, $values, true )->error();
} else {
$error = $this->query( $sql, $values )->error();
}
} else {
$error = $this->query( $sql )->error();
}
if ( $error ) {
Debug::warn( 'DB Action Error: ' );
Debug::warn( $this->errorMessage );
return $this;
}
$this->totalResults = $this->count;
if ( $this->count <= $this->maxQuery ) {
return $this;
}
Debug::warn( 'Query exceeded maximum results. Maximum allowed is ' . $this->maxQuery );
if ( !empty( $limit ) ) {
$newLimit = ( $reqLimit[0] + Pagination::perPage() );
$limit = " LIMIT {$reqLimit[0]},{$newLimit}";
} else {
$limit = ' LIMIT 0,' .Pagination::perPage();
}
$sql = $sqlPreLimit . $limit;
if ( isset( $values ) ) {
$error = $this->query( $sql, $values )->error();
} else {
$error = $this->query( $sql )->error();
}
if ( $error ) {
Debug::warn( 'DB Action Error: ' );
Debug::warn( $this->errorMessage );
}
return $this;
}
/**
* Function to insert into the DB.
*
* @param string $table - The table you wish to insert into.
* @param array $fields - The array of fields you wish to insert.
*
* @return bool
*/
public function insert( $table, $fields = [] ) {
$keys = array_keys( $fields );
$valuesSQL = null;
$x = 0;
$keysSQL = implode( '`, `', $keys );
foreach ( $fields as $value ) {
$x++;
$valuesSQL .= '?';
if ( $x < count( $fields ) ) {
$valuesSQL .= ', ';
}
}
$table = Config::getValue( 'database/dbPrefix' ) . $table;
$sql = "INSERT INTO `{$table}` (`" . $keysSQL . "`) VALUES ({$valuesSQL})";
if ( !$this->query( $sql, $fields, true )->error() ) {
return true;
}
return false;
}
/**
* Function to duplicate a database entry.
*
* @param string $table - The table you wish to duplicate the entry in.
* @param int $id - The ID of the entry you wish to duplicate.
*
* @return bool
*/
public function duplicateEntry($table, $id) {
// Get the original entry
$originalEntry = $this->action('SELECT', $table, ['ID', '=', $id])->results();
// Exclude the ID field
unset($originalEntry->ID);
// Insert the duplicated entry
if ($this->insert($table, (array) $originalEntry)) {
return true;
}
return false;
}
/**
* Function to update the database.
*
* @param string $table - The table you wish to update in.
* @param int $id - The ID of the entry you wish to update.
* @param array $fields - the various fields you wish to update
*
* @return bool
*/
public function update( $table, $id, $fields = [] ) {
$updateSQL = null;
$x = 0;
foreach ( $fields as $name => $value ) {
$x++;
$updateSQL .= "{$name} = ?";
if ( $x < count( $fields ) ) {
$updateSQL .= ', ';
}
}
$table = Config::getValue( 'database/dbPrefix' ) . $table;
$sql = "UPDATE {$table} SET {$updateSQL} WHERE ID = {$id}";
if ( !$this->query( $sql, $fields, true )->error() ) {
return true;
}
return false;
}
/**
* Deletes a series of, or a single instance(s) in the database.
*
* @param string $table - The table you are deleting from.
* @param string $where - The criteria for deletion.
*
* @return function
*/
public function delete( $table, $where ) {
return $this->action( 'DELETE', $table, $where );
}
/**
* Starts the object to create a new table if none already exists.
*
* NOTE: All tables created with this function will automatically
* have an 11 digit integer called ID added as a primary key.
*
* @param string $name - The name of the table you wish to create.
*
* @return boolean
*
* @todo - add a check for the name.
*/
public function newTable( $name, $addID = true ) {
if ( $this->tableExists( $name ) ) {
$this->tableBuff = null;
Debug::error( "Table already exists: $name" );
return false;
}
$this->queryReset( true );
$this->tableBuff = $name;
if ( $addID === true ) {
$this->addField( 'ID', 'int', 11, false );
}
return true;
}
/**
* Builds and executes a database query to to create a table
* using the current object's table name and fields.
*
* NOTE: By default: All tables have an auto incrementing primary key named 'ID'.
*
* @todo - Come back and add more versatility here.
*/
public function createTable() {
if ( empty( $this->tableBuff ) ) {
Debug::info( 'No Table set.' );
return false;
}
$table = Config::getValue( 'database/dbPrefix' ) . $this->tableBuff;
if ( $this->tableExists( $this->tableBuff ) ) {
Debug::error( "Table already exists: $table" );
return false;
}
$queryBuff = "CREATE TABLE `$table` (";
$x = 0;
$y = count( $this->fieldBuff );
while ( $x < $y ) {
$queryBuff .= $this->fieldBuff[$x];
$x++;
$queryBuff .= ( $x < $y ) ? ',' : '';
}
$queryBuff .= ') ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `' . $table . '` ADD PRIMARY KEY (`ID`); ';
$queryBuff .= 'ALTER TABLE `' . $table . "` MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Primary index value';";
$this->queryStatus = ( $this->raw( $queryBuff ) ? true : false );
return $this->queryStatus;
}
public function removeTable( $name ) {
if ( !$this->tableExists( $name ) ) {
Debug::error( "No table exists: $name" );
return false;
}
$table = Config::getValue( 'database/dbPrefix' ) . $name;
$this->queryStatus = ( $this->raw( 'DROP TABLE `' . $table . '`' ) ? true : false );
return $this->queryStatus;
}
/**
* This function allows you to add a new field to be
* added to a previously specified table.
*
* @param string $name - The name of the field to add
* @param string $type - The type of field.
* @param integer $length - The maximum length value for the field.
* @param boolean $null - Whether or not the field can be null
* @param string $default - The default value to use for new entries if any.
* @param string $comment - DB comment for this field.
*
* @return boolean
*
* @todo - add more error reporting and checks
* use switch/cases?
*/
public function addField( $name, $type, $length, $null = true, $default = null, $comment = '' ) {
if ( empty( $this->tableBuff ) ) {
Debug::info( 'No Table set.' );
return false;
}
if ( $this->columnExists( $this->tableBuff, $name ) ) {
Debug::error( "Column already exists: $this->tableBuff > $name" );
return false;
}
if ( $null === true ) {
$sDefault = ' DEFAULT NULL';
} else {
$sDefault = ' NOT NULL';
if ( !empty( $default ) ) {
$sDefault .= " DEFAULT '$default'";
}
}
if ( !empty( $length ) ) {
if ( is_int( $length ) ) {
$sType = $type . '(' . $length . ')';
} elseif ( is_string( $length ) && ctype_digit( $length ) ) {
$sType = $type . '(' . $length . ')';
} else {
$sType = $type;
}
} else {
$sType = $type;
}
if ( !empty( $comment ) ) {
$sComment = " COMMENT '$comment'";
} else {
$sComment = '';
}
$this->fieldBuff[] = ' `' . $name . '` ' . $sType . $sDefault . $sComment;
return true;
}
public function search( $table, $column, $param ) {
return $this->action( 'SELECT *', $table, [$column, 'LIKE', '%' . $param . '%'] );
}
/**
* Selects data from the database.
*
* @param string $table - The table we wish to select from.
* @param string $where - The criteria we wish to select.
* @param string $by - The key we wish to order by.
* @param string $direction - The direction we wish to order the results.
*
* @return function
*/
public function get( $table, $where, $by = 'ID', $direction = 'DESC', $limit = null ) {
if ( $where === '*' ) {
$where = ['ID', '>=', '0'];
}
return $this->action( 'SELECT *', $table, $where, $by, $direction, $limit );
}
/**
* Selects data from the database and automatically builds the pagination filter for the results array.
*
* @param string $table - The table we wish to select from.
* @param string $where - The criteria we wish to select.
* @param string $by - The key we wish to order by.
* @param string $direction - The direction we wish to order the results.
*
* @return function
*/
public function getPaginated( $table, $where, $by = 'ID', $direction = 'DESC', $limit = null ) {
if ( $where === '*' ) {
$where = ['ID', '>=', '0'];
}
$db = $this->action( 'SELECT ID', $table, $where, $by, $direction );
Pagination::updatePaginationTotal( $this->totalResults );
if ( ! is_array( $limit ) ) {
$limit = [ Pagination::getMin(), Pagination::getMax() ];
}
Pagination::paginate();
return $this->action( 'SELECT *', $table, $where, $by, $direction, $limit );
}
/**
* Function for returning the entire $results array.
*
* @return array - Returns the current query's results.
*/
public function results() {
return $this->results;
}
/**
* Function for returning the first result in the results array.
*
* @return array - Returns the current first member of the results array.
*/
public function first() {
if ( !empty( $this->results[0] ) ) {
return $this->results[0];
}
return false;
}
/**
* Function for returning current results' row count.
*
* @return int - Returns the current instance's SQL result count.
*/
public function count() {
return $this->count;
}
/**
* Returns if there are errors with the current query or not.
*
* @return bool
*/
public function error() {
return $this->error;
}
/**
* Returns if there are errors with the current query or not.
*
* @return bool
*/
public function errorMessage() {
//$this->query->errorInfo();
return $this->errorMessage;
}
/**
* Returns the boolean status of the most recently executed query.
*
* @return boolean
*/
public function getStatus() {
return $this->queryStatus;
}
}

View File

@ -0,0 +1,193 @@
<?php
/**
* core/database_model.php
*
* The class provides some basic functionality for models that interact
* with the database.
*
* @version 3.0
* @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com/Core
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/
namespace TheTempusProject\Bedrock\Classes;
use TheTempusProject\Canary\Canary as Debug;
use TheTempusProject\Bedrock\Functions\Check;
use TheTempusProject\Bedrock\Bedrock;
class DatabaseModel extends Model {
public $databaseMatrix;
public $tableName;
public function __construct() {
parent::__construct();
}
public function enabled() {
if ( empty( $this->enabled ) ) {
$this->enabled = self::$db->enabled();
}
return $this->enabled;
}
public function filter( $data, $params = [] ) {
return $data;
}
/**
* This method will remove all the installed model components.
*
* @return bool - If the uninstall was completed without error
*/
public function uninstall() {
parent::uninstall();
$this->uninstallTable();
return true;
}
public function rowMatrixToArray( $row_matrix ) {
$row_array = [];
$row_array['row_name'] = array_shift( $row_matrix );
$row_array['row_type'] = array_shift( $row_matrix );
$row_array['length'] = array_shift( $row_matrix );
if ( !empty( $row_matrix ) ) {
$row_array['is_null'] = array_shift( $row_matrix );
} else {
$row_array['is_null'] = true;
}
if ( !empty( $row_matrix ) ) {
$row_array['default_value'] = array_shift( $row_matrix );
} else {
$row_array['default_value'] = null;
}
if ( !empty( $row_matrix ) ) {
$row_array['comment'] = array_shift( $row_matrix );
} else {
$row_array['comment'] = '';
}
return $row_array;
}
/**
* Install db tables needed for the model.
*
* @return {bool}
*/
public function installTable() {
// should have some sort of DELTA functionality and safeguards
if ( empty( $this->tableName ) || empty( $this->databaseMatrix )) {
Debug::log( 'databaseMatrix is empty' );
return true;
}
if ( false === self::$db->newTable( $this->tableName ) ) {
return false;
}
Debug::log( 'adding a new table named: ' . $this->tableName );
foreach ( $this->databaseMatrix as $key => $row_matrix ) {
$row = $this->rowMatrixToArray( $row_matrix );
self::$db->addField(
$row['row_name'],
$row['row_type'],
$row['length'],
$row['is_null'],
$row['default_value'],
$row['comment'],
);
}
self::$db->createTable();
return self::$db->getStatus();
}
public function uninstallTable() {
if ( empty( $this->tableName ) ) {
return;
}
return self::$db->removeTable( $this->tableName );
}
/**
* Retrieves a row by its ID and filters it.
*
* @param {int} [$id]
* @return {object} - The filtered db entry.
*/
public function findById( $id ) {
if ( !Check::id( $id ) ) {
Debug::warn( "$this->tableName fingByID: illegal ID: $id" );
return false;
}
$data = self::$db->get( $this->tableName, ['ID', '=', $id] );
if ( !$data->count() ) {
Debug::info( 'No ' . $this->tableName . ' data found.' );
return false;
}
return $this->filter( $data->first() );
}
/**
* Function to delete the specified entry.
*
* @param int|array $ID the log ID or array of ID's to be deleted
* @return bool
*/
public function delete( $idArray ) {
if ( !is_array( $idArray ) ) {
$idArray = [ $idArray ];
}
foreach ( $idArray as $id ) {
if ( !Check::id( $id ) ) {
Debug::info( "invalid ID: $id." );
$error = true;
continue;
}
if ( self::$db->delete( $this->tableName, [ 'ID', '=', $id ] )->error() ) {
Debug::info( "Error Deleting id: $id" );
$error = true;
continue;
}
Debug::info( $this->tableName . " deleted: $id" );
}
if ( !empty( $error ) ) {
return false;
}
return true;
}
/**
* Function to clear entries of a defined type.
*
* @todo this is probably dumb
* @param string $data - The log type to be cleared
* @return bool
*/
public function empty() {
self::$db->delete( $this->tableName, ['ID', '>=', '0'] );
Debug::info( $this->tableName . ' Cleared' );
return true;
}
/**
* retrieves a list of paginated (limited) results.
*
* @param array $filter - A filter to be applied to the list.
* @return bool|object - Depending on success.
*/
public function listPaginated( $filter = null ) {
$data = self::$db->getPaginated( $this->tableName, '*' );
if ( !$data->count() ) {
Debug::info( $this->tableName . ' - No entries found' );
return false;
}
return $this->filter( $data->results() );
}
public function list( $filter = null ) {
$data = self::$db->get( $this->tableName, '*' );
if ( !$data->count() ) {
Debug::info( $this->tableName . ' - No entries found' );
return false;
}
return $this->filter( $data->results() );
}
}

124
vendor/bedrock/classes/model.php vendored Normal file
View File

@ -0,0 +1,124 @@
<?php
/**
* core/model.php
*
* The class provides some basic functionality for models.
*
* @version 3.0
* @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com/Core
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/
namespace TheTempusProject\Bedrock\Classes;
use TheTempusProject\Canary\Canary as Debug;
use TheTempusProject\Bedrock\Classes\Config;
use TheTempusProject\Bedrock\Classes\Database;
class Model {
public static $db;
public $configName;
public $configMatrix = [];
public $resourceMatrix = [];
public $modelVersion;
public $enabled = false;
/**
* The model constructor.
*/
public function __construct() {
Debug::debug( 'Model Constructed: ' . get_class( $this ) );
self::$db = Database::getInstance();
$this->load();
}
/**
* This method will remove all the installed model components.
*
* @return bool - If the uninstall was completed without error
*/
public function uninstall() {
$this->uninstallResources();
$this->uninstallConfigs();
return true;
}
/**
* Install resources needed for the model.
*
* @return {bool}
*/
public function installResources() {
// should have some sort of DELTA functionality and safeguards
$ids = [];
if ( empty($this->resourceMatrix) ) {
return true;
}
foreach ( $this->resourceMatrix as $entry ) {
foreach ( $entry as $key => $value ) {
if ( '{time}' == $value ) {
$entry[$key] = time();
}
}
self::$db->insert( $this->tableName, $entry );
$id = self::$db->lastId();
if ( $id ) {
$ids[] = $id;
}
}
return $ids;
}
public function uninstallResources() {
// this one needs some work
// should probably save the created resource ID's or something and remove them.
// presumably this isn't a big issue because i would imagine the table is removed
// there may be future instances where you can create resources for other tables
return true;
}
/**
* Install configs needed for the model.
*
* @return {bool}
*/
public function installConfigs() {
$config = new Config( CONFIG_JSON );
// should have some sort of DELTA functionality and safeguards
$config->addCategory( $this->configName );
foreach ( $this->configMatrix as $name => $details ) {
$config->add( $this->configName, $name, $details );
}
return $config->save();
}
public function uninstallConfigs() {
if ( empty( $this->configName ) ) {
return true;
}
$config = new Config( CONFIG_JSON );
return $config->removeCategory( $this->configName, true, true );
}
/**
* Tells the installer which types of integrations your model needs to install.
*
* @return bool - if the model was loaded without error
*/
public function load() {
return true;
}
public function getModelVersion() {
return $this->modelVersion;
}
/**
* Checks if the model is enabled.
*
* @return bool - if the model is enabled or not
*/
public function enabled() {
return $this->enabled;
}
}