Removing @deprecated 3.1 functionality and classes.

Changelog has been updated to include what was removed in terms of
major functionality, and what to use as a replacement.
This commit is contained in:
Sean Harvey 2014-08-18 15:49:32 +12:00
parent b346d2b4d3
commit 404478b07f
27 changed files with 18 additions and 1343 deletions

View File

@ -457,7 +457,7 @@ abstract class ModelAdmin extends LeftAndMain {
* overwrite the static page_length of the admin panel,
* should be called in the project _config file.
*
* @deprecated 3.1 Use "ModelAdmin.page_length" config setting
* @deprecated 3.2 Use "ModelAdmin.page_length" config setting
*/
public static function set_page_length($length){
Deprecation::notice('3.2', 'Use "ModelAdmin.page_length" config setting');
@ -467,7 +467,7 @@ abstract class ModelAdmin extends LeftAndMain {
/**
* Return the static page_length of the admin, default as 30
*
* @deprecated 3.1 Use "ModelAdmin.page_length" config setting
* @deprecated 3.2 Use "ModelAdmin.page_length" config setting
*/
public static function get_page_length(){
Deprecation::notice('3.2', 'Use "ModelAdmin.page_length" config setting');

View File

@ -334,7 +334,7 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
* The permissions represented in the $codes will not appearing in the form
* containing {@link PermissionCheckboxSetField} so as not to be checked / unchecked.
*
* @deprecated 3.1 Use "Permission.hidden_permissions" config setting instead
* @deprecated 3.2 Use "Permission.hidden_permissions" config setting instead
* @param $codes String|Array
*/
public static function add_hidden_permission($codes){
@ -344,7 +344,7 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
}
/**
* @deprecated 3.1 Use "Permission.hidden_permissions" config setting instead
* @deprecated 3.2 Use "Permission.hidden_permissions" config setting instead
* @param $codes String|Array
*/
public static function remove_hidden_permission($codes){
@ -354,7 +354,7 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
}
/**
* @deprecated 3.1 Use "Permission.hidden_permissions" config setting instead
* @deprecated 3.2 Use "Permission.hidden_permissions" config setting instead
* @return Array
*/
public static function get_hidden_permissions(){
@ -365,7 +365,7 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
/**
* Clear all permissions previously hidden with {@link add_hidden_permission}
*
* @deprecated 3.1 Use "Permission.hidden_permissions" config setting instead
* @deprecated 3.2 Use "Permission.hidden_permissions" config setting instead
*/
public static function clear_hidden_permissions(){
Deprecation::notice('3.2', 'Use "Permission.hidden_permissions" config setting instead');

View File

@ -224,4 +224,4 @@ class FixtureFactory {
}
}
}
}

View File

@ -1,239 +0,0 @@
<?php
/********************************************************************************\
* Copyright (C) Carl Taylor (cjtaylor@adepteo.com) *
* Copyright (C) Torben Nehmer (torben@nehmer.net) for Code Cleanup *
* Licensed under the BSD license upon request *
\********************************************************************************/
/// Enable multiple timers to aid profiling of performance over sections of code
/**
* Execution time profiler.
*
* @deprecated 3.1 The Profiler class is deprecated, use third party tools like XHProf instead
*
* @package framework
* @subpackage misc
*/
class Profiler {
var $description;
var $startTime;
var $endTime;
var $initTime;
var $cur_timer;
var $stack;
var $trail;
var $trace;
var $count;
var $running;
protected static $inst;
/**
* Initialise the timer. with the current micro time
*/
public function Profiler( $output_enabled=false, $trace_enabled=false)
{
$this->description = array();
$this->startTime = array();
$this->endTime = array();
$this->initTime = 0;
$this->cur_timer = "";
$this->stack = array();
$this->trail = "";
$this->trace = "";
$this->count = array();
$this->running = array();
$this->initTime = $this->getMicroTime();
$this->output_enabled = $output_enabled;
$this->trace_enabled = $trace_enabled;
$this->startTimer('unprofiled');
}
// Public Methods
public static function init() {
Deprecation::notice('3.1', 'The Profiler class is deprecated, use third party tools like XHProf instead');
if(!self::$inst) self::$inst = new Profiler(true,true);
}
public static function mark($name, $level2 = "", $desc = "") {
if($level2 && $_GET['debug_profile'] > 1) $name .= " $level2";
if(!self::$inst) self::$inst = new Profiler(true,true);
self::$inst->startTimer($name, $desc);
}
public static function unmark($name, $level2 = "", $desc = "") {
if($level2 && $_GET['debug_profile'] > 1) $name .= " $level2";
if(!self::$inst) self::$inst = new Profiler(true,true);
self::$inst->stopTimer($name, $desc);
}
public static function show($showTrace = false) {
if(!self::$inst) self::$inst = new Profiler(true,true);
echo "<div style=\"position: absolute; z-index: 100000; top: 20px; left: 20px; background-color: white;"
. " padding: 20px; border: 1px #AAA solid; height: 80%; overflow: auto;\">";
echo "<p><a href=\"#\" onclick=\"this.parentNode.parentNode.style.display = 'none'; return false;\">"
. "(Click to close)</a></p>";
self::$inst->printTimers();
if($showTrace) self::$inst->printTrace();
echo "</div>";
}
/**
* Start an individual timer
* This will pause the running timer and place it on a stack.
* @param string $name name of the timer
* @param string optional $desc description of the timer
*/
public function startTimer($name, $desc="" ){
$this->trace.="start $name\n";
$n=array_push( $this->stack, $this->cur_timer );
$this->__suspendTimer( $this->stack[$n-1] );
$this->startTime[$name] = $this->getMicroTime();
$this->cur_timer=$name;
$this->description[$name] = $desc;
if (!array_key_exists($name,$this->count))
$this->count[$name] = 1;
else
$this->count[$name]++;
}
/**
* Stop an individual timer
* Restart the timer that was running before this one
* @param string $name name of the timer
*/
public function stopTimer($name){
$this->trace.="stop $name\n";
$this->endTime[$name] = $this->getMicroTime();
if (!array_key_exists($name, $this->running))
$this->running[$name] = $this->elapsedTime($name);
else
$this->running[$name] += $this->elapsedTime($name);
$this->cur_timer=array_pop($this->stack);
$this->__resumeTimer($this->cur_timer);
}
/**
* measure the elapsed time of a timer without stoping the timer if
* it is still running
*/
public function elapsedTime($name){
// This shouldn't happen, but it does once.
if (!array_key_exists($name,$this->startTime))
return 0;
if(array_key_exists($name,$this->endTime)){
return ($this->endTime[$name] - $this->startTime[$name]);
} else {
$now=$this->getMicroTime();
return ($now - $this->startTime[$name]);
}
}//end start_time
/**
* Measure the elapsed time since the profile class was initialised
*
*/
public function elapsedOverall(){
$oaTime = $this->getMicroTime() - $this->initTime;
return($oaTime);
}//end start_time
/**
* print out a log of all the timers that were registered
*
*/
public function printTimers($enabled=false)
{
if($this->output_enabled||$enabled){
$TimedTotal = 0;
$tot_perc = 0;
ksort($this->description);
print("<pre>\n");
$oaTime = $this->getMicroTime() - $this->initTime;
echo"============================================================================\n";
echo " PROFILER OUTPUT\n";
echo"============================================================================\n";
print( "Calls Time Routine\n");
echo"-----------------------------------------------------------------------------\n";
while (list ($key, $val) = each ($this->description)) {
$t = $this->elapsedTime($key);
$total = $this->running[$key];
$count = $this->count[$key];
$TimedTotal += $total;
$perc = ($total/$oaTime)*100;
$tot_perc+=$perc;
// $perc=sprintf("%3.2f", $perc );
$lines[ sprintf( "%3d %3.4f ms (%3.2f %%) %s\n", $count, $total*1000, $perc, $key) ] = $total;
}
arsort($lines);
foreach($lines as $line => $total) {
echo $line;
}
echo "\n";
$missed=$oaTime-$TimedTotal;
$perc = ($missed/$oaTime)*100;
$tot_perc+=$perc;
// $perc=sprintf("%3.2f", $perc );
printf( " %3.4f ms (%3.2f %%) %s\n", $missed*1000,$perc, "Missed");
echo"============================================================================\n";
printf( " %3.4f ms (%3.2f %%) %s\n", $oaTime*1000,$tot_perc, "OVERALL TIME");
echo"============================================================================\n";
print("</pre>");
}
}
public function printTrace( $enabled=false )
{
if($this->trace_enabled||$enabled){
print("<pre>");
print("Trace\n$this->trace\n\n");
print("</pre>");
}
}
/// Internal Use Only Functions
/**
* Get the current time as accuratly as possible
*
*/
public function getMicroTime(){
$tmp=explode(' ', microtime());
$rt=$tmp[0]+$tmp[1];
return $rt;
}
/**
* resume an individual timer
*
*/
public function __resumeTimer($name){
$this->trace.="resume $name\n";
$this->startTime[$name] = $this->getMicroTime();
}
/**
* suspend an individual timer
*
*/
public function __suspendTimer($name){
$this->trace.="suspend $name\n";
$this->endTime[$name] = $this->getMicroTime();
if (!array_key_exists($name, $this->running))
$this->running[$name] = $this->elapsedTime($name);
else
$this->running[$name] += $this->elapsedTime($name);
}
}

View File

@ -157,14 +157,8 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
return static::$fixture_file;
}
/**
* @var array $fixtures Array of {@link YamlFixture} instances
* @deprecated 3.1 Use $fixtureFactory instad
*/
protected $fixtures = array();
protected $model;
public function setUp() {
// We cannot run the tests on this abstract class.
if(get_class($this) == "SapphireTest") $this->skipTest = true;
@ -445,7 +439,6 @@ class SapphireTest extends PHPUnit_Framework_TestCase {
* {@link loadFixture()}
*/
public function clearFixtures() {
$this->fixtures = array();
$this->getFixtureFactory()->clear();
}

View File

@ -83,12 +83,6 @@ class YamlFixture extends Object {
*/
protected $fixtureString;
/**
* @var FixtureFactory
* @deprecated 3.1 Use writeInto() and FixtureFactory instead
*/
protected $factory;
/**
* @param String Absolute file path, or relative path to {@link Director::baseFolder()}
*/
@ -123,68 +117,6 @@ class YamlFixture extends Object {
return $this->fixtureString;
}
/**
* Get the ID of an object from the fixture.
*
* @deprecated 3.1 Use writeInto() and FixtureFactory accessors instead
*
* @param $className The data class, as specified in your fixture file. Parent classes won't work
* @param $identifier The identifier string, as provided in your fixture file
*/
public function idFromFixture($className, $identifier) {
Deprecation::notice('3.1', 'Use writeInto() and FixtureFactory accessors instead');
if(!$this->factory) $this->factory = Injector::inst()->create('FixtureFactory');
return $this->factory->getId($className, $identifier);
}
/**
* Return all of the IDs in the fixture of a particular class name.
*
* @deprecated 3.1 Use writeInto() and FixtureFactory accessors instead
*
* @return A map of fixture-identifier => object-id
*/
public function allFixtureIDs($className) {
Deprecation::notice('3.1', 'Use writeInto() and FixtureFactory accessors instead');
if(!$this->factory) $this->factory = Injector::inst()->create('FixtureFactory');
return $this->factory->getIds($className);
}
/**
* Get an object from the fixture.
*
* @deprecated 3.1 Use writeInto() and FixtureFactory accessors instead
*
* @param $className The data class, as specified in your fixture file. Parent classes won't work
* @param $identifier The identifier string, as provided in your fixture file
*/
public function objFromFixture($className, $identifier) {
Deprecation::notice('3.1', 'Use writeInto() and FixtureFactory accessors instead');
if(!$this->factory) $this->factory = Injector::inst()->create('FixtureFactory');
return $this->factory->get($className, $identifier);
}
/**
* Load a YAML fixture file into the database.
* Once loaded, you can use idFromFixture() and objFromFixture() to get items from the fixture.
*
* Caution: In order to support reflexive relations which need a valid object ID,
* the record is written twice: first after populating all non-relational fields,
* then again after populating all relations (has_one, has_many, many_many).
*
* @deprecated 3.1 Use writeInto() and FixtureFactory instance instead
*/
public function saveIntoDatabase(DataModel $model) {
Deprecation::notice('3.1', 'Use writeInto() and FixtureFactory instance instead');
if(!$this->factory) $this->factory = Injector::inst()->create('FixtureFactory');
$this->writeInto($this->factory);
}
/**
* Persists the YAML data in a FixtureFactory,
* which in turn saves them into the database.

View File

@ -13,6 +13,12 @@
* ClassInfo::dataClassesFor now returns classes which should have tables, regardless of whether those
tables actually exist.
* SS_Filterable, SS_Limitable and SS_Sortable now explicitly extend SS_List
* ToggleField was deprecated in 3.1, and has been removed. Use custom Javascript with ReadonlyField instead.
* ExactMatchMultiFilter was deprecated in 3.1, and has been removed. Use ExactMatchFilter instead.
* NegationFilter was deprecated in 3.1, and has been removed. Use ExactMatchFilter:not instead.
* StartsWithMultiFilter was deprecated in 3.1, and has been removed. Use StartsWithFilter instead.
* ScheduledTask and subclasses like DailyTask were deprecated in 3.1, and have been removed.
Use custom code instead, or a module like silverstripe-crontask: https://github.com/silverstripe-labs/silverstripe-crontask
### CMS

View File

@ -182,4 +182,4 @@ for the [framework](https://travis-ci.org/silverstripe/silverstripe-framework) a
[cms](https://travis-ci.org/silverstripe/silverstripe-cms) modules.
In addition, some build configurations (e.g. running on Windows) are tested
through a [TeamCity](http://www.jetbrains.com/teamcity/) instance hosted at
[teamcity.silverstripe.com](http://teamcity.silverstripe.com) (click "Login as guest").
[teamcity.silverstripe.com](http://teamcity.silverstripe.com) (click "Login as guest").

View File

@ -45,7 +45,6 @@ doesn't necessarily have any visible styling.
* `[api:TabSet]`: Collection of fields which is rendered as separate tabs. Can be nested.
* `[api:Tab]`: A single tab inside a `TabSet`.
* `[api:ToggleCompositeField]`: Allows visibility of a group of fields to be toggled.
* `[api:ToggleField]`: ReadonlyField with added toggle-capabilities - will preview the first sentence of the contained text-value, and show the full content by a javascript-switch.
## Files

View File

@ -437,113 +437,3 @@ class Mailer extends Object {
}
}
/**
* @package framework
* @subpackage email
* @deprecated 3.1
*/
function htmlEmail($to, $from, $subject, $htmlContent, $attachedFiles = false, $customheaders = false,
$plainContent = false) {
Deprecation::notice('3.1', 'Use Email->sendHTML() instead');
$mailer = Injector::inst()->create('Mailer');
return $mailer->sendHTML($to, $from, $subject, $plainContent, $attachedFiles, $customheaders = false);
}
/**
* @package framework
* @subpackage email
* @deprecated 3.1
*/
function plaintextEmail($to, $from, $subject, $plainContent, $attachedFiles, $customheaders = false) {
Deprecation::notice('3.1', 'Use Email->sendPlain() instead');
$mailer = Injector::inst()->create('Mailer');
return $mailer->sendPlain($to, $from, $subject, $plainContent, $attachedFiles, $customheaders = false);
}
/**
* @package framework
* @subpackage email
* @deprecated 3.1
*/
function encodeMultipart($parts, $contentType, $headers = false) {
Deprecation::notice('3.1', 'Use Email->$this->encodeMultipart() instead');
$mailer = Injector::inst()->create('Mailer');
return $mailer->encodeMultipart($parts, $contentType, $headers = false);
}
/**
* @package framework
* @subpackage email
* @deprecated 3.1
*/
function wrapImagesInline($htmlContent) {
Deprecation::notice('3.1', 'Functionality removed from core');
$mailer = Injector::inst()->create('Mailer');
return $mailer->wrapImagesInline($htmlContent);
}
/**
* @package framework
* @subpackage email
* @deprecated 3.1
*/
function wrapImagesInline_rewriter($url) {
Deprecation::notice('3.1', 'Functionality removed from core');
$mailer = Injector::inst()->create('Mailer');
return $mailer->wrapImagesInline_rewriter($url);
}
/**
* @package framework
* @subpackage email
* @deprecated 3.1
*/
function processHeaders($headers, $body = false) {
Deprecation::notice('3.1', 'Set headers through Email->addCustomHeader()');
$mailer = Injector::inst()->create('Mailer');
return $mailer->processHeaders($headers, $url);
}
/**
* @package framework
* @subpackage email
* @deprecated 3.1
*/
function encodeFileForEmail($file, $destFileName = false, $disposition = NULL, $extraHeaders = "") {
Deprecation::notice('3.1', 'Please add files through Email->attachFile()');
$mailer = Injector::inst()->create('Mailer');
return $mailer->encodeFileForEmail($file, $destFileName, $disposition, $extraHeaders);
}
/**
* @package framework
* @subpackage email
* @deprecated 3.1
*/
function QuotedPrintable_encode($quotprint) {
Deprecation::notice('3.1', 'No longer available, handled internally');
$mailer = Injector::inst()->create('Mailer');
return $mailer->QuotedPrintable_encode($quotprint);
}
/**
* @package framework
* @subpackage email
* @deprecated 3.1
*/
function validEmailAddr($emailAddress) {
Deprecation::notice('3.1', 'Use Email->validEmailAddr() instead');
$mailer = Injector::inst()->create('Mailer');
return $mailer->validEmailAddr($emailAddress);
}

View File

@ -1,100 +0,0 @@
<?php
/**
* ReadonlyField with added toggle-capabilities - will preview the first sentence of the contained text-value,
* and show the full content by a javascript-switch.
*
* @deprecated 3.1 Use custom javascript with a ReadonlyField.
*
* Caution: Strips HTML-encoding for the preview.
* @package forms
* @subpackage fields-dataless
*/
class ToggleField extends ReadonlyField {
/**
* @var $labelMore string Text shown as a link to see the full content of the field
*/
public $labelMore;
/**
* @var $labelLess string Text shown as a link to see the partial view of the field content
*/
public $labelLess;
/**
* @see Text
* @var $truncateMethod string (FirstSentence|FirstParagraph)
*/
public $truncateMethod = 'FirstSentence';
/**
* @var $truncateChars int Number of chars to preview (optional).
* Truncating will be applied with $truncateMethod by default.
*/
public $truncateChars;
/**
* @param name The field name
* @param title The field title
* @param value The current value
*/
public function __construct($name, $title = "", $value = "") {
$this->labelMore = _t('ToggleField.MORE', 'more');
$this->labelLess = _t('ToggleField.LESS', 'less');
$this->startClosed(true);
parent::__construct($name, $title, $value);
}
public function Field($properties = array()) {
$content = '';
Requirements::javascript(FRAMEWORK_DIR . '/thirdparty/jquery/jquery.js');
Requirements::javascript(FRAMEWORK_DIR . "/javascript/ToggleField.js");
if($this->startClosed) $this->addExtraClass('startClosed');
$valforInput = $this->value ? Convert::raw2att($this->value) : "";
$rawInput = Convert::html2raw($valforInput);
if($this->charNum) $reducedVal = substr($rawInput,0,$this->charNum);
else $reducedVal = DBField::create_field('Text',$rawInput)->{$this->truncateMethod}();
// only create togglefield if the truncated content is shorter
if(strlen($reducedVal) < strlen($rawInput)) {
$content = <<<HTML
<div class="readonly typography contentLess" style="display: none">
$reducedVal
&nbsp;<a href="#" class="triggerMore">$this->labelMore</a>
</div>
<div class="readonly typography contentMore">
$this->value
&nbsp;<a href="#" class="triggerLess">$this->labelLess</a>
</div>
<br />
<input type="hidden" name="$this->name" value="$valforInput" />
HTML;
} else {
$this->dontEscape = true;
$content = parent::Field();
}
return $content;
}
/**
* Determines if the field should render open or closed by default.
*
* @param boolean
*/
public function startClosed($bool) {
($bool) ? $this->addExtraClass('startClosed') : $this->removeExtraClass('startClosed');
}
public function Type() {
return "toggleField";
}
}

View File

@ -1,188 +0,0 @@
<?php
/**
* Calculate an Aggregate on a particular field of a particular DataObject type (possibly with
* an additional filter before the aggregate)
*
* Implemented as a class to provide a semi-DSL method of calculating Aggregates. DataObject has a function
* that will create & return an instance of this class with the DataObject type and filter set,
* but at that point we don't yet know the aggregate function or field
*
* This class captures any XML_val or unknown call, and uses that to get the field & aggregate function &
* then return the result
*
* Two ways of calling
*
* $aggregate->XML_val(aggregate_function, array(field)) - For templates
* $aggregate->aggregate_function(field) - For PHP
*
* Aggregate functions are uppercased by this class, but are otherwise assumed to be valid SQL functions. Some
* examples: Min, Max, Avg
*
* Aggregates are often used as portions of a cacheblock key. They are therefore cached themselves, in the 'aggregate'
* cache, although the invalidation logic prefers speed over keeping valid data.
* The aggregate cache is cleared through {@link DataObject::flushCache()}, which in turn is called on
* {@link DataObject->write()} and other write operations.
* This means most write operations to the database will invalidate the cache correctly.
* Use {@link Aggregate::flushCache()} to manually clear.
*
* NOTE: The cache logic uses tags, and so a backend that supports tags is required. Currently only the File
* backend (and the two-level backend with the File backend as the slow store) meets this requirement
*
* @deprecated 3.1 Use DataList to aggregate data
*
* @author hfried
* @package framework
* @subpackage core
*/
class Aggregate extends ViewableData {
private static $cache = null;
/** Build & cache the cache object */
protected static function cache() {
return self::$cache ? self::$cache : (self::$cache = SS_Cache::factory('aggregate'));
}
/**
* Clear the aggregate cache for a given type, or pass nothing to clear all aggregate caches.
* {@link $class} is just effective if the cache backend supports tags.
*/
public static function flushCache($class=null) {
$cache = self::cache();
$capabilities = $cache->getBackend()->getCapabilities();
if($capabilities['tags'] && (!$class || $class == 'DataObject')) {
$cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('aggregate'));
} elseif($capabilities['tags']) {
$tags = ClassInfo::ancestry($class);
foreach($tags as &$tag) {
$tag = preg_replace('/[^a-zA-Z0-9_]/', '_', $tag);
}
$cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, $tags);
} else {
$cache->clean(Zend_Cache::CLEANING_MODE_ALL);
}
}
/**
* Constructor
*
* @deprecated 3.1 Use DataList to aggregate data
*
* @param string $type The DataObject type we are building an aggregate for
* @param string $filter (optional) An SQL filter to apply to the selected rows before calculating the aggregate
*/
public function __construct($type, $filter = '') {
Deprecation::notice('3.1', 'Call aggregate methods on a DataList directly instead. In templates'
. ' an example of the new syntax is &lt% cached List(Member).max(LastEdited) %&gt instead'
. ' (check partial-caching.md documentation for more details.)');
$this->type = $type;
$this->filter = $filter;
parent::__construct();
}
/**
* Build the SQLSelect to calculate the aggregate
* This is a seperate function so that subtypes of Aggregate can change just this bit
* @param string $attr - the SQL field statement for selection (i.e. "MAX(LastUpdated)")
* @return SQLSelect
*/
protected function query($attr) {
$query = DataList::create($this->type)->where($this->filter);
$query->setSelect($attr);
$query->setOrderBy(array());
$singleton->extend('augmentSQL', $query);
return $query;
}
/**
* Entry point for being called from a template.
*
* This gets the aggregate function
*
*/
public function XML_val($name, $args = null, $cache = false) {
$func = strtoupper( strpos($name, 'get') === 0 ? substr($name, 3) : $name );
$attribute = $args ? $args[0] : 'ID';
$table = null;
foreach (ClassInfo::ancestry($this->type, true) as $class) {
$fields = DataObject::database_fields($class, false);
if (array_key_exists($attribute, $fields)) { $table = $class; break; }
}
if (!$table) user_error("Couldn't find table for field $attribute in type {$this->type}", E_USER_ERROR);
$query = $this->query("$func(\"$table\".\"$attribute\")");
// Cache results of this specific SQL query until flushCache() is triggered.
$sql = $query->sql($parameters);
$cachekey = sha1($sql.'-'.var_export($parameters, true));
$cache = self::cache();
if (!($result = $cache->load($cachekey))) {
$result = (string)$query->execute()->value(); if (!$result) $result = '0';
$cache->save($result, null, array('aggregate', preg_replace('/[^a-zA-Z0-9_]/', '_', $this->type)));
}
return $result;
}
/**
* Entry point for being called from PHP.
*/
public function __call($method, $arguments) {
return $this->XML_val($method, $arguments);
}
}
/**
* A subclass of Aggregate that calculates aggregates for the result of a has_many query.
*
* @author hfried
* @package framework
* @subpackage core
*/
class Aggregate_Relationship extends Aggregate {
/**
* Constructor
*
* @param DataObject $object The object that has_many somethings that we're calculating the aggregate for
* @param string $relationship The name of the relationship
* @param string $filter (optional) An SQL filter to apply to the relationship rows before calculating the
* aggregate
*/
public function __construct($object, $relationship, $filter = '') {
$this->object = $object;
$this->relationship = $relationship;
$this->has_many = $object->has_many($relationship);
$this->many_many = $object->many_many($relationship);
if (!$this->has_many && !$this->many_many) {
user_error("Could not find relationship $relationship on object class {$object->class} in"
. " Aggregate Relationship", E_USER_ERROR);
}
parent::__construct($this->has_many ? $this->has_many : $this->many_many[1], $filter);
}
protected function query($attr) {
if ($this->has_many) {
$query = $this->object->getComponentsQuery($this->relationship, $this->filter);
}
else {
$query = $this->object->getManyManyComponentsQuery($this->relationship, $this->filter);
}
$query->setSelect($attr);
$query->setGroupBy(array());
$singleton = singleton($this->type);
$singleton->extend('augmentSQL', $query);
return $query;
}
}

View File

@ -1602,14 +1602,6 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
->sort($sort);
}
/**
* @deprecated 3.1 Use getComponents to get a filtered DataList for an object's relation
*/
public function getComponentsQuery($componentName, $filter = "", $sort = "", $join = "", $limit = "") {
Deprecation::notice('3.1', "Use getComponents to get a filtered DataList for an object's relation");
return $this->getComponents($componentName, $filter, $sort, $join, $limit);
}
/**
* Find the foreign class of a relation on this DataObject, regardless of the relation type.
*
@ -2994,36 +2986,6 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
return $result;
}
/**
* @deprecated 3.1 Use DataList::create and DataList to do your querying
*/
public function Aggregate($class = null) {
Deprecation::notice('3.1', 'Call aggregate methods on a DataList directly instead. In templates'
. ' an example of the new syntax is &lt% cached List(Member).max(LastEdited) %&gt instead'
. ' (check partial-caching.md documentation for more details.)');
if($class) {
$list = new DataList($class);
$list->setDataModel(DataModel::inst());
} else if(isset($this)) {
$list = new DataList(get_class($this));
$list->setDataModel($this->model);
} else {
throw new \InvalidArgumentException("DataObject::aggregate() must be called as an instance method or passed"
. " a classname");
}
return $list;
}
/**
* @deprecated 3.1 Use DataList::create and DataList to do your querying
*/
public function RelationshipAggregate($relationship) {
Deprecation::notice('3.1', 'Call aggregate methods on a relationship directly instead.');
return $this->$relationship();
}
/**
* Return the first item matching the given query.
* All calls to get_one() are cached.
@ -3072,8 +3034,6 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
* @return DataObject $this
*/
public function flushCache($persistent = true) {
if($persistent) Aggregate::flushCache($this->class);
if($this->class == 'DataObject') {
DataObject::$_cache_get_one = array();
return $this;

View File

@ -1,52 +0,0 @@
<?php
/**
* @package framework
* @subpackage search
*/
/**
* Checks if a value is in a given set.
* SQL syntax used: Column IN ('val1','val2')
* @deprecated 3.1 Use ExactMatchFilter instead
*
* @package framework
* @subpackage search
*/
class ExactMatchMultiFilter extends SearchFilter {
function __construct($fullName, $value = false, array $modifiers = array()) {
Deprecation::notice('3.1', 'Use ExactMatchFilter instead.');
parent::__construct($fullName, $value, $modifiers);
}
public function apply(DataQuery $query) {
if (!is_array($this->getValue())) {
$values = explode(',',$this->getValue());
} else {
$values = $this->getValue();
}
$filter = new ExactMatchFilter($this->getFullName(), $values, $this->getModifiers());
return $filter->apply($query);
}
protected function applyOne(DataQuery $query) {
/* NO OP */
}
public function exclude(DataQuery $query) {
if (!is_array($this->getValue())) {
$values = explode(',',$this->getValue());
} else {
$values = $this->getValue();
}
$filter = new ExactMatchFilter($this->getFullName(), $values, $this->getModifiers());
return $filter->exclude($query);
}
protected function excludeOne(DataQuery $query) {
/* NO OP */
}
public function isEmpty() {
return $this->getValue() === array() || $this->getValue() === null || $this->getValue() === '';
}
}

View File

@ -1,34 +0,0 @@
<?php
/**
* Matches on rows where the field is not equal to the given value.
*
* @deprecated 3.1 Use ExactMatchFilter:not instead
* @package framework
* @subpackage search
*/
class NegationFilter extends SearchFilter {
function __construct($fullName, $value = false, array $modifiers = array()) {
Deprecation::notice('3.1', 'Use ExactMatchFilter:not instead.');
$modifiers[] = 'not';
parent::__construct($fullName, $value, $modifiers);
}
public function apply(DataQuery $query) {
$filter = new ExactMatchFilter($this->getFullName(), $this->getValue(), $this->getModifiers());
return $filter->apply($query);
}
protected function applyOne(DataQuery $query) {
/* NO OP */
}
public function exclude(DataQuery $query) {
$filter = new ExactMatchFilter($this->getFullName(), $this->getValue(), $this->getModifiers());
return $filter->exclude($query);
}
protected function excludeOne(DataQuery $query) {
/* NO OP */
}
}

View File

@ -1,52 +0,0 @@
<?php
/**
* @package framework
* @subpackage search
*/
/**
* Checks if a value starts with one of the items of in a given set.
* @deprecated 3.1 Use StartsWithFilter instead
*
* @todo Add negation (NOT IN)6
* @package framework
* @subpackage search
*/
class StartsWithMultiFilter extends SearchFilter {
function __construct($fullName, $value = false, array $modifiers = array()) {
Deprecation::notice('3.1', 'Use StartsWithFilter instead.');
parent::__construct($fullName, $value, $modifiers);
}
public function apply(DataQuery $query) {
if (!is_array($this->getValue())) {
$values = explode(',',$this->getValue());
} else {
$values = $this->getValue();
}
$filter = new StartsWithFilter($this->getFullName(), $values, $this->getModifiers());
return $filter->apply($query);
}
protected function applyOne(DataQuery $query) {
/* NO OP */
}
public function exclude(DataQuery $query) {
if (!is_array($this->getValue())) {
$values = explode(',',$this->getValue());
} else {
$values = $this->getValue();
}
$filter = new StartsWithFilter($this->getFullName(), $values, $this->getModifiers());
return $filter->exclude($query);
}
protected function excludeOne(DataQuery $query) {
/* NO OP */
}
public function isEmpty() {
return $this->getValue() === array() || $this->getValue() === null || $this->getValue() === '';
}
}

View File

@ -554,11 +554,11 @@ class Permission extends DataObject implements TemplateGlobalProvider {
return $a['sort'] < $b['sort'] ? -1 : 1;
}
}
/**
* add a permission represented by the $code to the {@link slef::$hidden_permissions} list
*
* @deprecated 3.1 Use "Permission.hidden_permissions" config setting instead
* @deprecated 3.2 Use "Permission.hidden_permissions" config setting instead
* @param $code string - the permissions code
* @return void
*/
@ -571,7 +571,7 @@ class Permission extends DataObject implements TemplateGlobalProvider {
/**
* remove a permission represented by the $code from the {@link slef::$hidden_permissions} list
*
* @deprecated 3.1 Use "Permission.hidden_permissions" config setting instead
* @deprecated 3.2 Use "Permission.hidden_permissions" config setting instead
* @param $code string - the permissions code
* @return void
*/

View File

@ -74,15 +74,4 @@ class RandomGenerator {
return hash($algorithm, $this->generateEntropy());
}
/**
* @deprecated 3.1
*/
public function generateHash($algorithm = 'whirlpool') {
Deprecation::notice('3.1',
'RandomGenerator::generateHash is deprecated because of a confusing name that hints the output is secure, '.
'while in fact it is just a random string. Use RandomGenerator::randomToken instead.',
Deprecation::SCOPE_METHOD);
return $this->randomToken($algorithm);
}
}

View File

@ -1,17 +0,0 @@
<?php
/**
* Classes that must be run daily extend this class.
*
* Please note: Subclasses of this task aren't extecuted automatically,
* they need to be triggered by an external automation tool like unix cron.
* See {@link ScheduledTask} for details.
*
* @deprecated 3.1
*
* @todo Improve documentation
* @package framework
* @subpackage cron
*/
class DailyTask extends ScheduledTask {
}

View File

@ -1,16 +0,0 @@
<?php
/**
* Classes that must be run hourly extend this class
*
* Please note: Subclasses of this task aren't extecuted automatically,
* they need to be triggered by an external automation tool like unix cron.
* See {@link ScheduledTask} for details.
*
* @deprecated 3.1
*
* @package framework
* @subpackage cron
*/
class HourlyTask extends ScheduledTask {
}

View File

@ -1,16 +0,0 @@
<?php
/**
* Classes that must be run monthly extend this class
*
* Please note: Subclasses of this task aren't extecuted automatically,
* they need to be triggered by an external automation tool like unix cron.
* See {@link ScheduledTask} for details.
*
* @deprecated 3.1
*
* @package framework
* @subpackage cron
*/
class MonthlyTask extends ScheduledTask {
}

View File

@ -1,16 +0,0 @@
<?php
/**
* Classes that must be run quarter hourly extend this class
*
* Please note: Subclasses of this task aren't extecuted automatically,
* they need to be triggered by an external automation tool like unix cron.
* See {@link ScheduledTask} for details.
*
* @deprecated 3.1
*
* @package framework
* @subpackage cron
*/
class QuarterHourlyTask extends ScheduledTask {
}

View File

@ -1,73 +0,0 @@
<?php
/**
* Abstract task representing scheudled tasks.
*
* Scheduled tasks are tasks that are run at a certain time or set interval. For example, notify a page owner that
* their page is about to expire. Scheduled tasks are implemented as singleton instances and a single
* instance is responsibly directly or indirectly for executing all tasks that should be run at that time.
*
* You can use the different subclasses {@link HourlyTask}, {@link DailyTask},
* {@link WeeklyTask} to determine when a task should be run,
* and use automation tools such as unix cron to trigger them.
*
* <b>Usage</b>
*
* Implement a daily task by extending DailyTask and implementing process().
*
* <code>
* class MyTask extends DailyTask {
* function process() {
* // implement your task here
* }
* }
* </code>
*
* You can also implement the index() method to overwrite which singleton classes are instantiated and processed.
* By default, all subclasses of the task are instantiated and used. For the DailyTask class, this means
* that an instance of each subclass of DailyTask will be created.
*
* You can test your task from the command line by running the following command
* (replace <MyTask> is the classname of your task):
*
* <code>framework/cli-script.php /<MyTask></code>
*
* To perform all Daily tasks, run from the command line:
*
* <code>cli-script.php /DailyTask</code>
*
* <b>Example Cron Definition</b>
*
* <code>
* # Quarter-hourly task (every hour at 25 minutes past) (remove space between first * and /15)
* * /15 * * * * www-data /webroot/framework/cli-script.php /QuarterHourlyTask > /var/log/quarterhourlytask.log
*
* # HourlyTask (every hour at 25 minutes past)
* 25 * * * * www-data /webroot/framework/cli-script.php /HourlyTask > /var/log/hourlytask.log
*
* # DailyTask (every day at 6:25am)
* 25 6 * * * www-data /webroot/framework/cli-script.php /DailyTask > /var/log/dailytask.log
*
* # WeelkyTask (every Monday at 6:25am)
* 25 6 1 * * www-data /webroot/framework/cli-script.php /WeeklyTask > /var/log/weeklytask.log
* </code>
*
* @deprecated 3.1
*
* @todo Improve documentation
* @package framework
* @subpackage cron
*/
abstract class ScheduledTask extends CliController {
// this class exists as a logical extension
public function init() {
Deprecation::notice(
'3.1',
'ScheduledTask, QuarterHourlyTask, HourlyTask, DailyTask, MonthlyTask, WeeklyTask and ' .
'YearlyTask are deprecated, please extend from BuildTask or CliController, ' .
'and invoke them in self-defined frequencies through Unix cronjobs etc.'
);
parent::init();
}
}

View File

@ -1,16 +0,0 @@
<?php
/**
* Classes that must be run weekly extend this class
*
* Please note: Subclasses of this task aren't extecuted automatically,
* they need to be triggered by an external automation tool like unix cron.
* See {@link ScheduledTask} for details.
*
* @deprecated 3.1
*
* @package framework
* @subpackage cron
*/
class WeeklyTask extends ScheduledTask {
}

View File

@ -1,16 +0,0 @@
<?php
/**
* Classes that must be run yearly extend this class
*
* Please note: Subclasses of this task aren't extecuted automatically,
* they need to be triggered by an external automation tool like unix cron.
* See {@link ScheduledTask} for details.
*
* @deprecated 3.1
*
* @package framework
* @subpackage cron
*/
class YearlyTask extends ScheduledTask {
}

View File

@ -1,213 +0,0 @@
<?php
/*
* A hierarchy of data types, to...
*
* @deprecated. This is testing`
* {@link DataObject::Aggregate()} and {@link DataObject::RelationshipAggregate()}
* which are deprecated. Aggregates are handled directly by DataList instead.
* This test should be removed or merged into DataListTest once those functions are
* removed from DataObject.
*/
class AggregateTest_Foo extends DataObject implements TestOnly {
private static $db = array(
"Foo" => "Int"
);
private static $has_one = array('Bar' => 'AggregateTest_Bar');
private static $belongs_many_many = array('Bazi' => 'AggregateTest_Baz');
}
class AggregateTest_Fab extends AggregateTest_Foo {
private static $db = array(
"Fab" => "Int"
);
}
class AggregateTest_Fac extends AggregateTest_Fab {
private static $db = array(
"Fac" => "Int"
);
}
class AggregateTest_Bar extends DataObject implements TestOnly {
private static $db = array(
"Bar" => "Int"
);
private static $has_many = array(
"Foos" => "AggregateTest_Foo"
);
}
class AggregateTest_Baz extends DataObject implements TestOnly {
private static $db = array(
"Baz" => "Int"
);
private static $many_many = array(
"Foos" => "AggregateTest_Foo"
);
}
class AggregateTest extends SapphireTest {
protected static $fixture_file = 'AggregateTest.yml';
protected $extraDataObjects = array(
'AggregateTest_Foo',
'AggregateTest_Fab',
'AggregateTest_Fac',
'AggregateTest_Bar',
'AggregateTest_Baz'
);
protected $originalDeprecation;
public function setUp() {
parent::setUp();
// This test tests code that was deprecated after 2.4
$this->originalDeprecation = Deprecation::dump_settings();
Deprecation::notification_version('2.4');
}
public function tearDown() {
parent::tearDown();
Deprecation::restore_settings($this->originalDeprecation);
}
/**
* Test basic aggregation on a passed type
*/
public function testTypeSpecifiedAggregate() {
$foo = $this->objFromFixture('AggregateTest_Foo', 'foo1');
// Template style access
$this->assertEquals($foo->Aggregate('AggregateTest_Foo')->XML_val('Max', array('Foo')), 9);
$this->assertEquals($foo->Aggregate('AggregateTest_Fab')->XML_val('Max', array('Fab')), 3);
// PHP style access
$this->assertEquals($foo->Aggregate('AggregateTest_Foo')->Max('Foo'), 9);
$this->assertEquals($foo->Aggregate('AggregateTest_Fab')->Max('Fab'), 3);
}
/* */
/**
* Test basic aggregation on a given dataobject
* @return unknown_type
*/
public function testAutoTypeAggregate() {
$foo = $this->objFromFixture('AggregateTest_Foo', 'foo1');
$fab = $this->objFromFixture('AggregateTest_Fab', 'fab1');
// Template style access
$this->assertEquals($foo->Aggregate()->XML_val('Max', array('Foo')), 9);
$this->assertEquals($fab->Aggregate()->XML_val('Max', array('Fab')), 3);
// PHP style access
$this->assertEquals($foo->Aggregate()->Max('Foo'), 9);
$this->assertEquals($fab->Aggregate()->Max('Fab'), 3);
}
/* */
/**
* Test base-level field access - was failing due to use of custom_database_fields, not just database_fields
* @return unknown_type
*/
public function testBaseFieldAggregate() {
$foo = $this->objFromFixture('AggregateTest_Foo', 'foo1');
$this->assertEquals(
$this->formatDate($foo->Aggregate('AggregateTest_Foo')->Max('LastEdited')),
$this->formatDate(DataObject::get_one('AggregateTest_Foo', '', '', '"LastEdited" DESC')->LastEdited)
);
$this->assertEquals(
$this->formatDate($foo->Aggregate('AggregateTest_Foo')->Max('Created')),
$this->formatDate(DataObject::get_one('AggregateTest_Foo', '', '', '"Created" DESC')->Created)
);
}
/* */
/**
* Test aggregation takes place on the passed type & it's children only
*/
public function testChildAggregate() {
$foo = $this->objFromFixture('AggregateTest_Foo', 'foo1');
// For base classes, aggregate is calculcated on it and all children classes
$this->assertEquals($foo->Aggregate('AggregateTest_Foo')->Max('Foo'), 9);
// For subclasses, aggregate is calculated for that subclass and it's children only
$this->assertEquals($foo->Aggregate('AggregateTest_Fab')->Max('Foo'), 9);
$this->assertEquals($foo->Aggregate('AggregateTest_Fac')->Max('Foo'), 6);
}
/* */
/**
* Test aggregates are cached properly
*/
public function testCache() {
$this->markTestIncomplete();
}
/* */
/**
* Test cache is correctly flushed on write
*/
public function testCacheFlushing() {
$foo = $this->objFromFixture('AggregateTest_Foo', 'foo1');
$fab = $this->objFromFixture('AggregateTest_Fab', 'fab1');
// For base classes, aggregate is calculcated on it and all children classes
$this->assertEquals($fab->Aggregate('AggregateTest_Foo')->Max('Foo'), 9);
// For subclasses, aggregate is calculated for that subclass and it's children only
$this->assertEquals($fab->Aggregate('AggregateTest_Fab')->Max('Foo'), 9);
$this->assertEquals($fab->Aggregate('AggregateTest_Fac')->Max('Foo'), 6);
$foo->Foo = 12;
$foo->write();
// For base classes, aggregate is calculcated on it and all children classes
$this->assertEquals($fab->Aggregate('AggregateTest_Foo')->Max('Foo'), 12);
// For subclasses, aggregate is calculated for that subclass and it's children only
$this->assertEquals($fab->Aggregate('AggregateTest_Fab')->Max('Foo'), 9);
$this->assertEquals($fab->Aggregate('AggregateTest_Fac')->Max('Foo'), 6);
$fab->Foo = 15;
$fab->write();
// For base classes, aggregate is calculcated on it and all children classes
$this->assertEquals($fab->Aggregate('AggregateTest_Foo')->Max('Foo'), 15);
// For subclasses, aggregate is calculated for that subclass and it's children only
$this->assertEquals($fab->Aggregate('AggregateTest_Fab')->Max('Foo'), 15);
$this->assertEquals($fab->Aggregate('AggregateTest_Fac')->Max('Foo'), 6);
}
/* */
/**
* Test basic relationship aggregation
*/
public function testRelationshipAggregate() {
$bar1 = $this->objFromFixture('AggregateTest_Bar', 'bar1');
$this->assertEquals($bar1->RelationshipAggregate('Foos')->Max('Foo'), 8);
$baz1 = $this->objFromFixture('AggregateTest_Baz', 'baz1');
$this->assertEquals($baz1->RelationshipAggregate('Foos')->Max('Foo'), 8);
}
/* */
/**
* Copied from DataObject::__construct(), special case for MSSQLDatabase.
*
* @param String
* @return String
*/
protected function formatDate($dateStr) {
$dateStr = preg_replace('/:[0-9][0-9][0-9]([ap]m)$/i', ' \\1', $dateStr);
return date('Y-m-d H:i:s', strtotime($dateStr));
}
}

View File

@ -1,46 +0,0 @@
AggregateTest_Bar:
bar1:
Bar: 1
bar2:
Bar: 2
AggregateTest_Foo:
foo1:
Foo: 1
Bar: =>AggregateTest_Bar.bar1
foo2:
Foo: 2
Bar: =>AggregateTest_Bar.bar1
foo3:
Foo: 3
Bar: =>AggregateTest_Bar.bar2
AggregateTest_Fab:
fab1:
Foo: 7
Fab: 1
Bar: =>AggregateTest_Bar.bar1
fab2:
Foo: 8
Fab: 2
Bar: =>AggregateTest_Bar.bar1
fab3:
Foo: 9
Fab: 3
Bar: =>AggregateTest_Bar.bar2
AggregateTest_Fac:
fac1:
Foo: 4
Fac: 1
fac2:
Foo: 5
Fac: 2
fac3:
Foo: 6
Fac: 3
AggregateTest_Baz:
baz1:
Baz: 1
Foos: =>AggregateTest_Foo.foo1,=>AggregateTest_Foo.foo2,=>AggregateTest_Fab.fab1,=>AggregateTest_Fab.fab2
baz2:
Baz: 2
Foos: =>AggregateTest_Foo.foo3,=>AggregateTest_Fab.fab3