Skip to content

Commit

Permalink
Numerous updates here including: 1) improved speed of bootup and vari…
Browse files Browse the repository at this point in the history
…ous optimizations throughout; 2) addition of $cache API var (currently just a simple string cache); 3) Add support for translating uploaded filenames so that non-ascii chars get translated to ascii equivlants rathern than just underscores (though I need to do more testing on this)so that non-ascii chars get translated to ascii equivlants rathern than just underscores (though I need to do more testing on this); 4) Various updates to ProcessPageLister and InputfieldSelector; 5) Improvements and additions to the debug timers, plus a new "Timers" section in the debug info that appears in the admin; 6) Convert Fieldtype modules to load on-demand rather than all at boot. Lots of changes in this commit so please keep an eye out for any issues and thanks for testing it out.
  • Loading branch information
ryancramerdesign committed Jun 17, 2014
1 parent 7da0e98 commit ca8a541
Show file tree
Hide file tree
Showing 21 changed files with 1,051 additions and 188 deletions.
99 changes: 91 additions & 8 deletions wire/core/Debug.php
Expand Up @@ -19,39 +19,122 @@
class Debug {

static protected $timers = array();

static protected $savedTimers = array();

static protected $savedTimerNotes = array();

/**
* Measure time between two events
*
* First call should be to $key = Debug::timer() with no params, or provide your own key that's not already been used
* Second call should pass the key given by the first call to get the time elapsed, i.e. $time = Debug::timer($key)
* Second call should pass the key given by the first call to get the time elapsed, i.e. $time = Debug::timer($key).
* Note that you may make multiple calls back to Debug::timer() with the same key and it will continue returning the
* elapsed time since the original call. If you want to reset or remove the timer, call removeTimer or resetTimer.
*
* @param string $key
* Leave blank to start timer.
* Specify existing key (string) to return timer.
* Specify new made up key to start a named timer.
* @param bool $reset If the timer already exists, it will be reset when this is true.
* @return string|int
*
*/
static public function timer($key = '') {
static public function timer($key = '', $reset = false) {
// returns number of seconds elapsed since first call
if($reset && $key) self::removeTimer($key);

if(!$key || !isset(self::$timers[$key])) {
// start new timer
preg_match('/(\.[0-9]+) ([0-9]+)/', microtime(), $time);
$startTime = doubleval($time[1]) + doubleval($time[2]);
if(!$key) $key = $startTime;
while(isset(self::$timers[$key])) $key .= ".";
if(!$key) {
$key = $startTime;
while(isset(self::$timers[$key])) $key .= ".";
}
self::$timers[$key] = $startTime;
return $key;
$value = $key;
} else {
// return timer
preg_match('/(\.[0-9]*) ([0-9]*)/', microtime(), $time);
$endTime = doubleval($time[1]) + doubleval($time[2]);
$startTime = self::$timers[$key];
$runTime = number_format($endTime - $startTime, 4);
return $runTime;
$value = $runTime;
}

return $value;
}

/**
* Save the current time of the given timer which can be later retrieved with getSavedTimer($key)
*
* Note this also stops/removes the timer.
*
* @param string $key
* @param string $note Optional note to include in getSavedTimer
* @return bool Returns false if timer didn't exist in the first place
*
*/
static public function saveTimer($key, $note = '') {
if(!isset(self::$timers[$key])) return false;
self::$savedTimers[$key] = self::timer($key);
self::removeTimer($key);
if($note) self::$savedTimerNotes[$key] = $note;
return true;
}

/**
* Return the time recorded in the saved timer $key
*
* @param string $key
* @return string Blank if timer not recognized
*
*/
static public function getSavedTimer($key) {
$value = isset(self::$savedTimers[$key]) ? self::$savedTimers[$key] : null;
if(!is_null($value) && isset(self::$savedTimerNotes[$key])) $value = "$value - " . self::$savedTimerNotes[$key];
return $value;
}

/**
* Remove a saved timer
* Return all saved timers in associative array indexed by key
*
* @return array
*
*/
static public function remove($key) {
static public function getSavedTimers() {
$timers = self::$savedTimers;
arsort($timers);
foreach($timers as $key => $timer) {
$timers[$key] = self::getSavedTimer($key); // to include notes
}
return $timers;
}

/**
* Reset a timer so that it starts timing again from right now
*
*/
static public function resetTimer($key) {
self::removeTimer($key);
return self::timer($key);
}

/**
* Remove a timer completely
*
*/
static public function removeTimer($key) {
unset(self::$timers[$key]);
}

/**
* Remove all active timers
*
*/
static public function removeAll() {
self::$timers = array();
}

}
63 changes: 57 additions & 6 deletions wire/core/Fieldtypes.php
Expand Up @@ -18,17 +18,40 @@ class Fieldtypes extends WireArray {
/**
* Instance of Modules class
*
*/
protected $modules;
*/

protected $preloaded = false;

/**
* Construct this Fieldtypes object and load all Fieldtype modules
*
*/
public function init() {
$this->modules = $this->getFuel('modules');
$fieldtypes = $this->modules->find('className^=Fieldtype');
foreach($fieldtypes as $fieldtype) $this->add($fieldtype);
foreach($this->wire('modules') as $module) {
if(strpos($module->className(), 'Fieldtype') === 0) {
// if($module instanceof ModulePlaceholder) $module = $this->wire('modules')->get($module->className());
$this->add($module);
}
}
}

/**
* Convert all ModulePlaceholders to Fieldtype modules
*
*/
protected function preload() {
if($this->preloaded) return;
$debug = $this->wire('config')->debug;
if($debug) Debug::timer('Fieldtypes.preload');
foreach($this->data as $key => $module) {
if($module instanceof ModulePlaceholder) {
$fieldtype = $this->wire('modules')->get($module->className());
$this->data[$key] = $fieldtype;
}
}
if($debug) Debug::saveTimer('Fieldtypes.preload');
$this->preloaded = true;
}

/**
Expand Down Expand Up @@ -90,16 +113,44 @@ public function get($key) {
if(strpos($key, 'Fieldtype') !== 0) $key = "Fieldtype" . ucfirst($key);

if(!$fieldtype = parent::get($key)) {
$fieldtype = $this->modules->get($key);
$fieldtype = $this->wire('modules')->get($key);
}

if($fieldtype instanceof ModulePlaceholder) {
$fieldtype = $this->modules->get($fieldtype->className());
$fieldtype = $this->wire('modules')->get($fieldtype->className());
$this->set($key, $fieldtype);
}

return $fieldtype;
}

/**
* Below we account for all get() related functions in WireArray to preload the fieldtypes
*
* This ensures there are no ModulePlaceholders present when results from any of these methods.
*
*/

public function getArray() { $this->preload(); return parent::getArray(); }
public function getAll() { $this->preload(); return parent::getAll(); }
public function getValues() { $this->preload(); return parent::getValues(); }
public function getRandom($num = 1, $alwaysArray = false) { $this->preload(); return parent::getRandom($num, $alwaysArray); }
public function slice($start, $limit = 0) { $this->preload(); return parent::slice($start, $limit); }
public function shift() { $this->preload(); return parent::shift(); }
public function pop() { $this->preload(); return parent::pop(); }
public function eq($num) { $this->preload(); return parent::eq($num); }
public function first() { $this->preload(); return parent::first(); }
public function last() { $this->preload(); return parent::last(); }
public function sort($properties) { $this->preload(); return parent::sort($properties); }
protected function filterData($selectors, $not = false) { $this->preload(); return parent::filterData($selectors, $not); }
public function makeCopy() { $this->preload(); return parent::makeCopy(); }
public function makeNew() { $this->preload(); return parent::makeNew(); }
public function getIterator() { $this->preload(); return parent::getIterator(); }
public function getNext($item) { $this->preload(); return parent::getNext($item); }
public function getPrev($item) { $this->preload(); return parent::getPrev($item); }



}


0 comments on commit ca8a541

Please sign in to comment.