Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Improving core components and datasources

- Moves loader.php and environment.php into core subfolder.
- Renames config.php to config-sample.php and updates default settings.
- Modifies config defaults to play nice with database config settings.
- Changes datasource config structure to be more consistent between
  datasource types.
- Changes Load::Cache() and Load::DB() to more intelligently choose
  default based on configuration settings.
- Removes default definition "db" from Load::Datasource().
- Changes Load::Session() to ensure a config change to session type
  isn't applied mid-request.
- Adds exception_error_handler() function which can be used in places
  where exception handling is favorable over errors.
- Adds the local (object) storage of the last saved/loaded version of
  data in models.
- Removes manipulation of model objects by datasources.  Assignment of
  data is instead handled within the model logic.
- Fixes a bug where unset model fields would not get saved (as empty)
  to the database/datasources.
- Renames $model->assignVars() to setValues() and creates original as
  alias.  Code depending on assignVars() should be changed as the alias
  will eventually be removed.
- Adds $model->getValues() function which gets the current model data
  (based on schema fields).
- Changes ACL helper to accept a zero (root) context.
- Removes $usesuffix convention from all cache types.  This method of
  pseudo-clearing the cache was bad practice that could result in
  excessive memory usage, cache slams, etc.
- Improves connection checking in memcache helper.
- Adds two-level debugging to memcache helper.  Level 1 debug messages
  output the operation, key, and value performed.  Level 2 messages
  (turned on by setting $cache->debug = 2) output backtraces.
- Adds request cache helper, replacing arrcache datasource helper.
- Improves PDO database helper, including many various improvements to
  schema handling, caching, and optimized SQL generation and execution.
- Renames $pdo->address to $pdo->host.
- Improves connection checking in PDO helper.
- Fixes $pdo->getAssoc() for two-column result sets.
- Changes memcache datasource helper to generalized cache datasource
  helper.
- Adds "mode" option to database datasource for differentiating between
  inserts and updates.
- Improves handling of json-encoded "array" fields in database
  datasource.
  • Loading branch information...
