Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into translation-staging
Browse files Browse the repository at this point in the history
  • Loading branch information
chillu committed Aug 27, 2012
2 parents c191f1f + a8f3353 commit db28e88
Show file tree
Hide file tree
Showing 24 changed files with 395 additions and 2,460 deletions.
10 changes: 8 additions & 2 deletions _config/routes.yml
Expand Up @@ -7,8 +7,10 @@ Director:
'': 'Controller'
---
Name: coreroutes
After: cms/routes#modelascontrollerroutes
Before: '*'
After:
- framework/routes#rootroutes
- cms/routes#modelascontrollerroutes
---
Director:
rules:
Expand All @@ -21,7 +23,11 @@ Director:
'interactive': 'SapphireREPL'
---
Name: adminroutes
After: framework/routes#coreroutes
Before: '*'
After:
- framework/routes#rootroutes
- framework/routes#coreroutes
- cms/routes#modelascontrollerroutes
---
Director:
rules:
Expand Down
9 changes: 5 additions & 4 deletions admin/code/LeftAndMain.php
Expand Up @@ -336,9 +336,8 @@ function init() {
}

function handleRequest(SS_HTTPRequest $request, DataModel $model = null) {
$title = $this->Title();

$response = parent::handleRequest($request, $model);
$title = $this->Title();
if(!$response->getHeader('X-Controller')) $response->addHeader('X-Controller', $this->class);
if(!$response->getHeader('X-Title')) $response->addHeader('X-Title', $title);

Expand Down Expand Up @@ -1342,8 +1341,10 @@ function Title() {
* @return string
*/
function SectionTitle() {
if($title = $this->stat('menu_title')) return $title;

$class = get_class($this);
$defaultTitle = LeftAndMain::menu_title_for_class($class);
if($title = _t("{$class}.MENUTITLE", $defaultTitle)) return $title;

foreach($this->MainMenu() as $menuItem) {
if($menuItem->LinkingMode != 'link') return $menuItem->Title;
}
Expand Down
19 changes: 19 additions & 0 deletions core/ClassInfo.php
Expand Up @@ -231,6 +231,25 @@ static function classes_for_folder($folderPath) {

return $matchedClasses;
}

private static $method_from_cache = array();

static function has_method_from($class, $method, $compclass) {
if (!isset(self::$method_from_cache[$class])) self::$method_from_cache[$class] = array();

if (!array_key_exists($method, self::$method_from_cache[$class])) {
self::$method_from_cache[$class][$method] = false;

$classRef = new ReflectionClass($class);

if ($classRef->hasMethod($method)) {
$methodRef = $classRef->getMethod($method);
self::$method_from_cache[$class][$method] = $methodRef->getDeclaringClass()->getName();
}
}

return self::$method_from_cache[$class][$method] == $compclass;
}

}

19 changes: 8 additions & 11 deletions core/Config.php
Expand Up @@ -173,12 +173,6 @@ public function pushConfigManifest(SS_ConfigManifest $manifest) {
$this->collectConfigPHPSettings = false;
}

static $extra_static_sources = array();

static function add_static_source($forclass, $donorclass) {
self::$extra_static_sources[$forclass][] = $donorclass;
}

/** @var [Config_ForClass] - The list of Config_ForClass instances, keyed off class */
static protected $for_class_instances = array();

Expand Down Expand Up @@ -371,14 +365,17 @@ function get($class, $name, $sourceOptions = 0, &$result = null, $suppress = nul

// Then look at the static variables
$nothing = new stdClass();
$classes = array($class);

$sources = array($class);
// Include extensions only if not flagged not to, and some have been set
if ((($sourceOptions & self::EXCLUDE_EXTRA_SOURCES) != self::EXCLUDE_EXTRA_SOURCES) && isset(self::$extra_static_sources[$class])) {
$classes = array_merge($classes, self::$extra_static_sources[$class]);
if (($sourceOptions & self::EXCLUDE_EXTRA_SOURCES) != self::EXCLUDE_EXTRA_SOURCES) {
$extraSources = Object::get_extra_config_sources($class);
if ($extraSources) $sources = array_merge($sources, $extraSources);
}

foreach ($classes as $staticSource) {
$value = Object::static_lookup($staticSource, $name, $nothing);
foreach ($sources as $staticSource) {
if (is_array($staticSource)) $value = isset($staticSource[$name]) ? $staticSource[$name] : $nothing;
else $value = Object::static_lookup($staticSource, $name, $nothing);

if ($value !== $nothing) {
self::merge_low_into_high($result, $value, $suppress);
Expand Down
65 changes: 63 additions & 2 deletions core/DAG.php
Expand Up @@ -4,7 +4,7 @@
* A Directed Acyclic Graph - used for doing topological sorts on dependencies, such as the before/after conditions
* in config yaml fragments
*/
class SS_DAG {
class SS_DAG implements IteratorAggregate {
/** @var array|null - The nodes/vertices in the graph. Should be a numeric sequence of items (no string keys, no gaps). */
protected $data;

Expand Down Expand Up @@ -68,7 +68,68 @@ function sort() {
$dag = $withedges;
}

if ($dag) throw new Exception("DAG has cyclic requirements");
if ($dag) {
$remainder = new SS_DAG($data); $remainder->dag = $dag;
throw new SS_DAG_CyclicException("DAG has cyclic requirements", $remainder);
}
return $sorted;
}

function getIterator() {
return new SS_DAG_Iterator($this->data, $this->dag);
}
}

class SS_DAG_CyclicException extends Exception {

public $dag;

function __construct($message, $dag) {
$this->dag = $dag;
parent::__construct($message);
}

}

class SS_DAG_Iterator implements Iterator {

protected $data;
protected $dag;

protected $dagkeys;
protected $i;

function __construct($data, $dag) {
$this->data = $data;
$this->dag = $dag;
$this->rewind();
}

function key() {
return $this->i;
}

function current() {
$res = array();

$res['from'] = $this->data[$this->i];

$res['to'] = array();
foreach ($this->dag[$this->i] as $to) $res['to'][] = $this->data[$to];

return $res;
}

function next() {
$this->i = array_shift($this->dagkeys);
}

function rewind() {
$this->dagkeys = array_keys($this->dag);
$this->next();
}

function valid() {
return $this->i !== null;
}
}
5 changes: 1 addition & 4 deletions core/Extension.php
Expand Up @@ -46,14 +46,11 @@ function __construct() {
/**
* Called when this extension is added to a particular class
*
* TODO: This is likely to be replaced by event sytem before 3.0 final, so be aware
* this API is fairly unstable.
*
* @static
* @param $class
*/
static function add_to_class($class, $extensionClass, $args = null) {
Config::add_static_source($class, $extensionClass);
// NOP
}

/**
Expand Down
80 changes: 55 additions & 25 deletions core/Object.php
Expand Up @@ -463,6 +463,7 @@ public static function add_extension($class, $extension) {
if($subclasses) foreach($subclasses as $subclass) {
unset(self::$classes_constructed[$subclass]);
unset(self::$extra_methods[$subclass]);
unset(self::$extension_sources[$subclass]);
}

Config::inst()->update($class, 'extensions', array($extension));
Expand Down Expand Up @@ -505,6 +506,7 @@ public static function remove_extension($class, $extension) {
if($subclasses) foreach($subclasses as $subclass) {
unset(self::$classes_constructed[$subclass]);
unset(self::$extra_methods[$subclass]);
unset(self::$extension_sources[$subclass]);
}
}

Expand All @@ -531,38 +533,66 @@ public static function get_extensions($class, $includeArgumentString = false) {

// -----------------------------------------------------------------------------------------------------------------

private static $_added_extensions = array();
private static $extension_sources = array();

// Don't bother checking some classes that should never be extended
private static $unextendable_classes = array('Object', 'ViewableData', 'RequestHandler');

static public function get_extra_config_sources($class = null) {
if($class === null) $class = get_called_class();

// If this class is unextendable, NOP
if(in_array($class, self::$unextendable_classes)) return;

// If we have a pre-cached version, use that
if(array_key_exists($class, self::$extension_sources)) return self::$extension_sources[$class];

// Variable to hold sources in
$sources = null;

// Get a list of extensions
$extensions = Config::inst()->get($class, 'extensions', Config::UNINHERITED | Config::EXCLUDE_EXTRA_SOURCES);

if($extensions) {
// Build a list of all sources;
$sources = array();

foreach($extensions as $extension) {
list($extensionClass, $extensionArgs) = self::parse_class_spec($extension);
$sources[] = $extensionClass;

if(!ClassInfo::has_method_from($extensionClass, 'add_to_class', 'Extension')) {
Deprecation::notice('3.1.0', "add_to_class deprecated on $extensionClass. Use get_extra_config instead");
}

call_user_func(array($extensionClass, 'add_to_class'), $class, $extensionClass, $extensionArgs);

foreach(array_reverse(ClassInfo::ancestry($extensionClass)) as $extensionClassParent) {
if (ClassInfo::has_method_from($extensionClassParent, 'get_extra_config', $extensionClassParent)) {
$extras = $extensionClassParent::get_extra_config($class, $extensionClass, $extensionArgs);
if ($extras) $sources[] = $extras;
}
}
}
}

return self::$extension_sources[$class] = $sources;
}

public function __construct() {
$this->class = get_class($this);

// Don't bother checking some classes that should never be extended
static $notExtendable = array('Object', 'ViewableData', 'RequestHandler');

if($extensionClasses = ClassInfo::ancestry($this->class)) foreach($extensionClasses as $class) {
if(in_array($class, $notExtendable)) continue;
if($extensions = Config::inst()->get($class, 'extensions', Config::UNINHERITED)) {
foreach($extensions as $extension) {
// Get the extension class for this extension
list($extensionClass, $extensionArgs) = self::parse_class_spec($extension);

// If we haven't told that extension it's attached to this class yet, do that now
if (!isset(self::$_added_extensions[$extensionClass][$class])) {
// First call the add_to_class method - this will inherit down & is defined on Extension, so if not defined, no worries
call_user_func(array($extensionClass, 'add_to_class'), $class, $extensionClass, $extensionArgs);

// Then register it as having been told about us
if (!isset(self::$_added_extensions[$extensionClass])) self::$_added_extensions[$extensionClass] = array($class => true);
else self::$_added_extensions[$extensionClass][$class] = true;
}
foreach(ClassInfo::ancestry(get_called_class()) as $class) {
if(in_array($class, self::$unextendable_classes)) continue;
$extensions = Config::inst()->get($class, 'extensions', Config::UNINHERITED | Config::EXCLUDE_EXTRA_SOURCES);

$instance = self::create_from_string($extension);
$instance->setOwner(null, $class);
$this->extension_instances[$instance->class] = $instance;
}
if($extensions) foreach($extensions as $extension) {
$instance = self::create_from_string($extension);
$instance->setOwner(null, $class);
$this->extension_instances[$instance->class] = $instance;
}
}

if(!isset(self::$classes_constructed[$this->class])) {
$this->defineMethods();
self::$classes_constructed[$this->class] = true;
Expand Down

0 comments on commit db28e88

Please sign in to comment.