Updates all over. Redid some of the doc blocks cause they weren't to scale of a vim session with lline numbers on (still may not be... ugh). Also changed around some of the model level variables and stuff.

git-svn-id: http://svn.cleancode.org/svn/pickles@58 4d10bc64-7434-11dc-a737-d2d0f8310089
This commit is contained in:
Josh Sherman 2008-09-24 03:37:09 +00:00
parent 3d4b9f63b8
commit e02ded351d
12 changed files with 206 additions and 221 deletions

View file

@ -3,15 +3,15 @@
/**
* Small collection of array utilities
*
* A bit too small actually, as there is still only one function in here. Since
* I have built PICKLES based around my own needs, this has been the only
* function I have felt the need to add.
* A bit too small actually, as there is still only one function in here.
* Since I have built PICKLES based around my own needs, this has been the
* only function I have felt the need to add.
*
* @package PICKLES
* @author Joshua Sherman <josh@phpwithpickles.org>
* @copyright 2007-2008 Joshua Sherman
* @todo Just so it doesn't seem so bare, I need to add a few more common
* array manipulation functions.
* @todo Just so it doesn't seem so bare, I need to add a few more
* common array manipulation functions.
*/
class ArrayUtils {
@ -19,7 +19,8 @@ class ArrayUtils {
* Converts an object into an array (recursive)
*
* This only gets used by the Config class because simplexml_load_file()
* returns an object by default, and I prefered having it in an array format.
* returns an object by default, and I prefered having it in an array
* format.
*
* @param object $object Object to be converted into an array
* @return array Resulting array formed from the passed object

View file

@ -4,10 +4,10 @@
* Configuration class
*
* Handles loading and caching of the configuration into a Singleton object.
* Contains logic to determine if the configuration has already been loaded and
* will opt to use a "frozen" object rather than instantiate a new one. Also
* contains logic to reload configurations if the configuration file had been
* modified since it was originally instantiated (smart caching).
* Contains logic to determine if the configuration has already been loaded
* and will opt to use a "frozen" object rather than instantiate a new one.
* Also contains logic to reload configurations if the configuration file
* had been modified since it was originally instantiated (smart caching).
*
* @package PICKLES
* @author Joshua Sherman <josh@phpwithpickles.org>
@ -21,11 +21,6 @@ class Config extends Singleton {
*/
private static $instance;
/**
* Timestamp from when the object was frozen
*/
public $timestamp = null;
/**
* Private constructor
*/
@ -34,19 +29,15 @@ class Config extends Singleton {
/**
* Gets an instance of the configuration object
*
* Determines if a Config object has already been instantiated, if so it will
* use it. If not, it will check to see if a frozen copy of the object is
* available. If not, then a new object will be created.
* Determines if a Config object has already been instantiated, if so it
* will use it. If not, it will create one.
*
* @return An instace of the Config class
*/
public static function getInstance() {
$class = __CLASS__;
if (isset($_SESSION['objects'][$class])) {
self::$instance = Singleton::thaw($class);
}
else if (!self::$instance instanceof $class) {
if (!self::$instance instanceof $class) {
self::$instance = new $class();
}
@ -56,70 +47,59 @@ class Config extends Singleton {
/**
* Loads a configuration file
*
* Handles the potentialy loading of the configuration file, sanitizing the
* boolean values and freezing the instance for later use.
* Handles the potential loading of the configuration file and
* sanitizing the boolean strings into actual boolean values.
*
* @param string $file File name of the configuration file to be loaded
* @return boolean Based on the success or failure of the file load
* @todo Either get rid of or make better use of the Error object
*/
public function load($file) {
$load = true;
if (isset($this->file)) {
if (file_exists($this->file) && isset($this->timestamp)) {
if (filemtime($this->file) < $this->timestamp) {
$load = false;
}
}
}
if ($load) {
if (file_exists($file)) {
$this->file = $file;
if (file_exists($file)) {
$this->file = $file;
$config_array = ArrayUtils::object2array(simplexml_load_file($file));
$config_array = ArrayUtils::object2array(simplexml_load_file($file));
if (is_array($config_array)) {
foreach ($config_array as $variable => $value) {
if ($value == 'true' || $value == array()) {
$value = (bool)$value;
}
$this->$variable = $value == array() ? (bool)$value : $value;
if (is_array($config_array)) {
foreach ($config_array as $variable => $value) {
if ($value == 'true' || $value == array()) {
$value = (bool)$value;
}
$this->$variable = $value == array() ? (bool)$value : $value;
}
/**
* @todo Okay, now if no default section is specified, we'll
* default to the first section listed. But what should be
* done if no sections are specified? Perhaps force just
* the index to load, or perhaps error out? I have to keep
* in mind that single page sites exist where no navigation
* will exist. So yeah, I suppose just specifying the
* default would combat against that, or should I drill
* down further, and see if any site level models exist and
* load the first one, or even better I'm thinking that a
* shared model / template would be good when nothing is
* available. That would in turn tell the user to fix the
* issue to be able to get it all working again. Damn,
* this ended up being a long @todo.
* @todo This may be better suited in the loop above since we're
* already looping through all the values, we could snag it
* in passing.
*/
if (!isset($this->navigation['default']) || $this->navigation['default'] == '') {
$this->navigation['default'] = key($this->navigation['sections']);
}
$this->freeze();
return true;
}
else {
Error::addError('Unable to load the configuration file');
return false;
/**
* @todo Okay, now if no default section is specified, we'll
* default to the first section listed. But what
* should be done if no sections are specified?
* Perhaps force just the index to load, or perhaps
* error out? I have to keep in mind that single
* page sites exist where no navigation will exist.
* So yeah, I suppose just specifying the default
* would combat against that, or should I drill down
* further, and see if any site level models exist and
* load the first one, or even better I'm thinking
* that a shared model / template would be good when
* nothing is available. That would in turn tell the
* user to fix the issue to be able to get it all
* working again. Damn, this ended up being a very
* long @todo.
* @todo This may be better suited in the loop above since
* we're already looping through all the values, we
* could snag it in passing.
*/
if (!isset($this->navigation['default']) || $this->navigation['default'] == '') {
$this->navigation['default'] = key($this->navigation['sections']);
}
return true;
}
else {
Error::addError('Unable to load the configuration file');
return false;
}
}
}

View file

@ -40,14 +40,6 @@ class Controller extends Object {
public function __construct($file = '../config.xml', $controller = 'Web') {
parent::__construct();
// Start the session if it's not started already
/**
* @todo Need to make the session not so mandatory.
*/
if (ini_get('session.auto_start') == 0) {
session_start();
}
// Load the config for the site passed in
$this->config = Config::getInstance();
$this->config->load($file);
@ -94,30 +86,28 @@ class Controller extends Object {
$this->model = new Model();
}
if ($this->model->get('auth') == false) {
$this->model->set('auth', $this->config->get('behavior', 'auth'));
}
if ($this->model->get('view') == false) {
if ($this->config->get('behavior', 'view') != false) {
$view = $this->config->get('behavior', 'view');
// Start the session if it's not started already
/**
* @todo Need to make the session not so mandatory.
*/
if ($this->model->getSession() === true) {
if (ini_get('session.auto_start') == 0) {
session_start();
}
else {
// Perhaps Smarty shouldn't be assumed at this point...
$view = isset($argv) ? 'CLI' : 'Smarty';
}
$this->model->set('view', $view);
}
if ($this->model->get('auth') === true && $controller != 'CLI') {
if ($this->model->getAuthenticate() === true && $controller != 'CLI') {
Security::authenticate();
}
/**
* @todo are any of these relevant any more?
*/
$this->model->set('name', $name);
$this->model->set('section', $section);
$this->model->set('event', $event);
// Execute the model's logic
$this->model->__default();
// Load the viewer

View file

@ -3,19 +3,19 @@
/**
* Database abstraction layer for MySQL
*
* All database usage inside PICKLES-based sites should be done via the database
* object that is a part of every model ($this->db). Because the database
* object can execute raw SQL, there should be no limitations.
* All database usage inside PICKLES-based sites should be done via the
* database object that is a part of every model ($this->db). Because the
* database object can execute raw SQL, there should be no limitations.
*
* @package PICKLES
* @author Joshua Sherman <josh@phpwithpickles.org>
* @copyright 2007-2008 Joshua Sherman
* @todo Internally document the functions better.
* @todo Potentially switch to PDO to be able to easily accomodate different
* database types.
* @todo Eventually finish adding in my ActiveRecord class, even though I
* feel active record dumbs people down since it's a crutch for
* actually being able to write SQL.
* @todo Potentially switch to PDO to be able to easily accomodate
* different database types.
* @todo Eventually finish adding in my ActiveRecord class, even
* though I feel active record dumbs people down since it's a
* crutch for actually being able to write SQL.
*/
class DB extends Singleton {
@ -46,19 +46,15 @@ class DB extends Singleton {
/**
* Gets an instance of the database object
*
* Determines if a DB object has already been instantiated, if so it will use
* it. If not, it will check to see if a frozen copy of the object is
* available. If not, then a new object will be created.
* Determines if a DB object has already been instantiated, if so it
* will use it. If not, it will create one.
*
* @return object An instace of the DB class
*/
public static function getInstance() {
$class = __CLASS__;
if (isset($_SESSION['objects'][$class])) {
self::$instance = Singleton::thaw($class);
}
else if (!self::$instance instanceof $class) {
if (!self::$instance instanceof $class) {
self::$instance = new $class();
}
@ -68,12 +64,11 @@ class DB extends Singleton {
/**
* Opens database connection
*
* Establishes a connection to the MySQL database based on the configuration
* options that are available in the Config object.
* Establishes a connection to the MySQL database based on the
* configuration options that are available in the Config object.
*
* @return boolean Based on the success or failure of mysql_connect()
* @todo Remove the error supressing @ from mysql_connect()
* @todo Currently the DBO is not being cached in the object, since it stores the password, it's a security issue.
*/
public function open() {
if (!is_resource($this->connection)) {
@ -115,9 +110,9 @@ class DB extends Singleton {
/**
* Closes database connection
*
* Checks to see if the connection is available, and if so, closes it out.
* Checks to see if the connection is available, and if so, closes it.
*
* @return boolean Returns the status of mysql_close() or false (default)
* @return boolean Returns the status of mysql_close() (default = false)
*/
public function close() {
if (is_resource($this->connection)) {
@ -130,9 +125,9 @@ class DB extends Singleton {
/**
* Executes SQL
*
* Executes the passed SQL without any manipulation. If no SQL is passed in
* the function will return false (why return true if it didn't actually do
* something?)
* Executes the passed SQL without any manipulation. If no SQL is
* passed in the function will return false (why return true if it
* didn't actually do something?)
*
* @param string $sql SQL statement to be executed
* @return boolean Returns the status of the execution
@ -162,20 +157,21 @@ class DB extends Singleton {
* Gets a field from a result set
*
* Returns the value of a single field from either a previously executed
* query, or from the passed SQL. This function assumes your query results
* only contain a single field. If multiple fields are returned, this
* function will only return the first one.
* query, or from the passed SQL. This function assumes your query
* results only contain a single field. If multiple fields are
* returned, this function will only return the first one.
*
* @param string $sql SQL statement to be executed (optional)
* @return string Returns the value of the field or null if none
* @todo Need to remove the error supression
* @todo Right now it assumes your query only returns a single field, that
* probably should be changed to allow someone to specify what field
* they want from a row of data. Actually, this is still debatable
* as someone could use getRow and reference the field they want to
* accomplish the same goal.
* @todo Another debate point, should it return false instead of null, or
* perhaps have some sort of error indicator in the result set?
* @todo Right now it assumes your query only returns a single field,
* that probably should be changed to allow someone to specify
* what field they want from a row of data. Actually, this is
* still debatable as someone could use getRow and reference the
* field they want to accomplish the same goal.
* @todo Another debate point, should it return false instead of null,
* or perhaps have some sort of error indicator in the result
* set?
*/
public function getField($sql = null) {
if (isset($sql)) {
@ -201,26 +197,27 @@ class DB extends Singleton {
/**
* Gets a row from a result set
*
* Returns a row in an associative array from either a previously executed
* query, or from the passed SQL. This function assumes your query results
* only contain a single row. If multiple rows are returned, this function
* will only return the first one.
* Returns a row in an associative array from either a previously
* executed query, or from the passed SQL. This function assumes your
* query results only contain a single row. If multiple rows are
* returned, this function will only return the first one.
*
* @param string $sql SQL statement to be executed (optional)
* @return string Returns the row in an associative array or null if none
* @return mixed The row in an associative array or null if none
* @todo Need to remove the error supression
* @todo Right now it assumes your query only returns a single row, that
* probably should be changed to allow someone to specify what row
* they want from a set of data. Actually, this is still debatable
* as someone could use getArray and reference the row they want to
* accomplish the same goal.
* @todo Another debate point, should it return false instead of null, or
* perhaps have some sort of error indicator in the result set?
* @todo Calling bullshit on my own code, apparently this should only be
* returning a single row, but returns all the rows instead of just
* the first one. So basically, this function is functioning exactly
* the same as DB::getArray(). Just goes to show how often I
* actually use this function.
* @todo Right now it assumes your query only returns a single row,
* that probably should be changed to allow someone to specify
* what row they want from a set of data. Actually, this is
* still debatable as someone could use getArray and reference
* the row they want to accomplish the same goal.
* @todo Another debate point, should it return false instead of null,
* or perhaps have some sort of error indicator in the result
* set?
* @todo Calling bullshit on my own code, apparently this should only
* be returning a single row, but returns all the rows instead
* of just the first one. So basically, this function is
* functioning exactly the same as DB::getArray(). Just goes to
* show how often I actually use this function.
*/
public function getRow($sql = null) {
if (isset($sql)) {
@ -252,8 +249,9 @@ class DB extends Singleton {
* @param string $sql SQL statement to be executed (optional)
* @return string Returns the rows in an array or null if none
* @todo Need to remove the error supression
* @todo Another debate point, should it return false instead of null, or
* perhaps have some sort of error indicator in the result set?
* @todo Another debate point, should it return false instead of null,
* or perhaps have some sort of error indicator in the result
* set?
*/
public function getArray($sql = null) {
if (isset($sql)) {
@ -282,15 +280,16 @@ class DB extends Singleton {
/**
* Inserts a row into a table
*
* Easy insertion of a row into a table without being too savvy with SQL.
* Easy insertion of a row into a table without being too savvy with
* SQL.
*
* @param string $table Name of the table you want to insert to
* @param array $columnValues Associative array of name value pairs
* (Corresponds with the column names for the table)
* @return boolean Returns the status of the execution
* @todo Convert from camel case to underscores
* @todo Check that the table exists, and possibly check that the columns
* exist as well
* @todo Check that the table exists, and possibly check that the
* columns exist as well
*/
public function insert($table, $columnValues) {
$this->open();
@ -331,12 +330,12 @@ class DB extends Singleton {
* @params string $table Name of the table you want to insert to
* @params array $columnValues Associative array of name value pairs
* (Corresponds with the column names for the table)
* @params array $conditions Associative array of name value pairs that will
* be used to create a WHERE clause in the SQL.
* @params array $conditions Associative array of name value pairs that
will be used to create a WHERE clause in the SQL.
* @return boolean Returns the status of the execution
* @todo Convert from camel case to underscores
* @todo Check that the table exists, and possibly check that the columns
* exist and conditional columns exist as well
* @todo Check that the table exists, and possibly check that the
* columns exist and conditional columns exist as well
*/
public function update($table, $columnValues, $conditions) {
$this->open();
@ -390,8 +389,8 @@ class DB extends Singleton {
* @params string $table Name of the table you want to insert to
* @params array $columnValues Associative array of name value pairs
* (Corresponds with the column names for the table)
* @params array $conditions Associative array of name value pairs that will
* be used to create a WHERE clause in the SQL.
* @params array $conditions Associative array of name value pairs that
* will be used to create a WHERE clause in the SQL.
* @return boolean Returns the status of the execution
* @todo This function doesn't exist yet
* @todo Convert from camel case to underscores
@ -399,7 +398,6 @@ class DB extends Singleton {
public function delete($table, $columnValues, $conditions) {
}
}
?>

View file

@ -21,13 +21,17 @@ class Model extends Object {
/**
* Database object
*/
protected $db = null;
protected $db = null;
/**
* Name of the model
*/
protected $name = null;
protected $authenticate = null;
protected $viewer = null;
protected $session = null;
/**
* Constructor
*
@ -41,12 +45,56 @@ class Model extends Object {
}
/**
* Gets the auth variable
* Gets the authenticate value
*
* @return boolean Whether or not the model requires authorization to use
* @todo Add in configuration level override
* @return boolean Whether or not the model requires user authentication to use
*/
public function getAuth() {
return $this->get('auth');
public function getAuthenticate() {
// Order of precedence: Model, Config, Guess
if ($this->authenticate == null) {
return false;
}
else {
return $this->authenticate;
}
}
/**
* Gets the session value
*
* @todo Add in configuration level override
* @return boolean Whether or not the session needs to be started
*/
public function getSession() {
// Order of precedence: Auth On, Model, Config, Guess
if ($this->authenticate === true) {
return true;
}
else {
if ($this->session == null) {
return false;
}
else {
return $this->session;
}
}
}
/**
* Gets the requested Viewer
*
* @todo Add in configuration level override
* @return string The viewer that the model has requested to be used
*/
public function getViewer() {
// Order of precedence: Model, Config, Guess
if ($this->viewer == null) {
return isset($argv) ? 'CLI' : 'Smarty';
}
else {
return $this->viewer;
}
}
/**
@ -58,15 +106,6 @@ class Model extends Object {
return $this->get('data');
}
/**
* Gets the view type
*
* @return string The viewer that the model has requested to be used
*/
public function getView() {
return $this->get('view');
}
/**
* Destructor
*

View file

@ -16,8 +16,6 @@ class Object {
/**
* Protected instance of the Config class
*
* @todo Perhaps this should be private?
*/
protected $config = null;

View file

@ -29,8 +29,7 @@ class Security extends Object {
* the configuration as well.
*/
static function authenticate() {
$db = DB::getInstance();
$session = Session::getInstance();
$db = DB::getInstance();
if (isset($_SERVER['PHP_AUTH_USER'])) {
$from = '
@ -43,14 +42,14 @@ class Security extends Object {
$db->execute('SELECT COUNT(id) ' . $from);
if ($db->getField() != 0) {
$db->execute('SELECT id ' . $from);
$session->user_id = $db->getField();
$_SESSION['user_id'] = $db->getField();
}
else {
$session->user_id = null;
$_SESSION['user_id'] = null;
}
}
if (!isset($session->user_id)) {
if (!isset($_SESSION['user_id'])) {
header('WWW-Authenticate: Basic realm="Site Admin"');
header('HTTP/1.0 401 Unauthorized');
exit('No shirt, no shoes, no salvation. Access denied.');

View file

@ -4,9 +4,9 @@
* Singleton class
*
* This is the file that you include on the page you're instantiating the
* controller from (typically index.php). The path to the PICKLES code base is
* established as well as the path that Smarty will use to store the compiled
* pages.
* controller from (typically index.php). The path to the PICKLES code base
* is established as well as the path that Smarty will use to store the
* compiled pages.
*
* @package PICKLES
* @author Joshua Sherman <josh@phpwithpickles.org>
@ -19,18 +19,25 @@ class Singleton {
*/
private function __construct() { }
/**
* __clone
*/
public function __clone() {
trigger_error('Cloning is not available on a Singleton (that would defeat the purpose wouldn\'t it?)', E_USER_ERROR);
}
/**
* Gets a variable
*
* @param string $variable Name of the variable to be returned
* @param string $array_element Name of the array element that's part of the
* requested variable (optional)
* @param string $array_element Name of the array element that's part
* of the requested variable (optional)
* @return Returns either the variable value or false if no variable.
* @todo Need better checking if the passed variable is an array when the
* array element value is present
* @todo Need better checking if the passed variable is an array when
* the array element value is present
* @todo Returning false could be misleading, especially if you're
* expecting a boolean value to begin with. Perhaps an error should
* be thrown?
* expecting a boolean value to begin with. Perhaps an error
* should be thrown?
*/
public function get($variable, $array_element = null) {
if (isset($this->$variable)) {
@ -58,37 +65,6 @@ class Singleton {
public function set($variable, $value) {
$this->$$variable = $value;
}
/**
* Freezes (caches) an object
*
* Takes the object and serializes it and then stores it and the name and the
* timestamp that it was serialized in the session.
*
* @todo Needs to return the status for error tracking.
*/
public function freeze() {
$this->timestamp = time();
$class = get_class($this);
$_SESSION['objects'][$class] = serialize($this);
}
/**
* Thaws out a frozen object
*
* Forces an __autoload on the passed class name because if a serialized
* object is unserialized and then you attempt to use it, it will error out
* due to the class not being loaded. __autoload() doesn't occur
* automatically in this scenario, that's why it must be forced.
*
* @param string $class The name of the class to be thawed out
* @return object The unserialized object for the passed class name
*/
public static function thaw($class) {
__autoload($class);
return unserialize($_SESSION['objects'][$class]);
}
}
?>

View file

@ -31,7 +31,7 @@ class Viewer {
* constants would each be uppercase instead of mixedcase.
*/
public static function factory(Model $model) {
$class = 'Viewer_' . $model->getView();
$class = 'Viewer_' . $model->getViewer();
return new $class($model);
}
}

View file

@ -2,6 +2,8 @@
class store extends Model {
protected $session = true;
public function __construct() {
parent::__construct();

View file

@ -16,7 +16,7 @@
class store_cart extends store {
public function __default() {
//session_destroy();
$this->data['cart'] = $_SESSION['cart'];
}
}

View file

@ -17,6 +17,8 @@ class store_cart_add extends store {
* @todo Add handling for an invalid product
*/
public function __default() {
var_dump($_SESSION);
if ($this->db->getField('SELECT COUNT(id) FROM products WHERE id = "' . $_REQUEST['id'] . '";') != 1) {
}