commit a5cbb82184880104343ae17b56b97b0b97ecd355 1 parent 2485fc4
@thomshouse thomshouse authored
View
10 config.php → config-sample.php
@@ -12,13 +12,13 @@
// Database
$database['default'] = array(
- 'type' => 'adodb',
- 'adotype' => 'mysqli',
- 'address' => '127.0.0.1',
+ 'type' => 'pdo',
+ 'driver' => 'mysql',
+ 'host' => '127.0.0.1',
'username' => '',
'password' => '',
'database' => '',
- 'prefix' => 'esc_'
+ 'prefix' => 'esc_'
);
// Site config variables
@@ -28,7 +28,7 @@
// Routes
$static_routes = array(
'about' => array('controller' => 'page','id' => 2,'title' => 'About'),
- 'blog' => array('controller' => 'blog','id' => 1,'title' => 'Blog')
+ 'blog' => array('controller' => 'blog','id' => 1,'title' => 'Blog')
);
// Determines "active" plugins for running hooks
View
42 escher/defaults.php → escher/core/defaults.php
@@ -1,13 +1,5 @@
<?php
-// Convenience declarations
-$title = 'My Website';
-$subtitle = 'Powered by Escher';
-$wwwroot = '';
-
-// Data sources (read/write priority)
-$datasource_order['all'] = array('db');
-
// Router allows arguments sent to the root controller
$allow_root_args = TRUE;
@@ -37,7 +29,6 @@
);
// Maintenance mode defaults
-$maintenance_mode = FALSE;
$maintenance_message = 'This website is currently undergoing maintenance.';
$maintenance_root = array(
'controller'=>'errors',
@@ -71,14 +62,35 @@
array('admin','administrator','system')
);
-// Translate Cache datasource to default Cache
-if (!isset($cache)
- && !empty($datasource_cache_order['all'])
- && is_array($datasource_cache_order['all'])
-) {
- $cache = $datasource_cache_order['all'][0];
+// Set datasource order
+if (empty($datasource_order['all'])) {
+ $datasource_order['all'] = array();
+ foreach($datasource as $name => $ds) {
+ if (!empty($ds['helper']) && $ds['helper']=='database') {
+ $datasource_order['all'][] = $name;
+ }
+ }
+ unset($ds,$name);
+}
+
+// Set cache order
+if (empty($datasource_cache_order['all'])) {
+ $datasource_cache_order['all'] = array();
+ foreach($datasource as $name => $ds) {
+ if (!empty($ds['helper']) && $ds['helper']=='cache') {
+ $datasource_cache_order['all'][] = $name;
+ }
+ }
+ unset($ds,$name);
}
+// Add the request cache (static array)
+$datasource['request'] = array(
+ 'helper' => 'cache',
+ 'type' => 'request',
+);
+//array_unshift($datasource_cache_order['all'],'request');
+
// Document root and Escher path
$document_root = ESCHER_DOCUMENT_ROOT;
$escher_path = ESCHER_REAL_PATH;
View
7 escher/environment.php → escher/core/environment.php
@@ -22,3 +22,10 @@ function die_r($arr) {
unset($_GET['_PATH_INFO'],$GLOBALS['_REQUEST']['_PATH_INFO']);
$_SERVER['QUERY_STRING'] = http_build_query($_GET);
}
+
+// Error-to-exception handler
+if (!function_exists('exception_error_handler')) {
+ function exception_error_handler($errno, $errstr, $errfile, $errline ) {
+ throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
+ }
+}
View
98 escher/loader.php → escher/core/loader.php
@@ -154,11 +154,11 @@ public function Helper($helper,$type='default',$args=NULL) {
$newhelper = new $classname($args);
if (is_array($helper)) {
$newhelper->plugin = strtolower($helper[0]);
- $newhelper->type = strtolower($helper[1]);
+ $newhelper->helper = strtolower($helper[1]);
} else {
- $newhelper->type = strtolower($helper);
+ $newhelper->helper = strtolower($helper);
}
- $newhelper->flavor = strtolower($type);
+ $newhelper->type = strtolower($type);
return $newhelper;
} else {
return false;
@@ -194,8 +194,8 @@ public function PersistentHelper($name,$helper,$type='default',$args=NULL) {
if ($plugin!='core') {
$PHelpers[$helpername][$plugin][$type][$name]->plugin = $plugin;
}
- $PHelpers[$helpername][$plugin][$type][$name]->type = $helpername;
- $PHelpers[$helpername][$plugin][$type][$name]->flavor = $type;
+ $PHelpers[$helpername][$plugin][$type][$name]->helper = $helpername;
+ $PHelpers[$helpername][$plugin][$type][$name]->type = $type;
return $PHelpers[$helpername][$plugin][$type][$name];
} else {
return false;
@@ -263,14 +263,32 @@ public function ACL() {
* Shorthand for loading the default cache handler for the current Escher configuration.
* @return object|bool Returns the cache helper object, or false on failure.
*/
- public function Cache($name='default') {
+ public function Cache($name=NULL) {
$CFG = Load::Config();
- if (empty($CFG['cache'])) { return false; }
- $cache = $CFG['datasource'][$CFG['cache']];
- if (is_array($cache['type'])) {
- return Load::PersistentHelper($name,array($cache['type'][0],'cache'),$cache['type'][1],$cache['settings']);
+ if (is_null($name)) {
+ foreach($CFG['datasource_cache_order']['all'] as $n) {
+ if ($CFG['datasource'][$n]['helper']=='cache') {
+ $name = $n;
+ $args = $CFG['datasource'][$n];
+ break;
+ }
+ }
+ if (is_null($name)) { return FALSE; }
+ } elseif (array_key_exists($name,$CFG['datasource'])
+ && !empty($args['helper'])
+ && $args['helper']=='cache'
+ ) {
+ $args = $CFG['datasource'][$name];
+ } else {
+ return FALSE;
+ }
+ $type = $args['type'];
+ unset($args['helper'],$args['type']);
+ if (is_array($type)) {
+ return Load::PersistentHelper($name,array($type[0],'cache'),
+ $type[1],$args);
} else {
- return Load::PersistentHelper($name,'cache',$cache['type'],$cache['settings']);
+ return Load::PersistentHelper($name,'cache',$type,$args);
}
}
@@ -288,37 +306,51 @@ public function CFG() { return self::Config(); } // Shorthand
* Shorthand for loading the default database for the current Escher configuration.
* @return object|bool Returns the database helper object, or false on failure.
*/
- public function DB($name='default') {
+ public function DB($name=NULL) {
$CFG = Load::Config();
- $args = $CFG['database'][$name];
+ if (is_null($name)) {
+ foreach($CFG['datasource_order']['all'] as $n) {
+ if ($CFG['datasource'][$n]['helper']=='database') {
+ $name = $n;
+ $args = $CFG['datasource'][$n];
+ break;
+ }
+ }
+ if (is_null($name)) { return FALSE; }
+ } elseif (array_key_exists($name,$CFG['datasource'])
+ && !empty($args['helper'])
+ && $args['helper']=='database'
+ ) {
+ $args = $CFG['datasource'][$name];
+ } else {
+ return FALSE;
+ }
$type = $args['type'];
- unset($args['type']);
+ unset($args['helper'],$args['type']);
if (is_array($type)) {
- return Load::PersistentHelper($name,array($type[0],'database'),$type[1],$args);
+ return Load::PersistentHelper($name,array($type[0],'database'),
+ $type[1],$args);
} else {
return Load::PersistentHelper($name,'database',$type,$args);
}
}
/**
- * Shorthand for loading a Datasource object.
+ * Shorthand for loading a config-defined Datasource.
* @return object Returns the Datasource object.
*/
- public function Datasource($definition='db') {
+ public function Datasource($definition) {
$CFG = Load::Config();
- if ($definition=='db' && !isset($CFG['datasource']['db'])) {
- return Load::PersistentHelper('db','datasource','db');
- } elseif ($definition=='arrcache' && !isset($CFG['datasource']['arrcache'])) {
- return Load::PersistentHelper('arrcache','datasource','arrcache');
- } elseif (isset($CFG['datasource'][$definition]['type'])) {
- $type = $CFG['datasource'][$definition]['type'];
- $settings = !empty($CFG['datasource'][$definition]['settings'])
- ? $CFG['datasource'][$definition]['settings']
- : array();
- if (is_array($type)) {
- return Load::PersistentHelper($definition,array($type[0],'datasource'),$type[1],$settings);
+ if (isset($CFG['datasource'][$definition]['helper'])) {
+ $settings = $CFG['datasource'][$definition];
+ $helper = $settings['helper'];
+ unset($settings['helper']);
+ if (is_array($helper)) {
+ return Load::PersistentHelper($definition,
+ array($helper[0],'datasource'),$helper[1],$settings);
} else {
- return Load::PersistentHelper($definition,'datasource',$type,$settings);
+ return Load::PersistentHelper($definition,'datasource',
+ $helper,$settings);
}
}
return false;
@@ -451,8 +483,12 @@ public function Router($path=NULL) {
* @return object|bool Returns the session helper object, or false on failure.
*/
public function Session() {
- $CFG = Load::Config();
- $args = $CFG['session'];
+ static $session;
+ if (is_null($session)) {
+ $CFG = Load::Config();
+ $session = $CFG['session'];
+ }
+ $args = $session;
$type = $args['type'];
unset($args['type']);
self::$internalCall = true;
View
58 escher/core/model/model.php
@@ -5,7 +5,10 @@
protected $_schemaKeys = array();
protected $_schemaTriggers = array();
protected $_outputType = 'php';
+ protected $_new = TRUE;
+ protected $_savedValues = array();
+ // Used to keep track of parsed form inputs for new models
protected static $_parsedNew = array();
public function __construct($key=NULL) {
@@ -47,7 +50,9 @@ function loadCached($key) {
foreach($sources as $s) {
$ds = Load::Datasource($s);
if ($result = $ds->get($this,$key)) {
- // Assign class vars (metadata, content, etc.) and return
+ $this->assignVars($result);
+ $this->_savedValues = (array)$result;
+ $this->_new = FALSE;
return true;
}
}
@@ -74,6 +79,8 @@ function loadUncached($key) {
$this->_datasource = $s;
// Assign class vars (metadata, content, etc.)
$this->assignVars($result);
+ $this->_savedValues = (array)$result;
+ $this->_new = FALSE;
return true;
}
}
@@ -88,16 +95,39 @@ public function save() {
$this->_runTriggers('modify');
}
+ $values = array();
+ foreach($this->_schemaFields as $k => $p) {
+ if (isset($this->$k)) {
+ $values[$k] = $this->$k;
+ } elseif (array_key_exists($k,$this->_savedValues)) {
+ $values[$k] = '';
+ }
+ }
+
+ // Set datasource options
+ $options = array(
+ 'mode' => $this->_new
+ ? 'insert'
+ : 'update'
+ );
+
$sources = $this->_getDatasources();
// Iterate through the datasources and save
// Note: Only new objects should have to iterate
foreach($sources as $s) {
$ds = Load::Datasource($s);
- if ($ds->set($this)) {
+ if ($id = $ds->set($this->_m(),$values,$options)) {
+ $this->_new = FALSE;
+ if ($this->_primaryKey() && !$this->id()) {
+ $this->setValues(array(
+ $this->_primaryKey() => $id,
+ ));
+ }
if (!isset($this->_datasource)) {
$this->_datasource = $s;
}
- $this->cache();
+ $this->expire();
+ $this->_savedValues = $values;
return true;
}
}
@@ -214,13 +244,8 @@ protected function _getCacheDatasources() {
$CFG = Load::Config();
if (isset($CFG['datasource_cache_order'][$this->_m()])) {
$sources = $CFG['datasource_cache_order'][$this->_m()];
- } elseif (isset($CFG['datasource_cache_order']['all'])) {
- $sources = $CFG['datasource_cache_order']['all'];
} else {
- $sources = array('arrcache');
- }
- if (!in_array('arrcache',$sources)) {
- array_unshift($sources,'arrcache');
+ $sources = $CFG['datasource_cache_order']['all'];
}
return $sources;
}
@@ -255,7 +280,9 @@ function find($conditions=array(),$options=array()) {
}
// Override assignVars to protect class variables
- public function assignVars($vars) {
+ public function assignVars($vars) { return $this->setValues($vars); }
+
+ public function setValues($vars) {
if (!is_array($vars) || array_values($vars)==$vars) {
return false;
}
@@ -269,6 +296,16 @@ public function assignVars($vars) {
return true;
}
+ public function getValues() {
+ $values = array();
+ foreach($this->_schemaFields as $k => $props) {
+ if (isset($this->$k)) {
+ $values[$k] = $this->$k;
+ }
+ }
+ return $values;
+ }
+
function id() {
return $this->{$this->_primaryKey()};
}
@@ -298,6 +335,7 @@ function _primaryKey() {
case '_schemaFields':
case '_schemaKeys':
case '_schemaTriggers':
+ case '_savedValues':
return isset($this->$name)
? $this->$name
: NULL;
View
35 escher/helpers/acl/helper.acl.php
@@ -269,27 +269,28 @@ protected function setRule($entity,$rule,$resource,$action='all',$context=NULL,$
// Sanitize $action
if (!is_string($action)) return false;
// Sanitize $context
- if (is_null($context)) {
- $router = Load::Router();
- $context = $router->getContext();
- } elseif(is_integer($context)) {
- $router = Load::Router();
- $context = $router->getPathById($context,FALSE);
- $router = Load::Router($context);
- $context = $router->getContext();
- } elseif (is_string($context)) {
- $router = Load::Router($context);
- $context = $router->getContext();
- } elseif (!is_object($context)) {
- return false;
- }
- if (!$context->id) {
- return false;
+ if ($context!==0) {
+ if (is_null($context)) {
+ $router = Load::Router();
+ $context = $router->getContext();
+ } elseif(is_integer($context)) {
+ $router = Load::Router();
+ $context = $router->getPathById($context,FALSE);
+ $router = Load::Router($context);
+ $context = $router->getContext();
+ } elseif (is_string($context)) {
+ $router = Load::Router($context);
+ $context = $router->getContext();
+ } elseif (!is_object($context)) {
+ return false;
+ }
+ if (!$context->id()) { return false; }
+ $context = $context->id();
}
$model = Load::Model('acl_rule');
$conditions = array(
'resource_type' => $resource[0],'resource_id' => $resource[1],
- 'action' => $action, 'context' => $context->id, 'inheritable' => $inheritable,
+ 'action' => $action, 'context' => $context, 'inheritable' => $inheritable,
'entity_type' => $entity[0], 'entity_id' => $entity[1],'priority' => (int)$priority);
$options = array('limit' => 0,'select' => 'acl_rule_id','fetch' => 'col');
$current_rules = $model->find($conditions,$options);
View
45 escher/helpers/cache/helper.cache.php
@@ -15,56 +15,37 @@
*/
abstract class Helper_cache extends Helper {
protected $prefix;
- protected $suffix;
protected $host;
protected $port;
abstract function connect();
- abstract function get($key, $usesuffix=TRUE);
- abstract function set($key, $value=array(), $expire=0, $compress=0, $usesuffix=TRUE);
- abstract function add($key, $value=array(), $expire=0, $compress=0, $usesuffix=TRUE);
- abstract function replace($key, $value=array(), $expire=0, $compress=0, $usesuffix=TRUE);
+ abstract function get($key);
+ abstract function set($key, $value=array(), $expire=0);
+ abstract function add($key, $value=array(), $expire=0);
+ abstract function replace($key, $value=array(), $expire=0);
abstract function flush();
- abstract function expire($key, $timeout=0, $usesuffix=TRUE);
- abstract function increment($key, $count=1, $usesuffix=FALSE);
- abstract function decrement($key, $count=1, $usesuffix=FALSE);
+ abstract function expire($key, $timeout=0);
+ abstract function increment($key, $count=1);
+ abstract function decrement($key, $count=1);
abstract function isConnected();
function __construct($args) {
parent::__construct($args);
if (empty($this->prefix)) {
$CFG = Load::Config();
- $this->prefix = md5($CFG['wwwroot']);
+ $this->prefix = isset($CFG['instance'])
+ ? $CFG['instance']
+ : md5($CFG['wwwroot']);
}
}
/**
- * Set the keys prefix and suffix
+ * Prepends the key with the prefix
*
* @param string $key
- * @param bool $usesuffix
* @return string
*/
- final public function k($key, $usesuffix=TRUE) {
- $k = $this->prefix.':'.$key;
- if ($usesuffix && !empty($this->suffix)) {
- $k .= '('.$this->suffix.')';
- }
- return $k;
- }
-
- /**
- * Initalizes the cache key suffix
- *
- * @return void
- */
- function getSuffix() {
- $CFG = Load::Config();
- $suffix = $this->get('cache.internal.keysuffix', FALSE);
- if(empty($suffix)) {
- $suffix = date('ymdhisa');
- $this->set('cache.internal.keysuffix',$suffix,0, 0, FALSE);
- }
- $this->suffix = $suffix;
+ final public function k($key) {
+ return $this->prefix.':'.$key;
}
}
View
179 escher/helpers/cache/memcache/helper.cache.memcache.php
@@ -1,179 +0,0 @@
-<?php
-
-/**
- * Helper_cache_memcache.php
- *
- * Cache (Memcache) Helper class
- * @author Andrew Detwiler <adetwiler@adidamnetworks.com>
- * @version 1.0
- * @package Escher
- */
-
-/**
- * Cache Memcache Helper class
- * @package Escher
- */
-class Helper_cache_memcache extends Helper_cache {
- var $memcache;
-
- /**
- * Connects to the memcached server
- * @return void
- */
- function connect() {
- if (!$this->isConnected()) {
- $this->memcache = new Memcache;
- @$this->memcache->connect($this->host,$this->port);
- $this->getSuffix();
- }
- }
-
- /**
- * Returns the value stored in the memory by it's key
- *
- * @param string $key
- * @param bool $usesuffix
- * @return mix
- */
- function get($key, $usesuffix=TRUE) {
- $this->connect();
- if (is_array($key)) {
- $arr = array();
- foreach ($key as $k) {
- $ks = $this->k($k, $usesuffix);
- $arr[$k] = unserialize($this->memcache->get($ks));
- }
- return $arr;
- }
- $key = $this->k($key, $usesuffix);
- return unserialize($this->memcache->get($key));
- }
-
- /**
- * Store the value in the memcache memory (overwrite if key exists)
- *
- * @param string $key
- * @param mix $value
- * @param int $expire (seconds before item expires)
- * @param bool $compress
- * @param bool $usesuffix
- * @return bool
- */
- function set($key, $value=array(), $expire=0, $compress=0, $usesuffix=TRUE) {
- $this->connect();
- $key = $this->k($key, $usesuffix);
- return $this->memcache->set($key, serialize($value), $compress?MEMCACHE_COMPRESSED:null, $expire);
- }
-
- /**
- * Set the value in memcache if the value does not exist; returns FALSE if value exists
- *
- * @param sting $key
- * @param mix $value
- * @param int $expire
- * @param bool $compress
- * @param bool $usesuffix
- * @return bool
- */
- function add($key, $value=array(), $expire=0, $compress=0, $usesuffix=TRUE) {
- $this->connect();
- $key = $this->k($key, $usesuffix);
- return $this->memcache->add($key, serialize($value), $compress?MEMCACHE_COMPRESSED:null, $expire);
- }
-
- /**
- * Replace an existing value
- *
- * @param string $key
- * @param mix $value
- * @param int $expire
- * @param bool $compress
- * @param bool $usesuffix
- * @return bool
- */
- function replace($key, $value=array(), $expire=0, $compress=0, $usesuffix=TRUE) {
- $this->connect();
- $key = $this->k($key, $usesuffix);
- return $this->memcache->replace($key, $value, $compress?MEMCACHE_COMPRESSED:null, $expire);
- }
-
- /**
- * Clear the cache
- *
- * @return void
- */
- function flush() {
- $this->connect();
- $this->memcache->flush();
- }
-
- /**
- * Expire a record or set a timeout
- *
- * @param string $key
- * @param int $timeout
- * @param bool $usesuffix
- * @return bool
- */
- function expire($key, $timeout=0, $usesuffix=TRUE) {
- $this->connect();
- if (is_array($key)) {
- foreach ($key as $k) {
- $k = $this->k($k, $usesuffix);
- if(!$this->memcache->delete($k, $timeout)) {
- return false;
- }
- }
- return true;
- }
- $key = $this->k($key, $usesuffix);
- return $this->memcache->delete($key, $timeout);
- }
-
- /**
- * Delete a record immediately
- *
- * @param string $key
- * @param bool $usesuffix
- * @return bool
- */
- function delete($key, $usesuffix=TRUE) {
- return $this->expire($key,0,$usesuffix);
- }
-
- /**
- * Increment an existing integer value
- *
- * @param string $key
- * @param mix $value
- * @param bool $usesuffix
- * @return bool
- */
- function increment($key, $count=1, $usesuffix=FALSE) {
- $this->connect();
- $key = $this->k($key, $usesuffix);
- return $this->memcache->increment($key, $count);
- }
-
- /**
- * Decrement an existing value
- *
- * @param string $key
- * @param mix $value
- * @param bool $usesuffix
- * @return bool
- */
- function decrement($key, $count=1, $usesuffix=FALSE) {
- $this->connect();
- $key = $this->k($key, $usesuffix);
- return $this->memcache->decrement($key, $count);
- }
-
- /**
- * Checks if memcache object is null
- * @return bool
- */
- function isConnected() {
- return !is_null($this->memcache);
- }
-}
View
213 escher/helpers/cache/memcached/helper.cache.memcached.php
@@ -0,0 +1,213 @@
+<?php
+
+/**
+ * Helper_cache_memcache.php
+ *
+ * Memcache Cache Helper class
+ * @author Andrew Detwiler <adetwiler@adidamnetworks.com>
+ * @version 1.0
+ * @package Escher
+ */
+
+/**
+ * Memcached Cache Helper class
+ * @package Escher
+ */
+class Helper_cache_memcached extends Helper_cache {
+ protected $memcache;
+ var $debug = 0;
+
+ /**
+ * Connects to the memcached server
+ * @return void
+ */
+ function connect() {
+ if (is_null($this->memcache)) {
+ $this->memcache = new Memcache;
+ set_error_handler('exception_error_handler');
+ try {
+ $this->memcache->connect($this->host,$this->port);
+ } catch (Exception $e) {
+ $this->memcache = FALSE;
+ }
+ restore_error_handler();
+ if ($this->memcache===FALSE) {
+ return FALSE;
+ }
+ } elseif ($this->memcache===FALSE) {
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ /**
+ * Returns the value stored in the memory by it's key
+ *
+ * @param string $key
+ * @return mix
+ */
+ function get($key) {
+ if (!$this->connect()) { return FALSE; }
+ if (is_array($key)) {
+ $arr = array();
+ foreach ($key as $k) {
+ $pk = $this->k($k);
+ $arr[$k] = unserialize($this->memcache->get($pk));
+ $this->debug('GET',$pk);
+ }
+ return $arr;
+ }
+ $key = $this->k($key);
+ $this->debug('GET',$key);
+ return unserialize($this->memcache->get($key));
+ }
+
+ /**
+ * Store the value in the memcache memory (overwrite if key exists)
+ *
+ * @param string $key
+ * @param mix $value
+ * @param int $expire (seconds before item expires)
+ * @param bool $compress
+ * @return bool
+ */
+ function set($key, $value=array(), $expire=0, $compress=0) {
+ if (!$this->connect()) { return FALSE; }
+ $key = $this->k($key);
+ $this->debug('SET',$key,$value,$expire);
+ return $this->memcache->set($key, serialize($value), $compress?MEMCACHE_COMPRESSED:null, $expire);
+ }
+
+ /**
+ * Set the value in memcache if the value does not exist; returns FALSE if value exists
+ *
+ * @param sting $key
+ * @param mix $value
+ * @param int $expire
+ * @param bool $compress
+ * @return bool
+ */
+ function add($key, $value=array(), $expire=0, $compress=0) {
+ if (!$this->connect()) { return FALSE; }
+ $key = $this->k($key);
+ $this->debug('ADD',$key,$value,$expire);
+ return $this->memcache->add($key, serialize($value), $compress?MEMCACHE_COMPRESSED:null, $expire);
+ }
+
+ /**
+ * Replace an existing value
+ *
+ * @param string $key
+ * @param mix $value
+ * @param int $expire
+ * @param bool $compress
+ * @return bool
+ */
+ function replace($key, $value=array(), $expire=0, $compress=0) {
+ if (!$this->connect()) { return FALSE; }
+ $key = $this->k($key);
+ $this->debug('REPLACE',$key,$value,$expire);
+ return $this->memcache->replace($key, $value, $compress?MEMCACHE_COMPRESSED:null, $expire);
+ }
+
+ /**
+ * Clear the cache
+ *
+ * @return void
+ */
+ function flush() {
+ if (!$this->connect()) { return FALSE; }
+ $this->debug('FLUSH');
+ $this->memcache->flush();
+ }
+
+ /**
+ * Expire a record or set a timeout
+ *
+ * @param string $key
+ * @param int $timeout
+ * @return bool
+ */
+ function expire($key, $timeout=0) {
+ if (!$this->connect()) { return FALSE; }
+ if (is_array($key)) {
+ $result = TRUE;
+ foreach ($key as $k) {
+ $k = $this->k($k);
+ if(!$this->memcache->delete($k, $timeout)) {
+ $result = FALSE;
+ }
+ }
+ return $result;
+ }
+ $key = $this->k($key);
+ $this->debug('EXPIRE',$key,NULL,$timeout);
+ return $this->memcache->delete($key, $timeout);
+ }
+
+ /**
+ * Delete a record immediately
+ *
+ * @param string $key
+ * @return bool
+ */
+ function delete($key) {
+ return $this->expire($key,0);
+ }
+
+ /**
+ * Increment an existing integer value
+ *
+ * @param string $key
+ * @param mix $value
+ * @return bool
+ */
+ function increment($key, $count=1) {
+ if (!$this->connect()) { return FALSE; }
+ $key = $this->k($key);
+ $this->debug('INCREMENT',$key,$count);
+ return $this->memcache->increment($key, $count);
+ }
+
+ /**
+ * Decrement an existing value
+ *
+ * @param string $key
+ * @param mix $value
+ * @return bool
+ */
+ function decrement($key, $count=1) {
+ if (!$this->connect()) { return FALSE; }
+ $key = $this->k($key);
+ $this->debug('DECREMENT',$key,$count);
+ return $this->memcache->decrement($key, $count);
+ }
+
+ /**
+ * Checks if memcache object is null
+ * @return bool
+ */
+ function isConnected() {
+ return (bool)$this->memcache;
+ }
+
+ /**
+ * Debug reporting
+ *
+ * @param string $command
+ * @param string $key
+ * @param mix $value
+ * @param int $until
+ */
+ protected function debug($command,$key=NULL,$value=NULL,$until=NULL) {
+ if (!$this->debug) { return; }
+ echo "<hr />(memcache): $command";
+ if (!is_null($key)) { echo " `$key`"; }
+ if (!is_null($value)) { echo " = '".serialize($value)."'"; }
+ if (!is_null($until)) { echo " UNTIL $until"; }
+ echo '<hr />';
+ if (is_int($this->debug) && $this->debug>1) {
+ echo '<pre>'; debug_print_backtrace(); echo '</pre>';
+ }
+ }
+}
View
158 escher/helpers/cache/request/helper.cache.request.php
@@ -0,0 +1,158 @@
+<?php
+
+/**
+ * Helper_cache_request.php
+ *
+ * Request Cache Helper class
+ * @author Thom Stricklin <thomshouse@gmail.com>
+ * @version 1.0
+ * @package Escher
+ */
+
+/**
+ * Request Cache Helper class
+ * @package Escher
+ */
+class Helper_cache_request extends Helper_cache {
+ protected static $cache = array();
+
+ /**
+ * Null function (connect to the array, yay!)
+ * @return void
+ */
+ function connect() { return TRUE; }
+
+ /**
+ * Returns the value stored in the memory by its key
+ *
+ * @param string $key
+ * @return mix
+ */
+ function get($key) {
+ if (is_array($key)) {
+ $arr = array();
+ foreach ($key as $k) {
+ $arr[$k] = $this->get($k);
+ }
+ return $arr;
+ }
+ if (array_key_exists($key,self::$cache)) {
+ return self::$cache[$key];
+ } else {
+ return FALSE;
+ }
+ }
+
+ /**
+ * Store the value in the memcache memory (overwrite if key exists)
+ *
+ * @param string $key
+ * @param mix $value
+ * @param int $expire (seconds before item expires)
+ * @return bool
+ */
+ function set($key, $value=array(), $expire=0) {
+ self::$cache[$key] = $value;
+ return TRUE;
+ }
+
+ /**
+ * Set the value in memcache if the value does not exist; returns FALSE if value exists
+ *
+ * @param sting $key
+ * @param mix $value
+ * @param int $expire
+ * @return bool
+ */
+ function add($key, $value=array(), $expire=0) {
+ if (array_key_exists($key,self::$cache)) { return FALSE; }
+ self::$cache[$key] = $value;
+ return TRUE;
+ }
+
+ /**
+ * Replace an existing value
+ *
+ * @param string $key
+ * @param mix $value
+ * @param int $expire
+ * @return bool
+ */
+ function replace($key, $value=array(), $expire=0, $compress=0, $usesuffix=TRUE) {
+ if (!array_key_exists($key,self::$cache)) { return FALSE; }
+ self::$cache[$key] = $value;
+ return TRUE;
+ }
+
+ /**
+ * Clear the cache
+ *
+ * @return void
+ */
+ function flush() {
+ self::$cache = array();
+ }
+
+ /**
+ * Expire a record or set a timeout
+ *
+ * @param string $key
+ * @param int $timeout
+ * @return bool
+ */
+ function expire($key, $timeout=0) {
+ if ($timeout!=0) { return FALSE; }
+ if (is_array($key)) {
+ foreach ($key as $k) {
+ unset(self::$cache[$k]);
+ }
+ return TRUE;
+ }
+ if (!array_key_exists($key,self::$cache)) { return FALSE; }
+ unset(self::$cache[$key]);
+ return TRUE;
+ }
+
+ /**
+ * Delete a record immediately
+ *
+ * @param string $key
+ * @param bool $usesuffix
+ * @return bool
+ */
+ function delete($key, $usesuffix=TRUE) {
+ return $this->expire($key,0,$usesuffix);
+ }
+
+ /**
+ * Increment an existing integer value
+ *
+ * @param string $key
+ * @param mix $value
+ * @return bool
+ */
+ function increment($key, $count=1) {
+ if (!array_key_exists($key,self::$cache)) { return FALSE; }
+ self::$cache[$key] += $count;
+ return TRUE;
+ }
+
+ /**
+ * Decrement an existing value
+ *
+ * @param string $key
+ * @param mix $value
+ * @return bool
+ */
+ function decrement($key, $count=1, $usesuffix=FALSE) {
+ if (!array_key_exists($key,self::$cache)) { return FALSE; }
+ self::$cache[$key] -= $count;
+ return TRUE;
+ }
+
+ /**
+ * Checks to see if we're connected to the static array
+ * @return bool
+ */
+ function isConnected() { return TRUE; }
+}
View
14 escher/helpers/database/pdo/drivers/driver.mysql.php
@@ -13,7 +13,7 @@ function __construct($pdo) {
function getSchema($table) {
// Save the name of the metadata table. We'll reuse this
$metadataTable = $this->pdo->t($table.'_metadata',FALSE);
-
+
// Get the column info from information_schema
$result = $this->pdo->getAll(
'SELECT * FROM ' . $this->pdo->n('information_schema.COLUMNS')
@@ -30,7 +30,9 @@ function getSchema($table) {
// Build the fields array
$fields = array();
+ $tables = array();
foreach($result as $r) {
+ $tables[] = $r['TABLE_NAME'];
if(array_key_exists($r['COLUMN_NAME'],$fields)) { continue; }
$field = array(
'type' => $r['DATA_TYPE'],
@@ -56,7 +58,11 @@ function getSchema($table) {
// Get the key info from information_schema
$keys = array();
- foreach(array($table,$table.'_metadata',$table.'_content') as $t) {
+ $tables = array_intersect(
+ array($table,$table.'_metadata',$table.'_content'),
+ $tables
+ );
+ foreach($tables as $t) {
$kresult = $this->pdo->getAll('SHOW KEYS FROM ' . $this->pdo->t($t));
foreach($kresult as $r) {
$kname = $r['Key_name'];
@@ -265,6 +271,10 @@ function setSchema($table,$schema,$dbSchema,$complete=FALSE) {
$sql = "CREATE TABLE IF NOT EXISTS {$this->pdo->n($part)} (";
$fieldsSql = array();
foreach($primaryFields as $name => $f) {
+ // Only the primary partition should have an auto-increment
+ if ($part!=$fieldsTable) {
+ unset($f['auto_increment']);
+ }
$fs = $this->pdo->n($name).' '.$this->_fieldSQL($f);
$fieldsSql[] = $fs;
}
View
71 escher/helpers/database/pdo/helper.database.pdo.php
@@ -1,9 +1,9 @@
<?php
class Helper_database_pdo extends Helper_database {
- protected $schemas = array();
+ protected static $schemas = array();
protected $driver = 'mysql';
- protected $address = '127.0.0.1';
+ protected $host = '127.0.0.1';
protected $database;
protected $username;
protected $password;
@@ -19,12 +19,13 @@ function connect() {
if (!$this->isConnected()) {
try {
$this->db = new PDO(
- "{$this->driver}:host={$this->address};dbname={$this->database}",
+ "{$this->driver}:host={$this->host};dbname={$this->database}",
$this->username,$this->password);
} catch(PDOException $e) {
$this->db = NULL;
}
}
+ return !is_null($this->db);
}
function disconnect() {
@@ -32,7 +33,7 @@ function disconnect() {
}
function execute($sql,$vars=NULL) {
- $this->connect();
+ if (!$this->connect()) { return FALSE; }
$this->statement = $this->db->prepare($sql);
$result = $this->statement->execute($vars);
$this->debug($sql,$vars,$this->statement);
@@ -101,7 +102,7 @@ function insertOrReplace($table,$data,$keys=NULL,$ignore=FALSE,$replace=FALSE) {
$sql = 'INSERT'.($ignore ? ' IGNORE':'').' INTO '.$this->t($table).' ('.implode(',',$keys_sql).') VALUES '.implode(',',$values);
}
- $this->connect();
+ if (!$this->connect()) { return FALSE; }
$this->statement = $this->db->prepare($sql);
$result = $this->statement->execute($values);
$this->debug($sql,$values,$this->statement);
@@ -113,21 +114,17 @@ function replace($table,$data,$keys=NULL) {
}
function affectedRows() {
- if (!$this->isConnected()) {
- return false;
- }
+ if (!$this->isConnected()) { return FALSE; }
return $this->statement->rowCount();
}
function lastID() {
- if (!$this->isConnected()) {
- return false;
- }
+ if (!$this->isConnected()) { return FALSE; }
return $this->db->lastInsertId();
}
function getAll($sql,$vars=NULL) {
- $this->connect();
+ if (!$this->connect()) { return FALSE; }
$this->statement = $this->db->prepare($sql);
$this->statement->execute($vars);
$this->debug($sql,$vars,$this->statement);
@@ -135,7 +132,7 @@ function getAll($sql,$vars=NULL) {
}
function getAssoc($sql,$vars=NULL,$force_array=FALSE) {
- $this->connect();
+ if (!$this->connect()) { return FALSE; }
$this->statement = $this->db->prepare($sql);
$this->statement->execute($vars);
$this->debug($sql,$vars,$this->statement);
@@ -143,7 +140,7 @@ function getAssoc($sql,$vars=NULL,$force_array=FALSE) {
return array();
}
$result = array();
- if (!$force_array && sizeof($dbresult[0])==1) {
+ if (!$force_array && sizeof($dbresult[0])==2) {
foreach($dbresult as $r) {
$rkey = array_shift($r);
$result[$rkey] = array_shift($r);
@@ -158,7 +155,7 @@ function getAssoc($sql,$vars=NULL,$force_array=FALSE) {
}
function getCol($sql,$vars=NULL) {
- $this->connect();
+ if (!$this->connect()) { return FALSE; }
$this->statement = $this->db->prepare($sql);
$this->statement->execute($vars);
$this->debug($sql,$vars,$this->statement);
@@ -170,7 +167,7 @@ function getFieldNames($table) {
}
function getOne($sql,$vars=NULL) {
- $this->connect();
+ if (!$this->connect()) { return FALSE; }
$this->statement = $this->db->prepare($sql);
$this->statement->execute($vars);
$this->debug($sql,$vars,$this->statement);
@@ -178,7 +175,7 @@ function getOne($sql,$vars=NULL) {
}
function getRow($sql,$vars=NULL) {
- $this->connect();
+ if (!$this->connect()) { return FALSE; }
$this->statement = $this->db->prepare($sql);
$this->statement->execute($vars);
$this->debug($sql,$vars,$this->statement);
@@ -186,9 +183,7 @@ function getRow($sql,$vars=NULL) {
}
function getAutoId($sql=NULL,$vars=NULL) {
- if (!$this->isConnected()) {
- return false;
- }
+ if (!$this->isConnected()) { return FALSE; }
return $this->db->lastInsertId();
}
@@ -213,7 +208,7 @@ function n($str) {
function q($str) {
// PDO doesn't handle NULLs properly
if (is_null($str)) { return "NULL"; }
- $this->connect();
+ if (!$this->connect()) { return FALSE; }
return $this->db->quote($str);
}
@@ -251,21 +246,44 @@ function time($ts) {
}
function getSchema($table) {
+ if (array_key_exists($table,self::$schemas)) {
+ return self::$schemas[$table];
+ }
if ($cache = Load::Cache()) {
- if ($schema = $cache->get("PDO:{$this->driver}>SCHEMA>$table")) {
+ if ($schema = $cache->get("PDO:{$this->driver}:tableSchema:$table")) {
return $schema;
}
}
if (!$driver = $this->getDriver()) { return false; }
if (!$schema = $driver->getSchema($table)) { return false; }
- $this->schemas[$table] = $schema;
+ self::$schemas[$table] = $schema;
+ if ($cache) {
+ $cache->set("PDO:{$this->driver}:tableSchema:$table",$schema);
+ }
return $schema;
}
function setSchema($table,$schema,$complete=FALSE) {
- $dbSchema = $this->getSchema($table);
+ $oldSchema = $this->getSchema($table);
+ $newSchema = $schema;
+ // Skip the set if schema hasn't changed
+ ksort($oldSchema['fields']);
+ ksort($newSchema['fields']);
+ ksort($oldSchema['keys']);
+ ksort($newSchema['keys']);
+ if (md5(json_encode($oldSchema['fields']))
+ == md5(json_encode($newSchema['fields']))
+ && md5(json_encode($oldSchema['keys']))
+ == md5(json_encode($newSchema['keys']))
+ ) {
+ return array('fields' => array(), 'keys' => array());
+ }
if (!$driver = $this->getDriver()) { return false; }
- return $driver->setSchema($table,$schema,$dbSchema,$complete);
+ self::$schemas[$table] = $schema;
+ if ($cache = Load::Cache()) {
+ $cache->set("PDO:{$this->driver}:tableSchema:$table",$schema);
+ }
+ return $driver->setSchema($table,$schema,$oldSchema,$complete);
}
protected function debug($sql,$vars,$statement) {
@@ -279,6 +297,9 @@ protected function debug($sql,$vars,$statement) {
$sql = preg_replace('/\?/',$rep,$sql,1);
}
echo "<hr />({$this->driver}): $sql<hr />";
+ if (is_int($this->debug) && $this->debug>1) {
+ echo '<pre>'; debug_print_backtrace(); echo '</pre>';
+ }
$error = $statement->errorInfo();
if (!empty($error[2])) {
echo "<div>{$error[2]}</div>";
View
98 escher/helpers/datasource/arrcache/helper.datasource.arrcache.php
@@ -1,98 +0,0 @@
-<?php
-
-/**
- * Helper_datasource_arrcache.php
- *
- * Datasource (ArrCache) Helper class
- * @author Thom Stricklin <code@thomshouse.net>
- * @version 1.0
- * @package Escher
- */
-
-/**
- * Datasource ArrCache Helper class
- * Note: The ArrCache uses a local array (attached to this persistent helper) to cache data in simple key-value pairs
- * @package Escher
- */
-class Helper_datasource_arrcache extends Helper_datasource {
- protected $cache = array();
- function set($model,$attrs=array(),$values=NULL) {
- $sets = array();
- if (is_object($model)) {
- // If object provided, set data to the object
- $m = $model->_m();
- $data = $model;
- $attrs = get_object_vars($model);
- } elseif (is_string($model)) {
- // Else set data to an associative array
- $m = $model;
- if (array_keys($attrs)==array_keys(array_values($attrs))) {
- $attrs = array_combine($attrs,$values);
- }
- $data = $attrs;
- } else { return false; }
- // Cache all unique keys
- if (is_object($model)) {
- foreach($model->_schemaKeys as $c) {
- if (!in_array($c['type'],array('unique','primary'))) {
- continue;
- }
- ksort($c['fields']);
- $keyset = array();
- foreach($c['fields'] as $k) {
- if (!isset($attrs[$k])) {
- continue 2;
- }
- $keyset[] = "{$k}={$attrs[$k]}";
- }
- $keyset = implode('&',$keyset);
- $this->cache[$m.'?'.$keyset] = $data;
- }
- }
- return true;
- }
- function get($model,$conditions=array(),$limit=1,$options=array()) {
- if (is_object($model)) {
- $m = $model->_m();
- } elseif (is_string($model)) {
- $m = $model;
- } else { return false; }
- $name = $m.'?';
- if (is_array($conditions)) {
- ksort($conditions);
- $c = array();
- foreach($conditions as $k => $v) {
- $c[] = $k.'='.$v;
- }
- $name .= implode('&',$c);
- } else { return false; }
- if (!array_key_exists($name,$this->cache)) {
- return false;
- }
- $result = $this->cache[$name];
- if (is_object($model) && is_object($result) && get_class($model)==get_class($result)) {
- $model->assignVars(get_object_vars($result));
- }
- return $result;
- }
-
- function delete($model) {
- if (!is_object($model)) { return false; }
- $m = $model->_m();
-
- // Unset all unique keys
- foreach($model->_schemaKeys as $c) {
- ksort($c['fields']);
- $keyset = array();
- foreach($c['fields'] as $k) {
- if (!isset($attrs[$k])) {
- continue 2;
- }
- $keyset[] = "{$k}={$attrs[$k]}";
- }
- $keyset = implode('&',$keyset);
- unset($this->cache[$model->_m().'?'.$keyset]);
- }
- return true;
- }
-}
View
50 ...atasource/memcache/helper.datasource.memcache.php → ...pers/datasource/cache/helper.datasource.cache.php
@@ -1,40 +1,40 @@
<?php
/**
- * Helper_datasource_memcache.php
+ * Helper_datasource_cache.php
*
- * Datasource (ArrCache) Helper class
+ * Cache Datasource Helper class
* @author Thom Stricklin <code@thomshouse.net>
* @version 1.0
* @package Escher
*/
/**
- * Datasource Memcache Helper class
+ * Datasource Cache Helper class
* @package Escher
*/
-class Helper_datasource_memcache extends Helper_datasource {
- protected $memcache;
+class Helper_datasource_cache extends Helper_datasource {
+ protected $cache;
function __construct($args) {
parent::__construct($args);
- $this->memcache = Load::Helper('cache','memcache',$args);
+ $type = $args['type'];
+ unset($args['type']);
+ $this->cache = Load::Helper('cache',$type,$args);
}
- function set($model,$attrs=array(),$values=NULL) {
+ function set($model,$data=array(),$values=NULL) {
$sets = array();
if (is_object($model)) {
// If object provided, set data to the object
$m = $model->_m();
- $data = $model;
- $attrs = get_object_vars($model);
+ $data = get_object_vars($model);
} elseif (is_string($model)) {
// Else set data to an associative array
$m = $model;
- if (array_keys($attrs)==array_keys(array_values($attrs))) {
- $attrs = array_combine($attrs,$values);
+ if (array_keys($data)==array_keys(array_values($data))) {
+ $data = array_combine($data,$values);
}
- $data = $attrs;
} else { return false; }
// Cache all unique keys
if (is_object($model)) {
@@ -42,13 +42,13 @@ function set($model,$attrs=array(),$values=NULL) {
ksort($c['fields']);
$keyset = array();
foreach($c['fields'] as $k) {
- if (!isset($attrs[$k])) {
+ if (!isset($data[$k])) {
continue 2;
}
- $keyset[] = "{$k}={$attrs[$k]}";
+ $keyset[] = "{$k}={$data[$k]}";
}
$keyset = implode('&',$keyset);
- $this->memcache->set($m.'?'.$keyset,$data);
+ $this->cache->set($m.'?'.$keyset,$data);
}
}
return true;
@@ -68,12 +68,9 @@ function get(&$model,$conditions=array(),$limit=1,$options=array()) {
}
$name .= implode('&',$c);
} else { return false; }
- if (!$result = $this->memcache->get($name)) {
+ if (!$result = $this->cache->get($name)) {
return false;
}
- if (is_object($model) && is_object($result) && get_class($model)==get_class($result)) {
- $model->assignVars(get_object_vars($result));
- }
return $result;
}
@@ -91,7 +88,20 @@ function delete($model) {
$keyset[] = "{$k}={$model->$k}";
}
$keyset = implode('&',$keyset);
- $this->memcache->expire($model->_m().'?'.$keyset);
+ $this->cache->expire($model->_m().'?'.$keyset);
+ }
+ // Rinse and repeat for loaded values
+ foreach($model->_schemaKeys as $c) {
+ ksort($c['fields']);
+ $keyset = array();
+ foreach($c['fields'] as $k) {
+ if (!isset($model->_savedValues[$k])) {
+ continue 2;
+ }
+ $keyset[] = "{$k}={$model->_savedValues[$k]}";
+ }
+ $keyset = implode('&',$keyset);
+ $this->cache->expire($model->_m().'?'.$keyset);
}
return true;
}
View
83 ...er/helpers/datasource/db/helper.datasource.db.php → ...atasource/database/helper.datasource.database.php
@@ -3,7 +3,7 @@
/**
* Helper_datasource_db.php
*
- * Datasource (DB) Helper class
+ * Database Datasource Helper class
* @author Thom Stricklin <code@thomshouse.net>
* @version 1.0
* @package Escher
@@ -11,10 +11,10 @@
/**
* Datasource DB Helper class
- * Note: The Escher DB Datasource provides passive support for metadata/content tables.
+ * Note: The Escher Database Datasource provides passive support for metadata/content tables.
* @package Escher
*/
-class Helper_datasource_db extends Helper_datasource {
+class Helper_datasource_database extends Helper_datasource {
protected $db;
protected $intTypes = array(
'tinyint' => 1, // 256 (Range)
@@ -57,8 +57,10 @@ function set($model,$data=array(),$options=array()) {
$m = $model;
if ($model = Load::Model($m)) {
$schema = $this->getSchema($model);
+ $this->setSchema($model);
} else {
$schema = $this->getSchema($m);
+ $this->setSchema($m);
}
// If $model is array, get the object and schema
@@ -66,8 +68,10 @@ function set($model,$data=array(),$options=array()) {
$m = $model[1];
if ($model = Load::Model($m)) {
$schema = $this->getSchema($model);
+ $this->setSchema($model);
} else {
$schema = $this->getSchema($m);
+ $this->setSchema($m);
}
} else {
return false;
@@ -123,11 +127,20 @@ function set($model,$data=array(),$options=array()) {
'metadata' => $metadata,
'content' => $content,
);
+
+ // Determine whether the primary key has been set
+ $primarySet = (sizeof($primary)==sizeof(
+ (array)$schema['keys']['primary']['fields']));
+
+ // Determine set mode (insert or update)
+ $mode = !empty($options['mode'])
+ ? $options['mode']
+ : 'update';
+ if (!$primarySet) { $mode = 'insert'; }
+
// Iterate through each of the partitions
foreach($partitions as $partition => $values) {
- // Determine whether the primary key has been set
- $primarySet =
- sizeof($primary)==sizeof((array)$schema['keys']['primary']['fields']);
+ $result = FALSE;
// Skip content and metadata partition if nothing to save
if (in_array($partition,array('metadata','content'))
@@ -154,33 +167,41 @@ function set($model,$data=array(),$options=array()) {
}
// If primary key is set, perform an update
- if ($primarySet) {
- $result = $db->Execute(
+ if ($mode=='update') {
+ $db->Execute(
"UPDATE " . $partname. " SET " . implode(',',$attr_sql)
. " WHERE " . implode(' && ',$primary_sql),
array_merge(array_values($values),array_values($primary))
);
// Check to make sure update occurred
- if (!($db->affectedRows() || $db->getOne(
+ if ($db->affectedRows() || $db->getOne(
"SELECT COUNT(*) FROM " . $partname
. " WHERE " . implode(' && ',$primary_sql),
array_values($primary)
- ))) {
- $result = false;
+ )) {
+ $result = TRUE;
}
}
// If primary key is not set or if row did not exist, insert
- if (!$primarySet || !$result) {
+ if (!$primarySet || empty($result)) {
if (!$primarySet) {
+ $mode = 'insert';
if (sizeof((array)$schema['keys']['primary']['fields'])>1) {
return false;
}
- $key = reset($schema['keys']['primary']['fields']);
+ $key = is_array($schema['keys']['primary']['fields'])
+ ? reset($schema['keys']['primary']['fields'])
+ : $schema['keys']['primary']['fields'];
if (empty($schema['fields'][$key]['auto_increment'])) {
return false;
}
}
+ if (in_array($partition,array('metadata','content'))
+ && empty($values)
+ ) {
+ //continue;
+ }
$result = $db->Execute(
"INSERT INTO " . $partname . " SET "
. implode(',',array_merge($attr_sql,$primary_sql)),
@@ -190,9 +211,8 @@ function set($model,$data=array(),$options=array()) {
if (!$primarySet) {
$id = $db->getAutoId();
$primary = array($key => $id);
- if (is_object($model)) {
- $model->$key = $id;
- }
+ $primarySet = (sizeof($primary)==sizeof(
+ (array)$schema['keys']['primary']['fields']));
}
}
}
@@ -377,36 +397,49 @@ function get($models,$conditions=array(),$options=array()) {
if (!empty($result) && !empty($toDecode)) {
if ($qtype=='getOne') {
if (in_array(reset($options['select']),$toDecode)) {
- $result = json_decode($result,TRUE);
+ $decoded = json_decode($result,TRUE);
+ if (!json_last_error()) { $result = $decoded; }
}
} elseif ($qtype=='getCol') {
if (in_array(reset($options['select']),$toDecode)) {
foreach($result as $k => $r) {
- $result[$k] = json_decode($r,TRUE);
+ $decoded = json_decode($r,TRUE);
+ if (!json_last_error()) { $result[$k] = $decoded; }
}
}
} elseif ($qtype=='getRow') {
foreach($toDecode as $decode) {
if (array_key_exists($decode,$result)) {
- $result[$decode] = json_decode($result[$decode],TRUE);
+ $decoded = json_decode($result[$decode],TRUE);
+ if (!json_last_error()) { $result[$decode] = $decoded; }
}
}
} elseif ($qtype=='getAll') {
foreach($result as $k => $r) {
foreach($toDecode as $decode) {
if (array_key_exists($decode,$r)) {
- $result[$k][$decode] = json_decode($r[$decode],TRUE);
+ $decoded = json_decode($r[$decode],TRUE);
+ if (!json_last_error()) { $result[$k][$decode] = $decoded; }
+ }
+ }
+ }
+ } elseif ($qtype=='getAssoc') {
+ foreach($result as $k => $r) {
+ if (is_string($r)) {
+ $decoded = json_decode($r,TRUE);
+ if (!json_last_error()) { $result[$k] = $decoded; }
+ } else {
+ foreach($toDecode as $decode) {
+ if (array_key_exists($decode,$r)) {
+ $decoded = json_decode($r[$decode],TRUE);
+ if (!json_last_error()) { $result[$k][$decode] = $decoded; }
+ }
}
}
}
}
}
- // If result is a single valid row and we are selecting everything, get metadata and content
- if ($result && sizeof($models)==1 && is_a(reset($models),'Model') && $qtype=='getRow') {
- $model = reset($models);
- $model->assignVars($result);
- }
return $result;
}
View
6 escher/helpers/datasource/mongodb/helper.datasource.mongodb.php
@@ -58,9 +58,6 @@ function set($model,$data=array(),$options=array()) {
$result = $this->mongodb->selectCollection($collection)->insert($data,array('safe'=>TRUE));
$result = empty($result['err']);
if ($result) {
- if (is_object($model)) {
- $model->{$collection.'_id'} = $data[$collection.'_id'];
- }
return $data['_id'];
}
return false;
@@ -101,9 +98,6 @@ function get($model,$conditions=array(),$options=array()) {
unset($d['_id']);
$result[] = $d;
}
- if (is_object($model) && !empty($result) && $limit[1]==1) {
- $model->assignVars($result[0]);
- }
return $result;
}
View
4 escher/helpers/router/helper.router.php
@@ -127,7 +127,9 @@ function getRoute() {
}
function resolvePath($url,$absolute=TRUE) {
- if ($absolute && preg_match('#^(/.*)#',$url,$match)) {
+ if (preg_match('/^#/',$url)) {
+ return $url;
+ } elseif ($absolute && preg_match('#^(/.*)#',$url,$match)) {
return $this->getRootPath().$match[1];
} elseif (preg_match('#^~(/.*|)#',$url,$match)) {
return $this->getSitePath($absolute).$match[1];
View
4 escher/index.php
@@ -121,7 +121,7 @@ protected function initCommon() {
* Initialize environment settings
*/
protected function initEnvironment() {
- require_once($this->fileroot.'/escher/environment.php');
+ require_once($this->fileroot.'/escher/core/environment.php');
}
/**
@@ -145,7 +145,7 @@ protected function initConfig() {
* Initialize loader class
*/
protected function initLoader() {
- require_once($this->fileroot.'/escher/loader.php');
+ require_once($this->fileroot.'/escher/core/loader.php');
}
/**
Please sign in to comment.
Something went wrong with that request. Please try again.