Merge pull request #1022 from simonwelsh/indent-sniff_master

Add codesniffer that ensures indentation is with tabs.
This commit is contained in:
Sam Minnée 2012-12-11 20:46:51 -08:00
commit 0b7ac904c7
107 changed files with 2937 additions and 2923 deletions

View File

@ -22,7 +22,8 @@ before_script:
script:
- phpunit -c phpunit.xml.dist
- phpcs --encoding=utf-8 --tab-width=4 --standard=framework/tests/phpcs -np framework
- phpcs --encoding=utf-8 --tab-width=4 --standard=framework/tests/phpcs/ruleset.xml -np framework
- phpcs --encoding=utf-8 --standard=framework/tests/phpcs/tabs.xml -np framework
branches:
except:

View File

@ -26,15 +26,15 @@ class CMSProfileController extends LeftAndMain {
$form->Fields()->push(new HiddenField('ID', null, Member::currentUserID()));
$form->Actions()->push(
FormAction::create('save',_t('CMSMain.SAVE', 'Save'))
->addExtraClass('ss-ui-button ss-ui-action-constructive')
->setAttribute('data-icon', 'accept')
->setUseButtonTag(true)
);
$form->Actions()->removeByName('delete');
$form->setValidator(new Member_Validator());
$form->setTemplate('Form');
$form->setAttribute('data-pjax-fragment', null);
if($form->Fields()->hasTabset()) $form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet');
->addExtraClass('ss-ui-button ss-ui-action-constructive')
->setAttribute('data-icon', 'accept')
->setUseButtonTag(true)
);
$form->Actions()->removeByName('delete');
$form->setValidator(new Member_Validator());
$form->setTemplate('Form');
$form->setAttribute('data-pjax-fragment', null);
if($form->Fields()->hasTabset()) $form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet');
$form->addExtraClass('member-profile-form root-form cms-edit-form cms-panel-padded center');
return $form;

View File

@ -296,7 +296,7 @@ abstract class ModelAdmin extends LeftAndMain {
*
* @return array Map of model class names to importer instances
*/
public function getModelImporters() {
public function getModelImporters() {
$importerClasses = $this->stat('model_importers');
// fallback to all defined models if not explicitly defined

View File

@ -153,8 +153,8 @@
"select_limit" : 1,
'initially_select': [this.find('.current').attr('id')]
},
"crrm": {
'move': {
"crrm": {
'move': {
// Check if a node is allowed to be moved.
// Caution: Runs on every drag over a new node
'check_move': function(data) {

View File

@ -301,7 +301,7 @@ jQuery.noConflict();
*/
submitForm: function(form, button, callback, ajaxOptions) {
var self = this;
// look for save button
if(!button) button = this.find('.Actions :submit[name=action_save]');
// default to first button if none given - simulates browser behaviour

View File

@ -170,8 +170,8 @@
convertUrlToDataUrl: function( absUrl ) {
var u = path.parseUrl( absUrl );
if ( path.isEmbeddedPage( u ) ) {
// For embedded pages, remove the dialog hash key as in getFilePath(),
// otherwise the Data Url won't match the id of the embedded Page.
// For embedded pages, remove the dialog hash key as in getFilePath(),
// otherwise the Data Url won't match the id of the embedded Page.
return u.hash.split( dialogHashKey )[0].replace( /^#/, "" );
} else if ( path.isSameDomain( u, documentBase ) ) {
return u.hrefNoHash.replace( documentBase.domain, "" );
@ -232,4 +232,4 @@
};
$.path = path;
}(jQuery));
}(jQuery));

View File

@ -30,9 +30,9 @@ class FormEncodedDataFormatter extends XMLDataFormatter {
}
public function convertStringToArray($strData) {
$postArray = array();
parse_str($strData, $postArray);
return $postArray;
$postArray = array();
parse_str($strData, $postArray);
return $postArray;
//TODO: It would be nice to implement this function in Convert.php
//return Convert::querystr2array($strData);
}

View File

@ -106,9 +106,9 @@ class RSSFeed extends ViewableData {
* every time the representation does
*/
public function __construct(SS_List $entries, $link, $title,
$description = null, $titleField = "Title",
$descriptionField = "Content", $authorField = null,
$lastModified = null, $etag = null) {
$description = null, $titleField = "Title",
$descriptionField = "Content", $authorField = null,
$lastModified = null, $etag = null) {
$this->entries = $entries;
$this->link = $link;
$this->description = $description;
@ -270,7 +270,7 @@ class RSSFeed_Entry extends ViewableData {
* Create a new RSSFeed entry.
*/
public function __construct($entry, $titleField, $descriptionField,
$authorField) {
$authorField) {
$this->failover = $entry;
$this->titleField = $titleField;
$this->descriptionField = $descriptionField;

View File

@ -65,7 +65,7 @@ class RestfulService extends ViewableData {
* @param string $password The proxy auth password
* @param boolean $socks Set true to use socks5 proxy instead of http
*/
public function setProxy($proxy, $port = 80, $user = "", $password = "", $socks = false) {
public function setProxy($proxy, $port = 80, $user = "", $password = "", $socks = false) {
$this->proxy = array(
CURLOPT_PROXY => $proxy,
CURLOPT_PROXYUSERPWD => "{$user}:{$password}",
@ -337,14 +337,14 @@ class RestfulService extends ViewableData {
$child_count++;
$k = ($parent == "") ? (string)$key : $parent . "_" . (string)$key;
if($this->getRecurseValues($value,$data,$k) == 0){ // no childern, aka "leaf node"
$conv_value = Convert::raw2xml($value);
$conv_value = Convert::raw2xml($value);
}
//Review the fix for similar node names overriding it's predecessor
if(array_key_exists($k, $data) == true) {
$data[$k] = $data[$k] . ",". $conv_value;
}
else {
$data[$k] = $conv_value;
$data[$k] = $conv_value;
}

View File

@ -37,19 +37,19 @@ chdir(dirname($_SERVER['SCRIPT_FILENAME']));
* fourth => val
*/
if(isset($_SERVER['argv'][2])) {
$args = array_slice($_SERVER['argv'],2);
if(!isset($_GET)) $_GET = array();
if(!isset($_REQUEST)) $_REQUEST = array();
foreach($args as $arg) {
if(strpos($arg,'=') == false) {
$_GET['args'][] = $arg;
} else {
$newItems = array();
parse_str( (substr($arg,0,2) == '--') ? substr($arg,2) : $arg, $newItems );
$_GET = array_merge($_GET, $newItems);
}
}
$_REQUEST = array_merge($_REQUEST, $_GET);
$args = array_slice($_SERVER['argv'],2);
if(!isset($_GET)) $_GET = array();
if(!isset($_REQUEST)) $_REQUEST = array();
foreach($args as $arg) {
if(strpos($arg,'=') == false) {
$_GET['args'][] = $arg;
} else {
$newItems = array();
parse_str( (substr($arg,0,2) == '--') ? substr($arg,2) : $arg, $newItems );
$_GET = array_merge($_GET, $newItems);
}
}
$_REQUEST = array_merge($_REQUEST, $_GET);
}
// Set 'url' GET parameter
@ -76,7 +76,7 @@ DB::connect($databaseConfig);
$url = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : null;
if(!$url) {
echo 'Please specify an argument to cli-script.php/sake. For more information, visit'
. ' http://doc.silverstripe.org/framework/en/topics/commandline';
. ' http://doc.silverstripe.org/framework/en/topics/commandline';
die();
}

View File

@ -100,8 +100,8 @@ if(defined('SS_DATABASE_USERNAME') && defined('SS_DATABASE_PASSWORD')) {
}
// For schema enabled drivers:
if(defined('SS_DATABASE_SCHEMA'))
$databaseConfig["schema"] = SS_DATABASE_SCHEMA;
if(defined('SS_DATABASE_SCHEMA'))
$databaseConfig["schema"] = SS_DATABASE_SCHEMA;
}
if(defined('SS_SEND_ALL_EMAILS_TO')) {

View File

@ -45,7 +45,7 @@ class ContentNegotiator {
* that need to specify the character set make use of this function.
*/
public static function get_encoding() {
return self::$encoding;
return self::$encoding;
}
/**
@ -96,7 +96,7 @@ class ContentNegotiator {
} else {
// The W3C validator doesn't send an HTTP_ACCEPT header, but it can support xhtml. We put this special
// case in here so that designers don't get worried that their templates are HTML4.
if(isset($_SERVER['HTTP_USER_AGENT']) && substr($_SERVER['HTTP_USER_AGENT'], 0, 14) == 'W3C_Validator/') {
if(isset($_SERVER['HTTP_USER_AGENT']) && substr($_SERVER['HTTP_USER_AGENT'], 0, 14) == 'W3C_Validator/') {
$chosenFormat = "xhtml";
} else {

View File

@ -164,7 +164,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider {
Debug::message("Request handler $body->class object to $this->class controller;"
. "rendering with template returned by $body->class::getViewer()");
}
$body = $body->getViewer($request->latestParam('Action'))->process($body);
$body = $body->getViewer($request->latestParam('Action'))->process($body);
}
$this->response->setBody($body);
@ -367,7 +367,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider {
return $template->process($obj);
}
/**
* Call this to disable site-wide basic authentication for a specific contoller.
* This must be called before Controller::init(). That is, you must call it in your controller's

View File

@ -348,8 +348,8 @@ class Director implements TemplateGlobalProvider {
$url = dirname($_SERVER['REQUEST_URI'] . 'x') . '/' . $url;
}
if(substr($url,0,4) != "http") {
if($url[0] != "/") $url = Director::baseURL() . $url;
if(substr($url,0,4) != "http") {
if($url[0] != "/") $url = Director::baseURL() . $url;
// Sometimes baseURL() can return a full URL instead of just a path
if(substr($url,0,4) != "http") $url = self::protocolAndHost() . $url;
}
@ -630,21 +630,21 @@ class Director implements TemplateGlobalProvider {
/**
* Returns the Absolute URL of the site root.
*/
public static function absoluteBaseURL() {
return Director::absoluteURL(Director::baseURL());
}
public static function absoluteBaseURL() {
return Director::absoluteURL(Director::baseURL());
}
/**
* Returns the Absolute URL of the site root, embedding the current basic-auth credentials into the URL.
*/
public static function absoluteBaseURLWithAuth() {
public static function absoluteBaseURLWithAuth() {
$s = "";
$login = "";
if(isset($_SERVER['PHP_AUTH_USER'])) $login = "$_SERVER[PHP_AUTH_USER]:$_SERVER[PHP_AUTH_PW]@";
if(isset($_SERVER['PHP_AUTH_USER'])) $login = "$_SERVER[PHP_AUTH_USER]:$_SERVER[PHP_AUTH_PW]@";
return Director::protocol() . $login . $_SERVER['HTTP_HOST'] . Director::baseURL();
}
return Director::protocol() . $login . $_SERVER['HTTP_HOST'] . Director::baseURL();
}
/**
* Force the site to run on SSL.
@ -843,7 +843,7 @@ class Director implements TemplateGlobalProvider {
$result = $_GET['isDev'];
} else {
if($firstTimeCheckingGetVar && DB::connection_attempted()) {
echo "<p style=\"padding: 3px; margin: 3px; background-color: orange;
echo "<p style=\"padding: 3px; margin: 3px; background-color: orange;
color: white; font-weight: bold\">Sorry, you can't use ?isDev=1 until your
Member and Group tables database are available. Perhaps your database
connection is failing?</p>";

View File

@ -171,8 +171,8 @@ class HTTP {
if($regexes) foreach($regexes as $regex) {
if(preg_match_all($regex, $content, $matches)) {
$result = array_merge_recursive($result, (isset($matches[2]) ? $matches[2] : $matches[1]));
}
}
}
}
return count($result) ? $result : null;
}

View File

@ -296,21 +296,21 @@ class SS_HTTPRequest implements ArrayAccess {
public function getURL($includeGetVars = false) {
$url = ($this->getExtension()) ? $this->url . '.' . $this->getExtension() : $this->url;
if ($includeGetVars) {
// if we don't unset $vars['url'] we end up with /my/url?url=my/url&foo=bar etc
$vars = $this->getVars();
unset($vars['url']);
if ($includeGetVars) {
// if we don't unset $vars['url'] we end up with /my/url?url=my/url&foo=bar etc
$vars = $this->getVars();
unset($vars['url']);
if (count($vars)) {
$url .= '?' . http_build_query($vars);
}
}
else if(strpos($url, "?") !== false) {
$url = substr($url, 0, strpos($url, "?"));
}
if (count($vars)) {
$url .= '?' . http_build_query($vars);
}
}
else if(strpos($url, "?") !== false) {
$url = substr($url, 0, strpos($url, "?"));
}
return $url;
return $url;
}
/**
@ -501,9 +501,9 @@ class SS_HTTPRequest implements ArrayAccess {
* @return string
*/
public function shiftAllParams() {
$keys = array_keys($this->allParams);
$values = array_values($this->allParams);
$value = array_shift($values);
$keys = array_keys($this->allParams);
$values = array_values($this->allParams);
$value = array_shift($values);
// push additional unparsed URL parts onto the parameter stack
if(array_key_exists($this->unshiftedButParsedParts, $this->dirParts)) {
@ -636,10 +636,10 @@ class SS_HTTPRequest implements ArrayAccess {
*/
public function getIP() {
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
//check ip from share internet
//check ip from share internet
return $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
//to check ip is pass from proxy
//to check ip is pass from proxy
return $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif(isset($_SERVER['REMOTE_ADDR'])) {
return $_SERVER['REMOTE_ADDR'];
@ -655,12 +655,12 @@ class SS_HTTPRequest implements ArrayAccess {
* @return array
*/
public function getAcceptMimetypes($includeQuality = false) {
$mimetypes = array();
$mimetypesWithQuality = explode(',',$this->getHeader('Accept'));
foreach($mimetypesWithQuality as $mimetypeWithQuality) {
$mimetypes[] = ($includeQuality) ? $mimetypeWithQuality : preg_replace('/;.*/', '', $mimetypeWithQuality);
}
return $mimetypes;
$mimetypes = array();
$mimetypesWithQuality = explode(',',$this->getHeader('Accept'));
foreach($mimetypesWithQuality as $mimetypeWithQuality) {
$mimetypes[] = ($includeQuality) ? $mimetypeWithQuality : preg_replace('/;.*/', '', $mimetypeWithQuality);
}
return $mimetypes;
}
/**

View File

@ -303,37 +303,37 @@ class SS_HTTPResponse_Exception extends Exception {
* $statusDescription will be the HTTP status of the resulting response.
* @see SS_HTTPResponse::__construct();
*/
public function __construct($body = null, $statusCode = null, $statusDescription = null) {
if($body instanceof SS_HTTPResponse) {
// statusCode and statusDescription should override whatever is passed in the body
if($statusCode) $body->setStatusCode($statusCode);
public function __construct($body = null, $statusCode = null, $statusDescription = null) {
if($body instanceof SS_HTTPResponse) {
// statusCode and statusDescription should override whatever is passed in the body
if($statusCode) $body->setStatusCode($statusCode);
if($statusDescription) $body->setStatusDescription($statusDescription);
$this->setResponse($body);
} else {
} else {
$response = new SS_HTTPResponse($body, $statusCode, $statusDescription);
// Error responses should always be considered plaintext, for security reasons
$response->addHeader('Content-Type', 'text/plain');
$this->setResponse($response);
}
parent::__construct($this->getResponse()->getBody(), $this->getResponse()->getStatusCode());
}
/**
* @return SS_HTTPResponse
*/
public function getResponse() {
return $this->response;
}
/**
* @param SS_HTTPResponse $response
*/
public function setResponse(SS_HTTPResponse $response) {
$this->response = $response;
}
$this->setResponse($response);
}
parent::__construct($this->getResponse()->getBody(), $this->getResponse()->getStatusCode());
}
/**
* @return SS_HTTPResponse
*/
public function getResponse() {
return $this->response;
}
/**
* @param SS_HTTPResponse $response
*/
public function setResponse(SS_HTTPResponse $response) {
$this->response = $response;
}
}

View File

@ -94,7 +94,7 @@ class RequestHandler extends ViewableData {
* or by defining $allowed_actions in your {@link Form} class.
*/
static $allowed_actions = null;
public function __construct() {
$this->brokenOnConstruct = false;

View File

@ -36,6 +36,6 @@ class AopProxyService {
return $result;
}
}
}
}
}
}

View File

@ -69,18 +69,18 @@ class ArrayLib {
* @todo Improve documentation
*/
public static function array_values_recursive($arr) {
$lst = array();
foreach(array_keys($arr) as $k){
$v = $arr[$k];
if (is_scalar($v)) {
$lst[] = $v;
} elseif (is_array($v)) {
$lst = array_merge( $lst,
self::array_values_recursive($v)
);
}
}
return $lst;
$lst = array();
foreach(array_keys($arr) as $k){
$v = $arr[$k];
if (is_scalar($v)) {
$lst[] = $v;
} elseif (is_array($v)) {
$lst = array_merge( $lst,
self::array_values_recursive($v)
);
}
}
return $lst;
}
/**
@ -110,12 +110,12 @@ class ArrayLib {
*/
public static function is_associative($arr) {
if(is_array($arr) && ! empty($arr)) {
for($iterator = count($arr) - 1; $iterator; $iterator--) {
if (!array_key_exists($iterator, $arr)) return true;
}
return !array_key_exists(0, $arr);
}
return false;
for($iterator = count($arr) - 1; $iterator; $iterator--) {
if (!array_key_exists($iterator, $arr)) return true;
}
return !array_key_exists(0, $arr);
}
return false;
}
/**

View File

@ -27,21 +27,21 @@ define('USE_ASSERTS', function_exists('assert'));
* @access private
*/
class _DiffOp {
var $type;
var $orig;
var $final;
var $type;
var $orig;
var $final;
public function reverse() {
trigger_error("pure virtual", E_USER_ERROR);
}
public function reverse() {
trigger_error("pure virtual", E_USER_ERROR);
}
public function norig() {
return $this->orig ? sizeof($this->orig) : 0;
}
public function norig() {
return $this->orig ? sizeof($this->orig) : 0;
}
public function nfinal() {
return $this->final ? sizeof($this->final) : 0;
}
public function nfinal() {
return $this->final ? sizeof($this->final) : 0;
}
}
/**
@ -50,18 +50,18 @@ class _DiffOp {
* @access private
*/
class _DiffOp_Copy extends _DiffOp {
var $type = 'copy';
var $type = 'copy';
public function _DiffOp_Copy ($orig, $final = false) {
if (!is_array($final))
$final = $orig;
$this->orig = $orig;
$this->final = $final;
}
public function _DiffOp_Copy ($orig, $final = false) {
if (!is_array($final))
$final = $orig;
$this->orig = $orig;
$this->final = $final;
}
public function reverse() {
return new _DiffOp_Copy($this->final, $this->orig);
}
public function reverse() {
return new _DiffOp_Copy($this->final, $this->orig);
}
}
/**
@ -70,16 +70,16 @@ class _DiffOp_Copy extends _DiffOp {
* @access private
*/
class _DiffOp_Delete extends _DiffOp {
var $type = 'delete';
var $type = 'delete';
public function _DiffOp_Delete ($lines) {
$this->orig = $lines;
$this->final = false;
}
public function _DiffOp_Delete ($lines) {
$this->orig = $lines;
$this->final = false;
}
public function reverse() {
return new _DiffOp_Add($this->orig);
}
public function reverse() {
return new _DiffOp_Add($this->orig);
}
}
/**
@ -88,16 +88,16 @@ class _DiffOp_Delete extends _DiffOp {
* @access private
*/
class _DiffOp_Add extends _DiffOp {
var $type = 'add';
var $type = 'add';
public function _DiffOp_Add ($lines) {
$this->final = $lines;
$this->orig = false;
}
public function _DiffOp_Add ($lines) {
$this->final = $lines;
$this->orig = false;
}
public function reverse() {
return new _DiffOp_Delete($this->final);
}
public function reverse() {
return new _DiffOp_Delete($this->final);
}
}
/**
@ -106,16 +106,16 @@ class _DiffOp_Add extends _DiffOp {
* @access private
*/
class _DiffOp_Change extends _DiffOp {
var $type = 'change';
var $type = 'change';
public function _DiffOp_Change ($orig, $final) {
$this->orig = $orig;
$this->final = $final;
}
public function _DiffOp_Change ($orig, $final) {
$this->orig = $orig;
$this->final = $final;
}
public function reverse() {
return new _DiffOp_Change($this->final, $this->orig);
}
public function reverse() {
return new _DiffOp_Change($this->final, $this->orig);
}
}
@ -143,126 +143,126 @@ class _DiffOp_Change extends _DiffOp {
*/
class _DiffEngine
{
public function diff ($from_lines, $to_lines) {
$n_from = sizeof($from_lines);
$n_to = sizeof($to_lines);
public function diff ($from_lines, $to_lines) {
$n_from = sizeof($from_lines);
$n_to = sizeof($to_lines);
$this->xchanged = $this->ychanged = array();
$this->xv = $this->yv = array();
$this->xind = $this->yind = array();
unset($this->seq);
unset($this->in_seq);
unset($this->lcs);
$this->xchanged = $this->ychanged = array();
$this->xv = $this->yv = array();
$this->xind = $this->yind = array();
unset($this->seq);
unset($this->in_seq);
unset($this->lcs);
// Skip leading common lines.
for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) {
if ($from_lines[$skip] != $to_lines[$skip])
break;
$this->xchanged[$skip] = $this->ychanged[$skip] = false;
}
// Skip trailing common lines.
$xi = $n_from; $yi = $n_to;
for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) {
if ($from_lines[$xi] != $to_lines[$yi])
break;
$this->xchanged[$xi] = $this->ychanged[$yi] = false;
}
// Skip leading common lines.
for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) {
if ($from_lines[$skip] != $to_lines[$skip])
break;
$this->xchanged[$skip] = $this->ychanged[$skip] = false;
}
// Skip trailing common lines.
$xi = $n_from; $yi = $n_to;
for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) {
if ($from_lines[$xi] != $to_lines[$yi])
break;
$this->xchanged[$xi] = $this->ychanged[$yi] = false;
}
// Ignore lines which do not exist in both files.
for ($xi = $skip; $xi < $n_from - $endskip; $xi++)
$xhash[$from_lines[$xi]] = 1;
for ($yi = $skip; $yi < $n_to - $endskip; $yi++) {
$line = $to_lines[$yi];
if ( ($this->ychanged[$yi] = empty($xhash[$line])) )
continue;
$yhash[$line] = 1;
$this->yv[] = $line;
$this->yind[] = $yi;
}
for ($xi = $skip; $xi < $n_from - $endskip; $xi++) {
$line = $from_lines[$xi];
if ( ($this->xchanged[$xi] = empty($yhash[$line])) )
continue;
$this->xv[] = $line;
$this->xind[] = $xi;
}
// Ignore lines which do not exist in both files.
for ($xi = $skip; $xi < $n_from - $endskip; $xi++)
$xhash[$from_lines[$xi]] = 1;
for ($yi = $skip; $yi < $n_to - $endskip; $yi++) {
$line = $to_lines[$yi];
if ( ($this->ychanged[$yi] = empty($xhash[$line])) )
continue;
$yhash[$line] = 1;
$this->yv[] = $line;
$this->yind[] = $yi;
}
for ($xi = $skip; $xi < $n_from - $endskip; $xi++) {
$line = $from_lines[$xi];
if ( ($this->xchanged[$xi] = empty($yhash[$line])) )
continue;
$this->xv[] = $line;
$this->xind[] = $xi;
}
// Find the LCS.
$this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv));
// Find the LCS.
$this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv));
// Merge edits when possible
$this->_shift_boundaries($from_lines, $this->xchanged, $this->ychanged);
$this->_shift_boundaries($to_lines, $this->ychanged, $this->xchanged);
// Merge edits when possible
$this->_shift_boundaries($from_lines, $this->xchanged, $this->ychanged);
$this->_shift_boundaries($to_lines, $this->ychanged, $this->xchanged);
// Compute the edit operations.
$edits = array();
$xi = $yi = 0;
while ($xi < $n_from || $yi < $n_to) {
USE_ASSERTS && assert($yi < $n_to || $this->xchanged[$xi]);
USE_ASSERTS && assert($xi < $n_from || $this->ychanged[$yi]);
// Compute the edit operations.
$edits = array();
$xi = $yi = 0;
while ($xi < $n_from || $yi < $n_to) {
USE_ASSERTS && assert($yi < $n_to || $this->xchanged[$xi]);
USE_ASSERTS && assert($xi < $n_from || $this->ychanged[$yi]);
// Skip matching "snake".
$copy = array();
while ( $xi < $n_from && $yi < $n_to
&& !$this->xchanged[$xi] && !$this->ychanged[$yi]) {
$copy[] = $from_lines[$xi++];
++$yi;
}
if ($copy)
$edits[] = new _DiffOp_Copy($copy);
// Skip matching "snake".
$copy = array();
while ( $xi < $n_from && $yi < $n_to
&& !$this->xchanged[$xi] && !$this->ychanged[$yi]) {
$copy[] = $from_lines[$xi++];
++$yi;
}
if ($copy)
$edits[] = new _DiffOp_Copy($copy);
// Find deletes & adds.
$delete = array();
while ($xi < $n_from && $this->xchanged[$xi])
$delete[] = $from_lines[$xi++];
// Find deletes & adds.
$delete = array();
while ($xi < $n_from && $this->xchanged[$xi])
$delete[] = $from_lines[$xi++];
$add = array();
while ($yi < $n_to && $this->ychanged[$yi])
$add[] = $to_lines[$yi++];
$add = array();
while ($yi < $n_to && $this->ychanged[$yi])
$add[] = $to_lines[$yi++];
if ($delete && $add)
$edits[] = new _DiffOp_Change($delete, $add);
elseif ($delete)
$edits[] = new _DiffOp_Delete($delete);
elseif ($add)
$edits[] = new _DiffOp_Add($add);
}
return $edits;
}
if ($delete && $add)
$edits[] = new _DiffOp_Change($delete, $add);
elseif ($delete)
$edits[] = new _DiffOp_Delete($delete);
elseif ($add)
$edits[] = new _DiffOp_Add($add);
}
return $edits;
}
/* Divide the Largest Common Subsequence (LCS) of the sequences
* [XOFF, XLIM) and [YOFF, YLIM) into NCHUNKS approximately equally
* sized segments.
*
* Returns (LCS, PTS). LCS is the length of the LCS. PTS is an
* array of NCHUNKS+1 (X, Y) indexes giving the diving points between
* sub sequences. The first sub-sequence is contained in [X0, X1),
* [Y0, Y1), the second in [X1, X2), [Y1, Y2) and so on. Note
* that (X0, Y0) == (XOFF, YOFF) and
* (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM).
*
* This function assumes that the first lines of the specified portions
* of the two files do not match, and likewise that the last lines do not
* match. The caller must trim matching lines from the beginning and end
* of the portions it is going to specify.
*/
public function _diag ($xoff, $xlim, $yoff, $ylim, $nchunks) {
/* Divide the Largest Common Subsequence (LCS) of the sequences
* [XOFF, XLIM) and [YOFF, YLIM) into NCHUNKS approximately equally
* sized segments.
*
* Returns (LCS, PTS). LCS is the length of the LCS. PTS is an
* array of NCHUNKS+1 (X, Y) indexes giving the diving points between
* sub sequences. The first sub-sequence is contained in [X0, X1),
* [Y0, Y1), the second in [X1, X2), [Y1, Y2) and so on. Note
* that (X0, Y0) == (XOFF, YOFF) and
* (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM).
*
* This function assumes that the first lines of the specified portions
* of the two files do not match, and likewise that the last lines do not
* match. The caller must trim matching lines from the beginning and end
* of the portions it is going to specify.
*/
public function _diag ($xoff, $xlim, $yoff, $ylim, $nchunks) {
$flip = false;
if ($xlim - $xoff > $ylim - $yoff) {
// Things seems faster (I'm not sure I understand why)
// when the shortest sequence in X.
$flip = true;
list ($xoff, $xlim, $yoff, $ylim)
// Things seems faster (I'm not sure I understand why)
// when the shortest sequence in X.
$flip = true;
list ($xoff, $xlim, $yoff, $ylim)
= array( $yoff, $ylim, $xoff, $xlim);
}
}
if ($flip)
for ($i = $ylim - 1; $i >= $yoff; $i--)
for ($i = $ylim - 1; $i >= $yoff; $i--)
$ymatches[$this->xv[$i]][] = $i;
else
for ($i = $ylim - 1; $i >= $yoff; $i--)
for ($i = $ylim - 1; $i >= $yoff; $i--)
$ymatches[$this->yv[$i]][] = $i;
$this->lcs = 0;
@ -273,70 +273,70 @@ class _DiffEngine
$numer = $xlim - $xoff + $nchunks - 1;
$x = $xoff;
for ($chunk = 0; $chunk < $nchunks; $chunk++) {
if ($chunk > 0)
if ($chunk > 0)
for ($i = 0; $i <= $this->lcs; $i++)
$ymids[$i][$chunk-1] = $this->seq[$i];
$ymids[$i][$chunk-1] = $this->seq[$i];
$x1 = $xoff + (int)(($numer + ($xlim-$xoff)*$chunk) / $nchunks);
for ( ; $x < $x1; $x++) {
$line = $flip ? $this->yv[$x] : $this->xv[$x];
if (empty($ymatches[$line]))
continue;
$x1 = $xoff + (int)(($numer + ($xlim-$xoff)*$chunk) / $nchunks);
for ( ; $x < $x1; $x++) {
$line = $flip ? $this->yv[$x] : $this->xv[$x];
if (empty($ymatches[$line]))
continue;
$matches = $ymatches[$line];
reset($matches);
reset($matches);
while (list ($junk, $y) = each($matches))
if (empty($this->in_seq[$y])) {
if (empty($this->in_seq[$y])) {
$k = $this->_lcs_pos($y);
USE_ASSERTS && assert($k > 0);
$ymids[$k] = $ymids[$k-1];
break;
}
}
while (list ($junk, $y) = each($matches)) {
if ($y > $this->seq[$k-1]) {
if ($y > $this->seq[$k-1]) {
USE_ASSERTS && assert($y < $this->seq[$k]);
// Optimization: this is a common case:
// next match is just replacing previous match.
$this->in_seq[$this->seq[$k]] = false;
$this->seq[$k] = $y;
$this->in_seq[$y] = 1;
}
else if (empty($this->in_seq[$y])) {
}
else if (empty($this->in_seq[$y])) {
$k = $this->_lcs_pos($y);
USE_ASSERTS && assert($k > 0);
$ymids[$k] = $ymids[$k-1];
}
}
}
}
}
}
}
}
$seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff);
$ymid = $ymids[$this->lcs];
for ($n = 0; $n < $nchunks - 1; $n++) {
$x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks);
$y1 = $ymid[$n] + 1;
$seps[] = $flip ? array($y1, $x1) : array($x1, $y1);
}
$x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks);
$y1 = $ymid[$n] + 1;
$seps[] = $flip ? array($y1, $x1) : array($x1, $y1);
}
$seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim);
return array($this->lcs, $seps);
}
}
public function _lcs_pos ($ypos) {
public function _lcs_pos ($ypos) {
$end = $this->lcs;
if ($end == 0 || $ypos > $this->seq[$end]) {
$this->seq[++$this->lcs] = $ypos;
$this->in_seq[$ypos] = 1;
return $this->lcs;
}
$this->seq[++$this->lcs] = $ypos;
$this->in_seq[$ypos] = 1;
return $this->lcs;
}
$beg = 1;
while ($beg < $end) {
$mid = (int)(($beg + $end) / 2);
if ( $ypos > $this->seq[$mid] )
$mid = (int)(($beg + $end) / 2);
if ( $ypos > $this->seq[$mid] )
$beg = $mid + 1;
else
else
$end = $mid;
}
}
USE_ASSERTS && assert($ypos != $this->seq[$end]);
@ -344,77 +344,77 @@ class _DiffEngine
$this->seq[$end] = $ypos;
$this->in_seq[$ypos] = 1;
return $end;
}
}
/* Find LCS of two sequences.
*
* The results are recorded in the vectors $this->{x,y}changed[], by
* storing a 1 in the element for each line that is an insertion
* or deletion (ie. is not in the LCS).
*
* The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1.
*
* Note that XLIM, YLIM are exclusive bounds.
* All line numbers are origin-0 and discarded lines are not counted.
*/
public function _compareseq ($xoff, $xlim, $yoff, $ylim) {
/* Find LCS of two sequences.
*
* The results are recorded in the vectors $this->{x,y}changed[], by
* storing a 1 in the element for each line that is an insertion
* or deletion (ie. is not in the LCS).
*
* The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1.
*
* Note that XLIM, YLIM are exclusive bounds.
* All line numbers are origin-0 and discarded lines are not counted.
*/
public function _compareseq ($xoff, $xlim, $yoff, $ylim) {
// Slide down the bottom initial diagonal.
while ($xoff < $xlim && $yoff < $ylim
&& $this->xv[$xoff] == $this->yv[$yoff]) {
++$xoff;
++$yoff;
}
&& $this->xv[$xoff] == $this->yv[$yoff]) {
++$xoff;
++$yoff;
}
// Slide up the top initial diagonal.
while ($xlim > $xoff && $ylim > $yoff
&& $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) {
--$xlim;
--$ylim;
}
&& $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) {
--$xlim;
--$ylim;
}
if ($xoff == $xlim || $yoff == $ylim)
$lcs = 0;
$lcs = 0;
else {
// This is ad hoc but seems to work well.
//$nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5);
//$nchunks = max(2,min(8,(int)$nchunks));
$nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1;
list ($lcs, $seps)
// This is ad hoc but seems to work well.
//$nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5);
//$nchunks = max(2,min(8,(int)$nchunks));
$nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1;
list ($lcs, $seps)
= $this->_diag($xoff,$xlim,$yoff, $ylim,$nchunks);
}
}
if ($lcs == 0) {
// X and Y sequences have no common subsequence:
// mark all changed.
while ($yoff < $ylim)
// X and Y sequences have no common subsequence:
// mark all changed.
while ($yoff < $ylim)
$this->ychanged[$this->yind[$yoff++]] = 1;
while ($xoff < $xlim)
while ($xoff < $xlim)
$this->xchanged[$this->xind[$xoff++]] = 1;
}
}
else {
// Use the partitions to split this problem into subproblems.
reset($seps);
$pt1 = $seps[0];
while ($pt2 = next($seps)) {
// Use the partitions to split this problem into subproblems.
reset($seps);
$pt1 = $seps[0];
while ($pt2 = next($seps)) {
$this->_compareseq ($pt1[0], $pt2[0], $pt1[1], $pt2[1]);
$pt1 = $pt2;
}
}
}
}
}
}
/* Adjust inserts/deletes of identical lines to join changes
* as much as possible.
*
* We do something when a run of changed lines include a
* line at one end and has an excluded, identical line at the other.
* We are free to choose which identical line is included.
* 'compareseq' usually chooses the one at the beginning,
* but usually it is cleaner to consider the following identical line
* to be the "change".
*
* This is extracted verbatim from analyze.c (GNU diffutils-2.7).
*/
public function _shift_boundaries ($lines, &$changed, $other_changed) {
/* Adjust inserts/deletes of identical lines to join changes
* as much as possible.
*
* We do something when a run of changed lines include a
* line at one end and has an excluded, identical line at the other.
* We are free to choose which identical line is included.
* 'compareseq' usually chooses the one at the beginning,
* but usually it is cleaner to consider the following identical line
* to be the "change".
*
* This is extracted verbatim from analyze.c (GNU diffutils-2.7).
*/
public function _shift_boundaries ($lines, &$changed, $other_changed) {
$i = 0;
$j = 0;
@ -423,37 +423,37 @@ class _DiffEngine
$other_len = sizeof($other_changed);
while (1) {
/*
* Scan forwards to find beginning of another run of changes.
* Also keep track of the corresponding point in the other file.
*
* Throughout this code, $i and $j are adjusted together so that
* the first $i elements of $changed and the first $j elements
* of $other_changed both contain the same number of zeros
* (unchanged lines).
* Furthermore, $j is always kept so that $j == $other_len or
* $other_changed[$j] == false.
*/
while ($j < $other_len && $other_changed[$j])
/*
* Scan forwards to find beginning of another run of changes.
* Also keep track of the corresponding point in the other file.
*
* Throughout this code, $i and $j are adjusted together so that
* the first $i elements of $changed and the first $j elements
* of $other_changed both contain the same number of zeros
* (unchanged lines).
* Furthermore, $j is always kept so that $j == $other_len or
* $other_changed[$j] == false.
*/
while ($j < $other_len && $other_changed[$j])
$j++;
while ($i < $len && ! $changed[$i]) {
while ($i < $len && ! $changed[$i]) {
USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
$i++; $j++;
while ($j < $other_len && $other_changed[$j])
$j++;
}
$j++;
}
if ($i == $len)
if ($i == $len)
break;
$start = $i;
$start = $i;
// Find the end of this run of changes.
while (++$i < $len && $changed[$i])
// Find the end of this run of changes.
while (++$i < $len && $changed[$i])
continue;
do {
do {
/*
* Record the length of this run of changes, so that
* we can later determine whether the run has grown.
@ -466,15 +466,15 @@ class _DiffEngine
* This merges with previous changed regions.
*/
while ($start > 0 && $lines[$start - 1] == $lines[$i - 1]) {
$changed[--$start] = 1;
$changed[--$i] = false;
while ($start > 0 && $changed[$start - 1])
$changed[--$start] = 1;
$changed[--$i] = false;
while ($start > 0 && $changed[$start - 1])
$start--;
USE_ASSERTS && assert('$j > 0');
while ($other_changed[--$j])
USE_ASSERTS && assert('$j > 0');
while ($other_changed[--$j])
continue;
USE_ASSERTS && assert('$j >= 0 && !$other_changed[$j]');
}
USE_ASSERTS && assert('$j >= 0 && !$other_changed[$j]');
}
/*
* Set CORRESPONDING to the end of the changed run, at the last
@ -491,35 +491,35 @@ class _DiffEngine
* the changed region is moved forward as far as possible.
*/
while ($i < $len && $lines[$start] == $lines[$i]) {
$changed[$start++] = false;
$changed[$i++] = 1;
while ($i < $len && $changed[$i])
$changed[$start++] = false;
$changed[$i++] = 1;
while ($i < $len && $changed[$i])
$i++;
USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
$j++;
if ($j < $other_len && $other_changed[$j]) {
USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
$j++;
if ($j < $other_len && $other_changed[$j]) {
$corresponding = $i;
while ($j < $other_len && $other_changed[$j])
$j++;
}
}
} while ($runlength != $i - $start);
$j++;
}
}
} while ($runlength != $i - $start);
/*
* If possible, move the fully-merged run of changes
* back to a corresponding run in the other file.
*/
while ($corresponding < $i) {
/*
* If possible, move the fully-merged run of changes
* back to a corresponding run in the other file.
*/
while ($corresponding < $i) {
$changed[--$start] = 1;
$changed[--$i] = 0;
USE_ASSERTS && assert('$j > 0');
while ($other_changed[--$j])
continue;
continue;
USE_ASSERTS && assert('$j >= 0 && !$other_changed[$j]');
}
}
}
}
}
}
}
/**
@ -531,138 +531,138 @@ class Diff
{
public static $html_cleaner_class = null;
var $edits;
var $edits;
/**
* Constructor.
* Computes diff between sequences of strings.
*
* @param $from_lines array An array of strings.
* (Typically these are lines from a file.)
* @param $to_lines array An array of strings.
*/
public function Diff($from_lines, $to_lines) {
$eng = new _DiffEngine;
$this->edits = $eng->diff($from_lines, $to_lines);
//$this->_check($from_lines, $to_lines);
}
/**
* Constructor.
* Computes diff between sequences of strings.
*
* @param $from_lines array An array of strings.
* (Typically these are lines from a file.)
* @param $to_lines array An array of strings.
*/
public function Diff($from_lines, $to_lines) {
$eng = new _DiffEngine;
$this->edits = $eng->diff($from_lines, $to_lines);
//$this->_check($from_lines, $to_lines);
}
/**
* Compute reversed Diff.
*
* SYNOPSIS:
*
* $diff = new Diff($lines1, $lines2);
* $rev = $diff->reverse();
* @return object A Diff object representing the inverse of the
* original diff.
*/
public function reverse () {
/**
* Compute reversed Diff.
*
* SYNOPSIS:
*
* $diff = new Diff($lines1, $lines2);
* $rev = $diff->reverse();
* @return object A Diff object representing the inverse of the
* original diff.
*/
public function reverse () {
$rev = $this;
$rev->edits = array();
foreach ($this->edits as $edit) {
$rev->edits[] = $edit->reverse();
}
$rev->edits = array();
foreach ($this->edits as $edit) {
$rev->edits[] = $edit->reverse();
}
return $rev;
}
}
/**
* Check for empty diff.
*
* @return bool True iff two sequences were identical.
*/
public function isEmpty () {
foreach ($this->edits as $edit) {
if ($edit->type != 'copy')
return false;
}
return true;
}
/**
* Check for empty diff.
*
* @return bool True iff two sequences were identical.
*/
public function isEmpty () {
foreach ($this->edits as $edit) {
if ($edit->type != 'copy')
return false;
}
return true;
}
/**
* Compute the length of the Longest Common Subsequence (LCS).
*
* This is mostly for diagnostic purposed.
*
* @return int The length of the LCS.
*/
public function lcs () {
/**
* Compute the length of the Longest Common Subsequence (LCS).
*
* This is mostly for diagnostic purposed.
*
* @return int The length of the LCS.
*/
public function lcs () {
$lcs = 0;
foreach ($this->edits as $edit) {
if ($edit->type == 'copy')
$lcs += sizeof($edit->orig);
}
foreach ($this->edits as $edit) {
if ($edit->type == 'copy')
$lcs += sizeof($edit->orig);
}
return $lcs;
}
}
/**
* Get the original set of lines.
*
* This reconstructs the $from_lines parameter passed to the
* constructor.
*
* @return array The original sequence of strings.
*/
public function orig() {
$lines = array();
/**
* Get the original set of lines.
*
* This reconstructs the $from_lines parameter passed to the
* constructor.
*
* @return array The original sequence of strings.
*/
public function orig() {
$lines = array();
foreach ($this->edits as $edit) {
if ($edit->orig)
array_splice($lines, sizeof($lines), 0, $edit->orig);
}
return $lines;
}
foreach ($this->edits as $edit) {
if ($edit->orig)
array_splice($lines, sizeof($lines), 0, $edit->orig);
}
return $lines;
}
/**
* Get the final set of lines.
*
* This reconstructs the $to_lines parameter passed to the
* constructor.
*
* @return array The sequence of strings.
*/
public function finaltext() {
$lines = array();
/**
* Get the final set of lines.
*
* This reconstructs the $to_lines parameter passed to the
* constructor.
*
* @return array The sequence of strings.
*/
public function finaltext() {
$lines = array();
foreach ($this->edits as $edit) {
if ($edit->final)
array_splice($lines, sizeof($lines), 0, $edit->final);
}
return $lines;
}
foreach ($this->edits as $edit) {
if ($edit->final)
array_splice($lines, sizeof($lines), 0, $edit->final);
}
return $lines;
}
/**
* Check a Diff for validity.
*
* This is here only for debugging purposes.
*/
public function _check ($from_lines, $to_lines) {
if (serialize($from_lines) != serialize($this->orig()))
trigger_error("Reconstructed original doesn't match", E_USER_ERROR);
if (serialize($to_lines) != serialize($this->finaltext()))
trigger_error("Reconstructed final doesn't match", E_USER_ERROR);
/**
* Check a Diff for validity.
*
* This is here only for debugging purposes.
*/
public function _check ($from_lines, $to_lines) {
if (serialize($from_lines) != serialize($this->orig()))
trigger_error("Reconstructed original doesn't match", E_USER_ERROR);
if (serialize($to_lines) != serialize($this->finaltext()))
trigger_error("Reconstructed final doesn't match", E_USER_ERROR);
$rev = $this->reverse();
if (serialize($to_lines) != serialize($rev->orig()))
trigger_error("Reversed original doesn't match", E_USER_ERROR);
if (serialize($from_lines) != serialize($rev->finaltext()))
trigger_error("Reversed final doesn't match", E_USER_ERROR);
$rev = $this->reverse();
if (serialize($to_lines) != serialize($rev->orig()))
trigger_error("Reversed original doesn't match", E_USER_ERROR);
if (serialize($from_lines) != serialize($rev->finaltext()))
trigger_error("Reversed final doesn't match", E_USER_ERROR);
$prevtype = 'none';
foreach ($this->edits as $edit) {
if ( $prevtype == $edit->type )
trigger_error("Edit sequence is non-optimal", E_USER_ERROR);
$prevtype = $edit->type;
}
$prevtype = 'none';
foreach ($this->edits as $edit) {
if ( $prevtype == $edit->type )
trigger_error("Edit sequence is non-optimal", E_USER_ERROR);
$prevtype = $edit->type;
}
$lcs = $this->lcs();
trigger_error("Diff okay: LCS = $lcs", E_USER_NOTICE);
}
/**
$lcs = $this->lcs();
trigger_error("Diff okay: LCS = $lcs", E_USER_NOTICE);
}
/**
* Attempt to clean invalid HTML, which messes up diffs.
* This cleans code if possible, using an instance of HTMLCleaner
*
@ -750,7 +750,7 @@ class Diff
else $rechunked[$listName][] = $item;
if($lookForTag && !$tagStack[$listName] && isset($item[0]) && $item[0] == "<"
&& substr($item,0,2) != "</") {
&& substr($item,0,2) != "</") {
$tagStack[$listName] = 1;
} else if($tagStack[$listName]) {
if(substr($item,0,2) == "</") $tagStack[$listName]--;
@ -830,54 +830,54 @@ class Diff
class MappedDiff
extends Diff
{
/**
* Constructor.
*
* Computes diff between sequences of strings.
*
* This can be used to compute things like
* case-insensitve diffs, or diffs which ignore
* changes in white-space.
*
* @param $from_lines array An array of strings.
* (Typically these are lines from a file.)
*
* @param $to_lines array An array of strings.
*
* @param $mapped_from_lines array This array should
* have the same size number of elements as $from_lines.
* The elements in $mapped_from_lines and
* $mapped_to_lines are what is actually compared
* when computing the diff.
*
* @param $mapped_to_lines array This array should
* have the same number of elements as $to_lines.
*/
public function MappedDiff($from_lines, $to_lines,
$mapped_from_lines, $mapped_to_lines) {
/**
* Constructor.
*
* Computes diff between sequences of strings.
*
* This can be used to compute things like
* case-insensitve diffs, or diffs which ignore
* changes in white-space.
*
* @param $from_lines array An array of strings.
* (Typically these are lines from a file.)
*
* @param $to_lines array An array of strings.
*
* @param $mapped_from_lines array This array should
* have the same size number of elements as $from_lines.
* The elements in $mapped_from_lines and
* $mapped_to_lines are what is actually compared
* when computing the diff.
*
* @param $mapped_to_lines array This array should
* have the same number of elements as $to_lines.
*/
public function MappedDiff($from_lines, $to_lines,
$mapped_from_lines, $mapped_to_lines) {
assert(sizeof($from_lines) == sizeof($mapped_from_lines));
assert(sizeof($to_lines) == sizeof($mapped_to_lines));
assert(sizeof($from_lines) == sizeof($mapped_from_lines));
assert(sizeof($to_lines) == sizeof($mapped_to_lines));
$this->Diff($mapped_from_lines, $mapped_to_lines);
$this->Diff($mapped_from_lines, $mapped_to_lines);
$xi = $yi = 0;
// Optimizing loop invariants:
// http://phplens.com/lens/php-book/optimizing-debugging-php.php
for ($i = 0, $max = sizeof($this->edits); $i < $max; $i++) {
$orig = &$this->edits[$i]->orig;
if (is_array($orig)) {
$orig = array_slice($from_lines, $xi, sizeof($orig));
$xi += sizeof($orig);
}
$xi = $yi = 0;
// Optimizing loop invariants:
// http://phplens.com/lens/php-book/optimizing-debugging-php.php
for ($i = 0, $max = sizeof($this->edits); $i < $max; $i++) {
$orig = &$this->edits[$i]->orig;
if (is_array($orig)) {
$orig = array_slice($from_lines, $xi, sizeof($orig));
$xi += sizeof($orig);
}
$final = &$this->edits[$i]->final;
if (is_array($final)) {
$final = array_slice($to_lines, $yi, sizeof($final));
$yi += sizeof($final);
}
}
}
$final = &$this->edits[$i]->final;
if (is_array($final)) {
$final = array_slice($to_lines, $yi, sizeof($final));
$yi += sizeof($final);
}
}
}
}

View File

@ -140,7 +140,7 @@ abstract class BulkLoader extends ViewableData {
//get all instances of the to be imported data object
if($this->deleteExistingRecords) {
DataObject::get($this->objectClass)->removeAll();
DataObject::get($this->objectClass)->removeAll();
}
return $this->processAll($filepath);
@ -273,12 +273,12 @@ class BulkLoader_Result extends Object {
* </code>
*/
protected $created = array();
/**
* @var array (see {@link $created})
*/
protected $updated = array();
/**
* @var array (see {@link $created})
*/
@ -290,7 +290,7 @@ class BulkLoader_Result extends Object {
* one of 3 strings: "created", "updated", or "deleted"
*/
protected $lastChange = array();
/**
* Returns the count of all objects which were
* created or updated.
@ -408,5 +408,4 @@ class BulkLoader_Result extends Object {
return $set;
}
}

View File

@ -18,15 +18,15 @@ class DevelopmentAdmin extends Controller {
);
static $allowed_actions = array(
'index',
'tests',
'jstests',
'tasks',
'viewmodel',
'build',
'reset',
'viewcode'
);
'index',
'tests',
'jstests',
'tasks',
'viewmodel',
'build',
'reset',
'viewcode'
);
public function init() {
parent::init();
@ -56,7 +56,7 @@ class DevelopmentAdmin extends Controller {
$matched = false;
if(isset($_FILE_TO_URL_MAPPING[$testPath])) {
$matched = true;
break;
break;
}
$testPath = dirname($testPath);
}

View File

@ -8,14 +8,14 @@
*
* <code>
* public function testMyForm() {
* // Visit a URL
* $this->get("your/url");
* // Visit a URL
* $this->get("your/url");
*
* // Submit a form on the page that you get in response
* $this->submitForm("MyForm_ID", array("Email" => "invalid email ^&*&^"));
* // Submit a form on the page that you get in response
* $this->submitForm("MyForm_ID", array("Email" => "invalid email ^&*&^"));
*
* // Validate the content that is returned
* $this->assertExactMatchBySelector("#MyForm_ID p.error", array("That email address is invalid."));
* // Validate the content that is returned
* $this->assertExactMatchBySelector("#MyForm_ID p.error", array("That email address is invalid."));
* }
* </code>
*
@ -70,10 +70,10 @@ class FunctionalTest extends SapphireTest {
if($this->stat('use_draft_site')) {
$this->useDraftSite();
}
// Unprotect the site, tests are running with the assumption it's off. They will enable it on a case-by-case
// basis.
BasicAuth::protect_entire_site(false);
// Unprotect the site, tests are running with the assumption it's off. They will enable it on a case-by-case
// basis.
BasicAuth::protect_entire_site(false);
SecurityToken::disable();
}
@ -193,8 +193,8 @@ class FunctionalTest extends SapphireTest {
foreach($expectedMatches as $match) {
$this->assertTrue(
isset($actuals[$match]),
"Failed asserting the CSS selector '$selector' has a partial match to the expected elements:\n'"
. implode("'\n'", $expectedMatches) . "'\n\n"
"Failed asserting the CSS selector '$selector' has a partial match to the expected elements:\n'"
. implode("'\n'", $expectedMatches) . "'\n\n"
. "Instead the following elements were found:\n'" . implode("'\n'", array_keys($actuals)) . "'"
);
return false;

View File

@ -16,224 +16,224 @@
* @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;
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');
}
/**
* 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>";
}
// 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]++;
}
/**
* 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);
}
/**
* 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;
/**
* 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
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
/**
* 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;
}
/**
* 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";
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");
$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";
echo"============================================================================\n";
printf( " %3.4f ms (%3.2f %%) %s\n", $oaTime*1000,$tot_perc, "OVERALL TIME");
printf( " %3.4f ms (%3.2f %%) %s\n", $oaTime*1000,$tot_perc, "OVERALL TIME");
echo"============================================================================\n";
echo"============================================================================\n";
print("</pre>");
}
}
print("</pre>");
}
}
public function printTrace( $enabled=false )
{
if($this->trace_enabled||$enabled){
print("<pre>");
print("Trace\n$this->trace\n\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
/// 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;
}
/**
* 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();
}
/**
* 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);
}
/**
* 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

@ -83,17 +83,17 @@ class SapphireTestReporter implements PHPUnit_Framework_TestListener {
public function __construct() {
@include_once 'Benchmark/Timer.php';
if(class_exists('Benchmark_Timer')) {
$this->timer = new Benchmark_Timer();
$this->hasTimer = true;
$this->timer = new Benchmark_Timer();
$this->hasTimer = true;
} else {
$this->hasTimer = false;
$this->hasTimer = false;
}
$this->suiteResults = array(
'suites' => array(), // array of suites run
'hasTimer' => $this->hasTimer, // availability of PEAR Benchmark_Timer
'totalTests' => 0 // total number of tests run
);
$this->suiteResults = array(
'suites' => array(), // array of suites run
'hasTimer' => $this->hasTimer, // availability of PEAR Benchmark_Timer
'totalTests' => 0 // total number of tests run
);
}
/**
@ -117,14 +117,14 @@ class SapphireTestReporter implements PHPUnit_Framework_TestListener {
public function startTestSuite( PHPUnit_Framework_TestSuite $suite) {
if(strlen($suite->getName())) {
$this->endCurrentTestSuite();
$this->currentSuite = array(
'suite' => $suite, // the test suite
'tests' => array(), // the tests in the suite
'errors' => 0, // number of tests with errors (including setup errors)
'failures' => 0, // number of tests which failed
'incomplete' => 0, // number of tests that were not completed correctly
$this->currentSuite = array(
'suite' => $suite, // the test suite
'tests' => array(), // the tests in the suite
'errors' => 0, // number of tests with errors (including setup errors)
'failures' => 0, // number of tests which failed
'incomplete' => 0, // number of tests that were not completed correctly
'error' => null); // Any error encountered during setup of the test suite
}
}
}
/**
@ -226,7 +226,7 @@ class SapphireTestReporter implements PHPUnit_Framework_TestListener {
$this->currentSuite['incomplete']++;
$this->addStatus(TEST_INCOMPLETE, $e->toString(), $this->getTestException($test, $e), $e->getTrace());
}
/**
* Not used
*
@ -257,7 +257,7 @@ class SapphireTestReporter implements PHPUnit_Framework_TestListener {
$this->currentTest = null;
}
/**
/**
* Upon completion of a test, records the execution time (if available) and adds the test to
* the tests performed in the current suite.
*

View File

@ -27,13 +27,13 @@ class SilverStripeListener implements PHPUnit_Framework_TestListener {
public function startTest(PHPUnit_Framework_Test $test) {
}
public function endTest(PHPUnit_Framework_Test $test, $time) {
}
public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) {
}
public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) {
}

View File

@ -27,7 +27,7 @@ class TeamCityListener implements PHPUnit_Framework_TestListener {
$class = get_class($test);
echo "##teamcity[testStarted name='{$class}.{$test->getName()}']\n";
}
public function endTest(PHPUnit_Framework_Test $test, $time) {
$class = get_class($test);
echo "##teamcity[testFinished name='{$class}.{$test->getName()}' duration='$time']\n";
@ -40,7 +40,7 @@ class TeamCityListener implements PHPUnit_Framework_TestListener {
echo "##teamcity[testFailed type='exception' name='{$class}.{$test->getName()}' message='$message'"
. " details='$trace']\n";
}
public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) {
$class = get_class($test);
$message = $this->escape($e->getMessage());

View File

@ -13,15 +13,15 @@ class SS_TestListener implements PHPUnit_Framework_TestListener {
public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) {}
public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) {}
public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) {}
public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) {}
public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) {}
public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) {}
public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) {}
public function startTest(PHPUnit_Framework_Test $test) {}
public function startTest(PHPUnit_Framework_Test $test) {}
public function endTest(PHPUnit_Framework_Test $test, $time) {}
public function endTest(PHPUnit_Framework_Test $test, $time) {}
public function startTestSuite(PHPUnit_Framework_TestSuite $suite) {
$name = $suite->getName();
@ -29,7 +29,7 @@ class SS_TestListener implements PHPUnit_Framework_TestListener {
$this->class = new $name();
$this->class->setUpOnce();
}
}
public function endTestSuite(PHPUnit_Framework_TestSuite $suite) {
$name = $suite->getName();

View File

@ -138,14 +138,14 @@ class PhpUnitWrapper implements IPhpUnitWrapper {
public static function inst() {
if (self::$phpunit_wrapper == null) {
if (fileExistsInIncludePath("/PHPUnit/Autoload.php")) {
self::$phpunit_wrapper = new PhpUnitWrapper_3_5();
} else
if (fileExistsInIncludePath("/PHPUnit/Framework.php")) {
self::$phpunit_wrapper = new PhpUnitWrapper_3_4();
} else {
self::$phpunit_wrapper = new PhpUnitWrapper();
}
if (fileExistsInIncludePath("/PHPUnit/Autoload.php")) {
self::$phpunit_wrapper = new PhpUnitWrapper_3_5();
} else
if (fileExistsInIncludePath("/PHPUnit/Framework.php")) {
self::$phpunit_wrapper = new PhpUnitWrapper_3_4();
} else {
self::$phpunit_wrapper = new PhpUnitWrapper();
}
self::$phpunit_wrapper->init();
}

View File

@ -35,11 +35,11 @@ class PhpUnitWrapper_3_5 extends PhpUnitWrapper {
protected function beforeRunTests() {
if($this->getCoverageStatus()) {
$this->coverage = new PHP_CodeCoverage();
$this->coverage = new PHP_CodeCoverage();
$coverage = $this->coverage;
$filter = $coverage->filter();
$modules = $this->moduleDirectories();
$filter = $coverage->filter();
$modules = $this->moduleDirectories();
foreach(TestRunner::$coverage_filter_dirs as $dir) {
if($dir[0] == '*') {

View File

@ -363,12 +363,12 @@ class Email extends ViewableData {
* Validates the email address. Returns true of false
*/
public static function validEmailAddress($address) {
if (function_exists('filter_var')) {
return filter_var($address, FILTER_VALIDATE_EMAIL);
} else {
return preg_match('#^([a-zA-Z0-9_+\.\-]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)'
. '|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$#', $address);
}
if (function_exists('filter_var')) {
return filter_var($address, FILTER_VALIDATE_EMAIL);
} else {
return preg_match('#^([a-zA-Z0-9_+\.\-]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)'
. '|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$#', $address);
}
}
/**

View File

@ -120,9 +120,9 @@ class Mailer {
dieprintr($customheaders);
}
$bodyIsUnicode = (strpos($htmlContent,"&#") !== false);
$plainEncoding = "";
$plainEncoding = "";
// We generate plaintext content by default, but you can pass custom stuff
$plainEncoding = '';
@ -146,7 +146,7 @@ class Mailer {
// Make the HTML part
$headers["Content-Type"] = "text/html; charset=utf-8";
// Add basic wrapper tags if the body tag hasn't been given
if(stripos($htmlContent, '<body') === false) {
@ -199,14 +199,14 @@ class Mailer {
$headers["From"] = $this->validEmailAddr($from);
// Messages with the X-SilverStripeMessageID header can be tracked
if(isset($customheaders["X-SilverStripeMessageID"]) && defined('BOUNCE_EMAIL')) {
$bounceAddress = BOUNCE_EMAIL;
} else {
$bounceAddress = $from;
}
if(isset($customheaders["X-SilverStripeMessageID"]) && defined('BOUNCE_EMAIL')) {
$bounceAddress = BOUNCE_EMAIL;
} else {
$bounceAddress = $from;
}
// Strip the human name from the bounce address
if(preg_match('/^([^<>]*)<([^<>]+)> *$/', $bounceAddress, $parts)) $bounceAddress = $parts[2];
// Strip the human name from the bounce address
if(preg_match('/^([^<>]*)<([^<>]+)> *$/', $bounceAddress, $parts)) $bounceAddress = $parts[2];
// $headers["Sender"] = $from;
$headers["X-Mailer"] = X_MAILER;
@ -350,9 +350,9 @@ class Mailer {
$file['contents'] = $this->QuotedPrintable_encode($file['contents']);
}
$headers = "Content-type: $mimeType;\n\tname=\"$base\"\n".
"Content-Transfer-Encoding: $encoding\n".
"Content-Disposition: $disposition;\n\tfilename=\"$base\"\n" ;
$headers = "Content-type: $mimeType;\n\tname=\"$base\"\n".
"Content-Transfer-Encoding: $encoding\n".
"Content-Disposition: $disposition;\n\tfilename=\"$base\"\n" ;
if ( isset($file['contentLocation']) ) $headers .= 'Content-Location: ' . $file['contentLocation'] . "\n" ;
@ -487,4 +487,4 @@ function validEmailAddr($emailAddress) {
$mailer = Injector::inst()->create('Mailer');
return $mailer->validEmailAddr($emailAddress);
}
}

View File

@ -135,9 +135,9 @@ class GDBackend extends Object implements Image_Backend {
* @todo This method isn't very efficent
*/
public function fittedResize($width, $height) {
$gd = $this->resizeByHeight($height);
if($gd->width > $width) $gd = $gd->resizeByWidth($width);
return $gd;
$gd = $this->resizeByHeight($height);
if($gd->width > $width) $gd = $gd->resizeByWidth($width);
return $gd;
}
/**
@ -199,9 +199,9 @@ class GDBackend extends Object implements Image_Backend {
if(!$this->gd) return;
if(function_exists("imagerotate")) {
$newGD = imagerotate($this->gd, $angle,0);
$newGD = imagerotate($this->gd, $angle,0);
} else {
//imagerotate is not included in PHP included in Ubuntu
//imagerotate is not included in PHP included in Ubuntu
$newGD = $this->rotatePixelByPixel($angle);
}
$output = clone $this;
@ -210,45 +210,45 @@ class GDBackend extends Object implements Image_Backend {
}
/**
* Rotates image by given angle. It's slow because makes it pixel by pixel rather than
* using built-in function. Used when imagerotate function is not available(i.e. Ubuntu)
*
* @param angle
*
* @return GD
*/
* Rotates image by given angle. It's slow because makes it pixel by pixel rather than
* using built-in function. Used when imagerotate function is not available(i.e. Ubuntu)
*
* @param angle
*
* @return GD
*/
public function rotatePixelByPixel($angle) {
$sourceWidth = imagesx($this->gd);
$sourceHeight = imagesy($this->gd);
if ($angle == 180) {
$destWidth = $sourceWidth;
$destHeight = $sourceHeight;
} else {
$destWidth = $sourceHeight;
$destHeight = $sourceWidth;
}
$rotate=imagecreatetruecolor($destWidth,$destHeight);
imagealphablending($rotate, false);
for ($x = 0; $x < ($sourceWidth); $x++) {
for ($y = 0; $y < ($sourceHeight); $y++) {
$color = imagecolorat($this->gd, $x, $y);
switch ($angle) {
case 90:
imagesetpixel($rotate, $y, $destHeight - $x - 1, $color);
break;
case 180:
imagesetpixel($rotate, $destWidth - $x - 1, $destHeight - $y - 1, $color);
break;
case 270:
imagesetpixel($rotate, $destWidth - $y - 1, $x, $color);
break;
default: $rotate = $this->gd;
};
}
}
return $rotate;
}
public function rotatePixelByPixel($angle) {
$sourceWidth = imagesx($this->gd);
$sourceHeight = imagesy($this->gd);
if ($angle == 180) {
$destWidth = $sourceWidth;
$destHeight = $sourceHeight;
} else {
$destWidth = $sourceHeight;
$destHeight = $sourceWidth;
}
$rotate=imagecreatetruecolor($destWidth,$destHeight);
imagealphablending($rotate, false);
for ($x = 0; $x < ($sourceWidth); $x++) {
for ($y = 0; $y < ($sourceHeight); $y++) {
$color = imagecolorat($this->gd, $x, $y);
switch ($angle) {
case 90:
imagesetpixel($rotate, $y, $destHeight - $x - 1, $color);
break;
case 180:
imagesetpixel($rotate, $destWidth - $x - 1, $destHeight - $y - 1, $color);
break;
case 270:
imagesetpixel($rotate, $destWidth - $y - 1, $x, $color);
break;
default: $rotate = $this->gd;
};
}
}
return $rotate;
}
/**
@ -271,7 +271,7 @@ class GDBackend extends Object implements Image_Backend {
return $output;
}
/**
/**
* Method return width of image.
*
* @return integer width.
@ -334,9 +334,9 @@ class GDBackend extends Object implements Image_Backend {
/**
* Resize to fit fully within the given box, without resizing. Extra space left around
* the image will be padded with the background color.
* @param width
* @param height
* @param backgroundColour
* @param width
* @param height
* @param backgroundColour
*/
public function paddedResize($width, $height, $backgroundColor = "FFFFFF") {
if(!$this->gd) return;
@ -476,4 +476,4 @@ class GD extends GDBackend {
);
GDBackend::set_default_quality($quality);
}
}
}

View File

@ -29,7 +29,7 @@ class AjaxUniqueTextField extends TextField {
parent::__construct($name, $title, $value);
}
public function Field($properties = array()) {
$url = Convert::raw2att( $this->validateURL );

View File

@ -79,7 +79,7 @@ class CheckboxSetField extends OptionsetField {
if(is_a($object, 'DataObject')) {
$items[] = $object->ID;
}
}
}
} elseif($values && is_string($values)) {
$items = explode(',', $values);
$items = str_replace('{comma}', ',', $items);

View File

@ -163,8 +163,8 @@ class CompositeField extends FormField {
$formName = (isset($this->form)) ? $this->form->FormName() : '(unknown form)';
if(isset($list[$name])) {
user_error("collateDataFields() I noticed that a field called '$name' appears twice in"
. " your form: '{$formName}'. One is a '{$field->class}' and the other is a"
. " '{$list[$name]->class}'", E_USER_ERROR);
. " your form: '{$formName}'. One is a '{$field->class}' and the other is a"
. " '{$list[$name]->class}'", E_USER_ERROR);
}
$list[$name] = $field;
}

View File

@ -52,7 +52,7 @@ class CreditCardField extends TextField {
if($this->value) foreach($this->value as $part){
if(!$part || !(strlen($part) == 4) || !preg_match("/([0-9]{4})/", $part)){
switch($i){
case 0: $number = _t('CreditCardField.FIRST', 'first'); break;
case 0: $number = _t('CreditCardField.FIRST', 'first'); break;
case 1: $number = _t('CreditCardField.SECOND', 'second'); break;
case 2: $number = _t('CreditCardField.THIRD', 'third'); break;
case 3: $number = _t('CreditCardField.FOURTH', 'fourth'); break;

View File

@ -43,9 +43,9 @@ require_once 'Zend/Date.php';
*
* ## Example: German dates with separate fields for day, month, year
*
* $f = new DateField('MyDate');
* $f->setLocale('de_DE');
* $f->setConfig('dmyfields');
* $f = new DateField('MyDate');
* $f->setLocale('de_DE');
* $f->setConfig('dmyfields');
*
* # Validation
*
@ -314,11 +314,11 @@ class DateField extends TextField {
* @return boolean
*/
public static function set_default_config($k, $v) {
if (array_key_exists($k,self::$default_config)) {
self::$default_config[$k]=$v;
return true;
}
return false;
if (array_key_exists($k,self::$default_config)) {
self::$default_config[$k]=$v;
return true;
}
return false;
}
/**
@ -567,7 +567,7 @@ class DateField_View_JQuery extends Object {
// Include language files (if required)
if ($this->jqueryLocaleFile){
Requirements::javascript($this->jqueryLocaleFile);
}
}
Requirements::javascript(FRAMEWORK_DIR . "/javascript/DateField.js");
}
@ -609,51 +609,51 @@ class DateField_View_JQuery extends Object {
public static function convert_iso_to_jquery_format($format) {
$convert = array(
'/([^d])d([^d])/' => '$1d$2',
'/^d([^d])/' => 'd$1',
'/([^d])d$/' => '$1d',
'/dd/' => 'dd',
'/SS/' => '',
'/eee/' => 'd',
'/e/' => 'N',
'/D/' => '',
'/EEEE/' => 'DD',
'/EEE/' => 'D',
'/w/' => '',
'/^d([^d])/' => 'd$1',
'/([^d])d$/' => '$1d',
'/dd/' => 'dd',
'/SS/' => '',
'/eee/' => 'd',
'/e/' => 'N',
'/D/' => '',
'/EEEE/' => 'DD',
'/EEE/' => 'D',
'/w/' => '',
// make single "M" lowercase
'/([^M])M([^M])/' => '$1m$2',
'/([^M])M([^M])/' => '$1m$2',
// make single "M" at start of line lowercase
'/^M([^M])/' => 'm$1',
'/^M([^M])/' => 'm$1',
// make single "M" at end of line lowercase
'/([^M])M$/' => '$1m',
'/([^M])M$/' => '$1m',
// match exactly three capital Ms not preceeded or followed by an M
'/(?<!M)MMM(?!M)/' => 'M',
'/(?<!M)MMM(?!M)/' => 'M',
// match exactly two capital Ms not preceeded or followed by an M
'/(?<!M)MM(?!M)/' => 'mm',
'/(?<!M)MM(?!M)/' => 'mm',
// match four capital Ms (maximum allowed)
'/MMMM/' => 'MM',
'/l/' => '',
'/YYYY/' => 'yy',
'/yyyy/' => 'yy',
// See http://open.silverstripe.org/ticket/7669
'/y{1,3}/' => 'yy',
'/a/' => '',
'/B/' => '',
'/hh/' => '',
'/h/' => '',
'/([^H])H([^H])/' => '',
'/^H([^H])/' => '',
'/([^H])H$/' => '',
'/HH/' => '',
// '/mm/' => '',
'/ss/' => '',
'/zzzz/' => '',
'/I/' => '',
'/ZZZZ/' => '',
'/Z/' => '',
'/z/' => '',
'/X/' => '',
'/r/' => '',
'/U/' => '',
'/MMMM/' => 'MM',
'/l/' => '',
'/YYYY/' => 'yy',
'/yyyy/' => 'yy',
// See http://open.silverstripe.org/ticket/7669
'/y{1,3}/' => 'yy',
'/a/' => '',
'/B/' => '',
'/hh/' => '',
'/h/' => '',
'/([^H])H([^H])/' => '',
'/^H([^H])/' => '',
'/([^H])H$/' => '',
'/HH/' => '',
// '/mm/' => '',
'/ss/' => '',
'/zzzz/' => '',
'/I/' => '',
'/ZZZZ/' => '',
'/Z/' => '',
'/z/' => '',
'/X/' => '',
'/r/' => '',
'/U/' => '',
);
$patterns = array_keys($convert);
$replacements = array_values($convert);

View File

@ -90,12 +90,12 @@ class FieldGroup extends CompositeField {
*
* @param string $zebra one of odd or even.
*/
public function setZebra($zebra) {
if($zebra == 'odd' || $zebra == 'even') $this->zebra = $zebra;
else user_error("setZebra passed '$zebra'. It should be passed 'odd' or 'even'", E_USER_WARNING);
return $this;
}
public function setZebra($zebra) {
if($zebra == 'odd' || $zebra == 'even') $this->zebra = $zebra;
else user_error("setZebra passed '$zebra'. It should be passed 'odd' or 'even'", E_USER_WARNING);
return $this;
}
/**
* @return string
*/
@ -132,4 +132,4 @@ class FieldGroup extends CompositeField {
public function php($data) {
return;
}
}
}

View File

@ -999,7 +999,7 @@ class Form extends RequestHandler {
*
* @return boolean
*/
public function validate(){
public function validate(){
if($this->validator){
$errors = $this->validator->validate();
@ -1420,7 +1420,7 @@ class Form extends RequestHandler {
$result .= "</ul>";
if( $this->validator )
$result .= '<h3>'._t('Form.VALIDATOR', 'Validator').'</h3>' . $this->validator->debug();
$result .= '<h3>'._t('Form.VALIDATOR', 'Validator').'</h3>' . $this->validator->debug();
return $result;
}
@ -1437,8 +1437,8 @@ class Form extends RequestHandler {
*/
public function testSubmission($action, $data) {
$data['action_' . $action] = true;
return Director::test($this->FormAction(), $data, Controller::curr()->getSession());
return Director::test($this->FormAction(), $data, Controller::curr()->getSession());
//$response = $this->controller->run($data);
//return $response;

View File

@ -85,7 +85,7 @@ class FormField extends RequestHandler {
protected
$template,
$fieldHolderTemplate,
$smallFieldHolderTemplate;
$smallFieldHolderTemplate;
/**
* @var array All attributes on the form field (not the field holder).
@ -582,14 +582,14 @@ class FormField extends RequestHandler {
return $obj->renderWith($this->getFieldHolderTemplates());
}
/**
* Returns a restricted field holder used within things like FieldGroups.
*
* @param array $properties
*
* @return string
*/
public function SmallFieldHolder($properties = array()) {
/**
* Returns a restricted field holder used within things like FieldGroups.
*
* @param array $properties
*
* @return string
*/
public function SmallFieldHolder($properties = array()) {
$obj = ($properties) ? $this->customise($properties) : $this;
return $obj->renderWith($this->getSmallFieldHolderTemplates());

View File

@ -175,8 +175,8 @@ class HtmlEditorField extends TextareaField {
// Save file & link tracking data.
if(class_exists('SiteTree')) {
if($record->ID && $record->many_many('LinkTracking') && $tracker = $record->LinkTracking()) {
$tracker->removeByFilter(sprintf('"FieldName" = \'%s\' AND "SiteTreeID" = %d',
$this->name, $record->ID));
$tracker->removeByFilter(sprintf('"FieldName" = \'%s\' AND "SiteTreeID" = %d',
$this->name, $record->ID));
if($linkedPages) foreach($linkedPages as $item) {
$SQL_fieldName = Convert::raw2sql($this->name);
@ -186,9 +186,9 @@ class HtmlEditorField extends TextareaField {
}
if($record->ID && $record->many_many('ImageTracking') && $tracker = $record->ImageTracking()) {
$tracker->where(
sprintf('"FieldName" = \'%s\' AND "SiteTreeID" = %d', $this->name, $record->ID)
)->removeAll();
$tracker->where(
sprintf('"FieldName" = \'%s\' AND "SiteTreeID" = %d', $this->name, $record->ID)
)->removeAll();
$fieldName = $this->name;
if($linkedFiles) foreach($linkedFiles as $item) {

View File

@ -14,8 +14,8 @@ class NumericField extends TextField{
/** PHP Validation **/
public function validate($validator){
if($this->value && !is_numeric(trim($this->value))){
$validator->validationError(
$this->name,
$validator->validationError(
$this->name,
_t(
'NumericField.VALIDATION', "'{value}' is not a number, only numbers can be accepted for this field",
array('value' => $this->value)

View File

@ -33,11 +33,11 @@ class PhoneNumberField extends FormField {
list($countryCode, $areaCode, $phoneNumber, $extension) = $this->parseValue();
$hasTitle = false;
if ($this->value=="") {
$countryCode=$this->countryCode;
$areaCode=$this->areaCode;
$extension=$this->ext;
}
if ($this->value=="") {
$countryCode=$this->countryCode;
$areaCode=$this->areaCode;
$extension=$this->ext;
}
if($this->countryCode !== null) {
$fields->push(new NumericField($this->name.'[Country]', '+', $countryCode, 4));
@ -94,7 +94,7 @@ class PhoneNumberField extends FormField {
preg_match( '/^(?:(?:\+(\d+))?\s*\((\d+)\))?\s*([0-9A-Za-z]*)\s*(?:[#]\s*(\d+))?$/', $this->value, $parts);
else
return array( '', '', $this->value, '' );
if(is_array($parts)) array_shift( $parts );
for ($x=0;$x<=3;$x++) {

View File

@ -42,15 +42,15 @@ class RequiredFields extends Validator {
* Debug helper
*/
public function debug() {
if(!is_array($this->required)) return false;
if(!is_array($this->required)) return false;
$result = "<ul>";
foreach( $this->required as $name ){
$result .= "<li>$name</li>";
}
$result = "<ul>";
foreach( $this->required as $name ){
$result .= "<li>$name</li>";
}
$result .= "</ul>";
return $result;
$result .= "</ul>";
return $result;
}
/**

View File

@ -211,7 +211,7 @@ class GridField extends FormField {
public function getManipulatedList() {
$list = $this->getList();
foreach($this->getComponents() as $item) {
if($item instanceof GridField_DataManipulator) {
if($item instanceof GridField_DataManipulator) {
$list = $item->getManipulatedData($this, $list);
}
}

View File

@ -244,7 +244,6 @@
this._super();
this.selectable('destroy');
}
});
/**

View File

@ -6,15 +6,15 @@
* ajax / iframe submissions
*/
var ss = ss || {};
var ss = ss || {};
/**
* Wrapper for HTML WYSIWYG libraries, which abstracts library internals
* from interface concerns like inserting and editing links.
* Caution: Incomplete and unstable API.
*/
ss.editorWrappers = {};
ss.editorWrappers.initial
ss.editorWrappers.tinyMCE = (function() {
ss.editorWrappers = {};
ss.editorWrappers.initial
ss.editorWrappers.tinyMCE = (function() {
return {
init: function(config) {
if(!ss.editorWrappers.tinyMCE.initialized) {
@ -807,7 +807,7 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
if(header) header[(hasItems) ? 'show' : 'hide']();
// Disable "insert" button if no files are selected
this.find('.Actions :submit')
this.find('.Actions :submit')
.button(hasItems ? 'enable' : 'disable')
.toggleClass('ui-state-disabled', !hasItems);

View File

@ -108,7 +108,7 @@ ss.i18n = {
* @return string result : Stripped string
*
*/
stripStr: function(str) {
stripStr: function(str) {
return str.replace(/^\s*/, "").replace(/\s*$/, "");
},
@ -228,4 +228,4 @@ ss.i18n = {
ss.i18n.addEvent(window, "load", function() {
ss.i18n.init();
});
});

View File

@ -23,7 +23,7 @@
// loaded files list - to protect against loading existed file again (by PGA)
_ondemand_loaded_list : null,
/**
* Returns true if the given CSS or JS script has already been loaded
*/
@ -160,4 +160,4 @@
});
})(jQuery);
})(jQuery);

View File

@ -212,7 +212,7 @@ Tree.prototype = {
}
// Update the helper classes accordingly
if(!hasChildren) this.removeNodeClass('children');
if(!hasChildren) this.removeNodeClass('children');
else this.lastTreeNode().addNodeClass('last');
// Update the helper variables
@ -303,8 +303,8 @@ TreeNode.prototype = {
// Move all the nodes up until that point into spanC
for(j=startingPoint;j<stoppingPoint;j++) {
/* Use [startingPoint] every time, because the appentChild
removes the node, so it then points to the next one. */
/* Use [startingPoint] every time, because the appentChild
removes the node, so it then points to the next one. */
spanC.appendChild(li.childNodes[startingPoint]);
}
@ -527,7 +527,7 @@ TreeNode.prototype = {
}
// Update the helper classes accordingly
if(!hasChildren) this.removeNodeClass('children');
if(!hasChildren) this.removeNodeClass('children');
else this.lastTreeNode().addNodeClass('last');
// Update the helper variables
@ -599,27 +599,27 @@ TreeNode.prototype = {
/* Close or Open all the trees, at beginning or on request. sjd. */
function treeCloseAll() {
var candidates = document.getElementsByTagName('li');
for (var i=0;i<candidates.length;i++) {
var aSpan = candidates[i].childNodes[0];
if(aSpan.childNodes[0] && aSpan.childNodes[0].className == "b") {
if (!aSpan.className.match(/spanClosed/) && candidates[i].id != 'record-0' ) {
aSpan.childNodes[0].onclick();
}
}
}
var candidates = document.getElementsByTagName('li');
for (var i=0;i<candidates.length;i++) {
var aSpan = candidates[i].childNodes[0];
if(aSpan.childNodes[0] && aSpan.childNodes[0].className == "b") {
if (!aSpan.className.match(/spanClosed/) && candidates[i].id != 'record-0' ) {
aSpan.childNodes[0].onclick();
}
}
}
}
function treeOpenAll() {
var candidates = document.getElementsByTagName('li');
for (var i=0;i<candidates.length;i++) {
var aSpan = candidates[i].childNodes[0];
if(aSpan.childNodes[0] && aSpan.childNodes[0].className == "b") {
if (aSpan.className.match(/spanClosed/)) {
aSpan.childNodes[0].onclick();
}
}
}
var candidates = document.getElementsByTagName('li');
for (var i=0;i<candidates.length;i++) {
var aSpan = candidates[i].childNodes[0];
if(aSpan.childNodes[0] && aSpan.childNodes[0].className == "b") {
if (aSpan.className.match(/spanClosed/)) {
aSpan.childNodes[0].onclick();
}
}
}
}
@ -922,4 +922,4 @@ MultiselectTree.prototype = {
delete this.selectedNodes[idx];
}
}
}

View File

@ -218,7 +218,7 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
* @return boolean
*/
public function canSortBy($fieldName) {
return $this->dataQuery()->query()->canSortBy($fieldName);
return $this->dataQuery()->query()->canSortBy($fieldName);
}
/**
@ -718,7 +718,7 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
* @return mixed
*/
public function max($fieldName) {
return $this->dataQuery->max($fieldName);
return $this->dataQuery->max($fieldName);
}
/**
@ -728,7 +728,7 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
* @return mixed
*/
public function min($fieldName) {
return $this->dataQuery->min($fieldName);
return $this->dataQuery->min($fieldName);
}
/**
@ -738,7 +738,7 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
* @return mixed
*/
public function avg($fieldName) {
return $this->dataQuery->avg($fieldName);
return $this->dataQuery->avg($fieldName);
}
/**
@ -748,7 +748,7 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
* @return mixed
*/
public function sum($fieldName) {
return $this->dataQuery->sum($fieldName);
return $this->dataQuery->sum($fieldName);
}
@ -878,7 +878,7 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
// Index current data
foreach($this->column() as $id) {
$has[$id] = true;
$has[$id] = true;
}
// Keep track of items to delete
@ -996,7 +996,7 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
*/
public function newObject($initialFields = null) {
$class = $this->dataClass;
return Injector::inst()->create($class, $initialFields, false, $this->model);
return Injector::inst()->create($class, $initialFields, false, $this->model);
}
/**
@ -1012,14 +1012,14 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
}
/**
* Remove an item from this DataList by ID
/**
* Remove an item from this DataList by ID
*
* @param int $itemID - The primary ID
*/
*/
public function removeByID($itemID) {
$item = $this->byID($itemID);
if($item) return $item->delete();
$item = $this->byID($itemID);
if($item) return $item->delete();
}
/**
@ -1091,7 +1091,7 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
* @return bool
*/
public function offsetExists($key) {
return ($this->limit(1,$key)->First() != null);
return ($this->limit(1,$key)->First() != null);
}
/**
@ -1101,7 +1101,7 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
* @return DataObject
*/
public function offsetGet($key) {
return $this->limit(1, $key)->First();
return $this->limit(1, $key)->First();
}
/**
@ -1111,7 +1111,7 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
* @param mixed $value
*/
public function offsetSet($key, $value) {
user_error("Can't alter items in a DataList using array-access", E_USER_ERROR);
user_error("Can't alter items in a DataList using array-access", E_USER_ERROR);
}
/**
@ -1120,7 +1120,7 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
* @param mixed $key
*/
public function offsetUnset($key) {
user_error("Can't alter items in a DataList using array-access", E_USER_ERROR);
user_error("Can't alter items in a DataList using array-access", E_USER_ERROR);
}
}

View File

@ -13,46 +13,46 @@
*
* <code>
* class Article extends DataObject implements PermissionProvider {
* static $api_access = true;
*
* function canView($member = false) {
* return Permission::check('ARTICLE_VIEW');
* }
* function canEdit($member = false) {
* return Permission::check('ARTICLE_EDIT');
* }
* function canDelete() {
* return Permission::check('ARTICLE_DELETE');
* }
* function canCreate() {
* return Permission::check('ARTICLE_CREATE');
* }
* function providePermissions() {
* return array(
* 'ARTICLE_VIEW' => 'Read an article object',
* 'ARTICLE_EDIT' => 'Edit an article object',
* 'ARTICLE_DELETE' => 'Delete an article object',
* 'ARTICLE_CREATE' => 'Create an article object',
* );
* }
* static $api_access = true;
*
* function canView($member = false) {
* return Permission::check('ARTICLE_VIEW');
* }
* function canEdit($member = false) {
* return Permission::check('ARTICLE_EDIT');
* }
* function canDelete() {
* return Permission::check('ARTICLE_DELETE');
* }
* function canCreate() {
* return Permission::check('ARTICLE_CREATE');
* }
* function providePermissions() {
* return array(
* 'ARTICLE_VIEW' => 'Read an article object',
* 'ARTICLE_EDIT' => 'Edit an article object',
* 'ARTICLE_DELETE' => 'Delete an article object',
* 'ARTICLE_CREATE' => 'Create an article object',
* );
* }
* }
* </code>
*
* Object-level access control by {@link Group} membership:
* <code>
* class Article extends DataObject {
* static $api_access = true;
*
* function canView($member = false) {
* if(!$member) $member = Member::currentUser();
* return $member->inGroup('Subscribers');
* }
* function canEdit($member = false) {
* if(!$member) $member = Member::currentUser();
* return $member->inGroup('Editors');
* }
*
* // ...
* static $api_access = true;
*
* function canView($member = false) {
* if(!$member) $member = Member::currentUser();
* return $member->inGroup('Subscribers');
* }
* function canEdit($member = false) {
* if(!$member) $member = Member::currentUser();
* return $member->inGroup('Editors');
* }
*
* // ...
* }
* </code>
*
@ -818,7 +818,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
* @param $priority String left|right Determines who wins in case of a conflict (optional)
* @param $includeRelations Boolean Merge any existing relations (optional)
* @param $overwriteWithEmpty Boolean Overwrite existing left values with empty right values.
* Only applicable with $priority='right'. (optional)
* Only applicable with $priority='right'. (optional)
* @return Boolean
*/
public function merge($rightObj, $priority = 'right', $includeRelations = true, $overwriteWithEmpty = false) {
@ -997,7 +997,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
if($defaults && !is_array($defaults)) {
user_error("Bad '$this->class' defaults given: " . var_export($defaults, true),
E_USER_WARNING);
E_USER_WARNING);
$defaults = null;
}
@ -1258,8 +1258,8 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
. " Make sure that you call parent::onBeforeDelete().", E_USER_ERROR);
}
// Deleting a record without an ID shouldn't do anything
if(!$this->ID) throw new LogicException("DataObject::delete() called on a DataObject without an ID");
// Deleting a record without an ID shouldn't do anything
if(!$this->ID) throw new LogicException("DataObject::delete() called on a DataObject without an ID");
// TODO: This is quite ugly. To improve:
// - move the details of the delete code in the DataQuery system
@ -1868,8 +1868,8 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
* Used by {@link SearchContext}.
*
* @param array $_params
* 'fieldClasses': Associative array of field names as keys and FormField classes as values
* 'restrictFields': Numeric array of a field name whitelist
* 'fieldClasses': Associative array of field names as keys and FormField classes as values
* 'restrictFields': Numeric array of a field name whitelist
* @return FieldList
*/
public function scaffoldSearchFields($_params = null) {
@ -1960,14 +1960,14 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
* or extended onto it by using {@link DataExtension->updateCMSFields()}.
*
* <code>
* klass MyCustomClass extends DataObject {
* static $db = array('CustomProperty'=>'Boolean');
* class MyCustomClass extends DataObject {
* static $db = array('CustomProperty'=>'Boolean');
*
* function getCMSFields() {
* $fields = parent::getCMSFields();
* $fields->addFieldToTab('Root.Content',new CheckboxField('CustomProperty'));
* return $fields;
* }
* function getCMSFields() {
* $fields = parent::getCMSFields();
* $fields->addFieldToTab('Root.Content',new CheckboxField('CustomProperty'));
* return $fields;
* }
* }
* </code>
*
@ -3130,8 +3130,8 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
// var_dump("{$ancestorClass}.{$type}_{$name}");
$autoLabels[$name] = _t("{$ancestorClass}.{$type}_{$name}",FormField::name_to_label($name));
}
}
}
}
}
$labels = array_merge((array)$autoLabels, (array)$customLabels);
$this->extend('updateFieldLabels', $labels);
@ -3278,7 +3278,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
*
* <code>
* array(
* 'MySQLDatabase' => 'ENGINE=MyISAM'
* 'MySQLDatabase' => 'ENGINE=MyISAM'
* )
* </code>
*
@ -3321,8 +3321,8 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
*
* Example:
* array(
* array('Title' => "DefaultPage1", 'PageTitle' => 'page1'),
* array('Title' => "DefaultPage2")
* array('Title' => "DefaultPage1", 'PageTitle' => 'page1'),
* array('Title' => "DefaultPage2")
* ).
*
* @var array
@ -3378,7 +3378,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
* Example code:
* <code>
* public static $many_many_extraFields = array(
* 'Members' => array(
* 'Members' => array(
* 'Role' => 'Varchar(100)'
* )
* );
@ -3408,8 +3408,8 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
*
* Overriding the default filter, with a custom defined filter:
* <code>
* static $searchable_fields = array(
* "Name" => "PartialMatchFilter"
* static $searchable_fields = array(
* "Name" => "PartialMatchFilter"
* );
* </code>
*
@ -3417,21 +3417,21 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
* The 'filter' parameter will be generated from {@link DBField::$default_search_filter_class}.
* The 'title' parameter will be generated from {@link DataObject->fieldLabels()}.
* <code>
* static $searchable_fields = array(
* "Name" => array(
* "field" => "TextField"
* )
* static $searchable_fields = array(
* "Name" => array(
* "field" => "TextField"
* )
* );
* </code>
*
* Overriding the default form field, filter and title:
* <code>
* static $searchable_fields = array(
* "Organisation.ZipCode" => array(
* "field" => "TextField",
* "filter" => "PartialMatchFilter",
* "title" => 'Organisation ZIP'
* )
* static $searchable_fields = array(
* "Organisation.ZipCode" => array(
* "field" => "TextField",
* "filter" => "PartialMatchFilter",
* "title" => 'Organisation ZIP'
* )
* );
* </code>
*/
@ -3483,21 +3483,21 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
}
/**
* Returns true if the given method/parameter has a value
* (Uses the DBField::hasValue if the parameter is a database field)
*
* Returns true if the given method/parameter has a value
* (Uses the DBField::hasValue if the parameter is a database field)
*
* @param string $field The field name
* @param array $arguments
* @param bool $cache
* @return boolean
*/
public function hasValue($field, $arguments = null, $cache = true) {
$obj = $this->dbObject($field);
if($obj) {
return $obj->exists();
} else {
return parent::hasValue($field, $arguments, $cache);
}
}
* @return boolean
*/
public function hasValue($field, $arguments = null, $cache = true) {
$obj = $this->dbObject($field);
if($obj) {
return $obj->exists();
} else {
return parent::hasValue($field, $arguments, $cache);
}
}
}

View File

@ -338,7 +338,7 @@ class DataQuery {
* @param String $field Unquoted database column name (will be escaped automatically)
*/
public function max($field) {
return $this->aggregate(sprintf('MAX("%s")', Convert::raw2sql($field)));
return $this->aggregate(sprintf('MAX("%s")', Convert::raw2sql($field)));
}
/**
@ -347,7 +347,7 @@ class DataQuery {
* @param String $field Unquoted database column name (will be escaped automatically)
*/
public function min($field) {
return $this->aggregate(sprintf('MIN("%s")', Convert::raw2sql($field)));
return $this->aggregate(sprintf('MIN("%s")', Convert::raw2sql($field)));
}
/**
@ -356,7 +356,7 @@ class DataQuery {
* @param String $field Unquoted database column name (will be escaped automatically)
*/
public function avg($field) {
return $this->aggregate(sprintf('AVG("%s")', Convert::raw2sql($field)));
return $this->aggregate(sprintf('AVG("%s")', Convert::raw2sql($field)));
}
/**
@ -365,14 +365,14 @@ class DataQuery {
* @param String $field Unquoted database column name (will be escaped automatically)
*/
public function sum($field) {
return $this->aggregate(sprintf('SUM("%s")', Convert::raw2sql($field)));
return $this->aggregate(sprintf('SUM("%s")', Convert::raw2sql($field)));
}
/**
* Runs a raw aggregate expression. Please handle escaping yourself
*/
public function aggregate($expression) {
return $this->getFinalisedQuery()->aggregate($expression)->execute()->value();
return $this->getFinalisedQuery()->aggregate($expression)->execute()->value();
}
/**
@ -567,74 +567,74 @@ class DataQuery {
* @return The model class of the related item
*/
public function applyRelation($relation) {
// NO-OP
if(!$relation) return $this->dataClass;
if(is_string($relation)) $relation = explode(".", $relation);
$modelClass = $this->dataClass;
foreach($relation as $rel) {
$model = singleton($modelClass);
if ($component = $model->has_one($rel)) {
if(!$this->query->isJoinedTo($component)) {
$foreignKey = $model->getReverseAssociation($component);
$this->query->addLeftJoin($component,
"\"$component\".\"ID\" = \"{$modelClass}\".\"{$foreignKey}ID\"");
// NO-OP
if(!$relation) return $this->dataClass;
if(is_string($relation)) $relation = explode(".", $relation);
$modelClass = $this->dataClass;
foreach($relation as $rel) {
$model = singleton($modelClass);
if ($component = $model->has_one($rel)) {
if(!$this->query->isJoinedTo($component)) {
$foreignKey = $model->getReverseAssociation($component);
$this->query->addLeftJoin($component,
"\"$component\".\"ID\" = \"{$modelClass}\".\"{$foreignKey}ID\"");
/**
* add join clause to the component's ancestry classes so that the search filter could search on
* its ancestor fields.
*/
$ancestry = ClassInfo::ancestry($component, true);
if(!empty($ancestry)){
$ancestry = array_reverse($ancestry);
foreach($ancestry as $ancestor){
if($ancestor != $component){
$this->query->addInnerJoin($ancestor, "\"$component\".\"ID\" = \"$ancestor\".\"ID\"");
}
}
}
}
$modelClass = $component;
/**
* add join clause to the component's ancestry classes so that the search filter could search on
* its ancestor fields.
*/
$ancestry = ClassInfo::ancestry($component, true);
if(!empty($ancestry)){
$ancestry = array_reverse($ancestry);
foreach($ancestry as $ancestor){
if($ancestor != $component){
$this->query->addInnerJoin($ancestor, "\"$component\".\"ID\" = \"$ancestor\".\"ID\"");
}
}
}
}
$modelClass = $component;
} elseif ($component = $model->has_many($rel)) {
if(!$this->query->isJoinedTo($component)) {
$ancestry = $model->getClassAncestry();
$foreignKey = $model->getRemoteJoinField($rel);
$this->query->addLeftJoin($component,
"\"$component\".\"{$foreignKey}\" = \"{$ancestry[0]}\".\"ID\"");
/**
* add join clause to the component's ancestry classes so that the search filter could search on
* its ancestor fields.
*/
$ancestry = ClassInfo::ancestry($component, true);
if(!empty($ancestry)){
$ancestry = array_reverse($ancestry);
foreach($ancestry as $ancestor){
if($ancestor != $component){
$this->query->addInnerJoin($ancestor, "\"$component\".\"ID\" = \"$ancestor\".\"ID\"");
}
}
}
}
$modelClass = $component;
} elseif ($component = $model->has_many($rel)) {
if(!$this->query->isJoinedTo($component)) {
$ancestry = $model->getClassAncestry();
$foreignKey = $model->getRemoteJoinField($rel);
$this->query->addLeftJoin($component,
"\"$component\".\"{$foreignKey}\" = \"{$ancestry[0]}\".\"ID\"");
/**
* add join clause to the component's ancestry classes so that the search filter could search on
* its ancestor fields.
*/
$ancestry = ClassInfo::ancestry($component, true);
if(!empty($ancestry)){
$ancestry = array_reverse($ancestry);
foreach($ancestry as $ancestor){
if($ancestor != $component){
$this->query->addInnerJoin($ancestor, "\"$component\".\"ID\" = \"$ancestor\".\"ID\"");
}
}
}
}
$modelClass = $component;
} elseif ($component = $model->many_many($rel)) {
list($parentClass, $componentClass, $parentField, $componentField, $relationTable) = $component;
$parentBaseClass = ClassInfo::baseDataClass($parentClass);
$componentBaseClass = ClassInfo::baseDataClass($componentClass);
$this->query->addInnerJoin($relationTable,
"\"$relationTable\".\"$parentField\" = \"$parentBaseClass\".\"ID\"");
$this->query->addLeftJoin($componentBaseClass,
"\"$relationTable\".\"$componentField\" = \"$componentBaseClass\".\"ID\"");
if(ClassInfo::hasTable($componentClass)) {
$this->query->addLeftJoin($componentClass,
"\"$relationTable\".\"$componentField\" = \"$componentClass\".\"ID\"");
}
$modelClass = $componentClass;
} elseif ($component = $model->many_many($rel)) {
list($parentClass, $componentClass, $parentField, $componentField, $relationTable) = $component;
$parentBaseClass = ClassInfo::baseDataClass($parentClass);
$componentBaseClass = ClassInfo::baseDataClass($componentClass);
$this->query->addInnerJoin($relationTable,
"\"$relationTable\".\"$parentField\" = \"$parentBaseClass\".\"ID\"");
$this->query->addLeftJoin($componentBaseClass,
"\"$relationTable\".\"$componentField\" = \"$componentBaseClass\".\"ID\"");
if(ClassInfo::hasTable($componentClass)) {
$this->query->addLeftJoin($componentClass,
"\"$relationTable\".\"$componentField\" = \"$componentClass\".\"ID\"");
}
$modelClass = $componentClass;
}
}
}
return $modelClass;

View File

@ -422,7 +422,7 @@ abstract class SS_Database {
//Indexes specified as arrays cannot be checked with this line: (it flattens out the array)
if(!is_array($spec)) {
$spec = preg_replace('/\s*,\s*/', ',', $spec);
}
}
if(!isset($this->tableList[strtolower($table)])) $newTable = true;
@ -1142,7 +1142,7 @@ abstract class SS_Query implements Iterator {
$result .= "<tr>";
foreach($record as $k => $v) {
$result .= "<th>" . Convert::raw2xml($k) . "</th> ";
}
}
$result .= "</tr> \n";
}
@ -1219,7 +1219,7 @@ abstract class SS_Query implements Iterator {
*/
public function valid() {
if(!$this->queryHasBegun) $this->next();
return $this->currentRecord !== false;
return $this->currentRecord !== false;
}
/**

View File

@ -298,8 +298,8 @@ class DatabaseAdmin extends Controller {
foreach($subclasses as $subclass) {
$id = $record['ID'];
if(($record['ClassName'] != $subclass) &&
(!is_subclass_of($record['ClassName'], $subclass)) &&
(isset($recordExists[$subclass][$id]))) {
(!is_subclass_of($record['ClassName'], $subclass)) &&
(isset($recordExists[$subclass][$id]))) {
$sql = "DELETE FROM \"$subclass\" WHERE \"ID\" = $record[ID]";
echo "<li>$sql";
DB::query($sql);

View File

@ -66,10 +66,10 @@ class HasManyList extends RelationList {
* @param $itemID The ID of the item to be removed
*/
public function removeByID($itemID) {
$item = $this->byID($itemID);
return $this->remove($item);
}
$item = $this->byID($itemID);
return $this->remove($item);
}
/**
* Remove an item from this relation.
* Doesn't actually remove the item, it just clears the foreign key value.
@ -77,10 +77,10 @@ class HasManyList extends RelationList {
* @todo Maybe we should delete the object instead?
*/
public function remove($item) {
if(!($item instanceof $this->dataClass)) {
throw new InvalidArgumentException("HasManyList::remove() expecting a $this->dataClass object, or ID",
E_USER_ERROR);
}
if(!($item instanceof $this->dataClass)) {
throw new InvalidArgumentException("HasManyList::remove() expecting a $this->dataClass object, or ID",
E_USER_ERROR);
}
$fk = $this->foreignKey;
$item->$fk = null;

View File

@ -434,14 +434,14 @@ class Hierarchy extends DataExtension {
public function Children() {
if(!(isset($this->_cache_children) && $this->_cache_children)) {
$result = $this->owner->stageChildren(false);
if(isset($result)) {
$this->_cache_children = new ArrayList();
foreach($result as $child) {
if($child->canView()) {
$this->_cache_children->push($child);
}
}
}
if(isset($result)) {
$this->_cache_children = new ArrayList();
foreach($result as $child) {
if($child->canView()) {
$this->_cache_children->push($child);
}
}
}
}
return $this->_cache_children;
}
@ -487,10 +487,10 @@ class Hierarchy extends DataExtension {
// Next, go through the live children. Only some of these will be listed
$liveChildren = $this->owner->liveChildren(true, true);
if($liveChildren) {
$merged = new ArrayList();
$merged->merge($stageChildren);
$merged->merge($liveChildren);
$stageChildren = $merged;
$merged = new ArrayList();
$merged->merge($stageChildren);
$merged->merge($liveChildren);
$stageChildren = $merged;
}
}
@ -526,7 +526,7 @@ class Hierarchy extends DataExtension {
throw new Exception('Hierarchy->AllHistoricalChildren() only works with Versioned extension applied');
}
return Versioned::get_including_deleted(ClassInfo::baseDataClass($this->owner->class),
return Versioned::get_including_deleted(ClassInfo::baseDataClass($this->owner->class),
"\"ParentID\" = " . (int)$this->owner->ID)->count();
}

View File

@ -117,11 +117,11 @@ class ManyManyList extends RelationList {
* @param $itemID The ID of the item to remove.
*/
public function remove($item) {
if(!($item instanceof $this->dataClass)) {
throw new InvalidArgumentException("ManyManyList::remove() expecting a $this->dataClass object");
}
return $this->removeByID($item->ID);
if(!($item instanceof $this->dataClass)) {
throw new InvalidArgumentException("ManyManyList::remove() expecting a $this->dataClass object");
}
return $this->removeByID($item->ID);
}
/**
@ -130,7 +130,7 @@ class ManyManyList extends RelationList {
* @param $itemID The item it
*/
public function removeByID($itemID) {
if(!is_numeric($itemID)) throw new InvalidArgumentException("ManyManyList::removeById() expecting an ID");
if(!is_numeric($itemID)) throw new InvalidArgumentException("ManyManyList::removeById() expecting an ID");
$query = new SQLQuery("*", array("\"$this->joinTable\""));
$query->setDelete(true);
@ -145,16 +145,16 @@ class ManyManyList extends RelationList {
$query->execute();
}
/**
* Remove all items from this many-many join. To remove a subset of items, filter it first.
*/
public function removeAll() {
/**
* Remove all items from this many-many join. To remove a subset of items, filter it first.
*/
public function removeAll() {
$query = $this->dataQuery()->query();
$query->setDelete(true);
$query->setSelect(array('*'));
$query->setFrom("\"$this->joinTable\"");
$query->execute();
}
}
/**
* Find the extra field data for a single row of the relationship

View File

@ -269,8 +269,8 @@ class MySQLDatabase extends SS_Database {
if($alteredIndexes) foreach($alteredIndexes as $k => $v) {
$alterList[] .= "DROP INDEX \"$k\"";
$alterList[] .= "ADD ". $this->getIndexSqlDefinition($k, $v);
}
}
if($alteredOptions && isset($alteredOptions[get_class($this)])) {
if(!isset($this->indexList[$tableName])) {
$this->indexList[$tableName] = $this->indexList($tableName);
@ -298,7 +298,7 @@ class MySQLDatabase extends SS_Database {
}
}
$alterations = implode(",\n", $alterList);
$alterations = implode(",\n", $alterList);
$this->query("ALTER TABLE \"$tableName\" $alterations");
}
@ -467,9 +467,9 @@ class MySQLDatabase extends SS_Database {
$indexSpec = trim($indexSpec);
if($indexSpec[0] != '(') list($indexType, $indexFields) = explode(' ',$indexSpec,2);
else $indexFields = $indexSpec;
else $indexFields = $indexSpec;
if(!isset($indexType))
if(!isset($indexType))
$indexType = "index";
if($indexType=='using')
@ -499,15 +499,15 @@ class MySQLDatabase extends SS_Database {
$indexSpec=$this->convertIndexSpec($indexSpec);
$indexSpec = trim($indexSpec);
if($indexSpec[0] != '(') {
list($indexType, $indexFields) = explode(' ',$indexSpec,2);
} else {
$indexFields = $indexSpec;
}
if($indexSpec[0] != '(') {
list($indexType, $indexFields) = explode(' ',$indexSpec,2);
} else {
$indexFields = $indexSpec;
}
if(!$indexType) {
$indexType = "index";
}
if(!$indexType) {
$indexType = "index";
}
$this->query("ALTER TABLE \"$tableName\" DROP INDEX \"$indexName\"");
$this->query("ALTER TABLE \"$tableName\" ADD $indexType \"$indexName\" $indexFields");
@ -822,19 +822,19 @@ class MySQLDatabase extends SS_Database {
if(!class_exists('File')) throw new Exception('MySQLDatabase->searchEngine() requires "File" class');
$fileFilter = '';
$keywords = Convert::raw2sql($keywords);
$keywords = Convert::raw2sql($keywords);
$htmlEntityKeywords = htmlentities($keywords, ENT_NOQUOTES, 'UTF-8');
$extraFilters = array('SiteTree' => '', 'File' => '');
if($booleanSearch) $boolean = "IN BOOLEAN MODE";
if($booleanSearch) $boolean = "IN BOOLEAN MODE";
if($extraFilter) {
$extraFilters['SiteTree'] = " AND $extraFilter";
if($extraFilter) {
$extraFilters['SiteTree'] = " AND $extraFilter";
if($alternativeFileFilter) $extraFilters['File'] = " AND $alternativeFileFilter";
else $extraFilters['File'] = $extraFilters['SiteTree'];
}
if($alternativeFileFilter) $extraFilters['File'] = " AND $alternativeFileFilter";
else $extraFilters['File'] = $extraFilters['SiteTree'];
}
// Always ensure that only pages with ShowInSearch = 1 can be searched
$extraFilters['SiteTree'] .= " AND ShowInSearch <> 0";
@ -982,7 +982,7 @@ class MySQLDatabase extends SS_Database {
$boolean = $booleanSearch ? "IN BOOLEAN MODE" : "";
$fieldNames = '"' . implode('", "', $fields) . '"';
$SQL_keywords = Convert::raw2sql($keywords);
$SQL_keywords = Convert::raw2sql($keywords);
$SQL_htmlEntityKeywords = Convert::raw2sql(htmlentities($keywords, ENT_NOQUOTES, 'UTF-8'));
return "(MATCH ($fieldNames) AGAINST ('$SQL_keywords' $boolean) + MATCH ($fieldNames)"
@ -1151,7 +1151,7 @@ class MySQLDatabase extends SS_Database {
* @param string $date2 to be substracted of $date1, can be either 'now', literal datetime like
* '1973-10-14 10:30:00' or field name, e.g. '"SiteTree"."Created"'
* @return string SQL datetime expression to query for the interval between $date1 and $date2 in seconds which
* is the result of the substraction
* is the result of the substraction
*/
public function datetimeDifferenceClause($date1, $date2) {

View File

@ -908,11 +908,11 @@ class SQLQuery {
* @return string
*/
public function __toString() {
try {
return $this->sql();
} catch(Exception $e) {
return "<sql query>";
}
try {
return $this->sql();
} catch(Exception $e) {
return "<sql query>";
}
}
/**

View File

@ -53,6 +53,6 @@ class SS_Transliterator extends Object {
* Transliteration using iconv()
*/
protected function useIconv($source) {
return iconv("utf-8", "us-ascii//IGNORE//TRANSLIT", $source);
return iconv("utf-8", "us-ascii//IGNORE//TRANSLIT", $source);
}
}

View File

@ -136,8 +136,8 @@ class Versioned extends DataExtension {
* @todo Should this all go into VersionedDataQuery?
*/
public function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) {
$baseTable = ClassInfo::baseDataClass($dataQuery->dataClass());
$baseTable = ClassInfo::baseDataClass($dataQuery->dataClass());
switch($dataQuery->getQueryParam('Versioned.mode')) {
// Noop
case '':
@ -266,8 +266,8 @@ class Versioned extends DataExtension {
*/
function augmentLoadLazyFields(SQLQuery &$query, DataQuery &$dataQuery = null, $record) {
$dataClass = $dataQuery->dataClass();
if (isset($record['Version'])){
$dataQuery->where("\"$dataClass\".\"RecordID\" = " . $record['ID']);
if (isset($record['Version'])){
$dataQuery->where("\"$dataClass\".\"RecordID\" = " . $record['ID']);
$dataQuery->where("\"$dataClass\".\"Version\" = " . $record['Version']);
$dataQuery->setQueryParam('Versioned.mode', 'all_versions');
}

View File

@ -330,23 +330,23 @@ class Date extends DBField {
public function days_between($fyear, $fmonth, $fday, $tyear, $tmonth, $tday){
return abs((mktime ( 0, 0, 0, $fmonth, $fday, $fyear) - mktime ( 0, 0, 0, $tmonth, $tday, $tyear))/(60*60*24));
return abs((mktime ( 0, 0, 0, $fmonth, $fday, $fyear) - mktime ( 0, 0, 0, $tmonth, $tday, $tyear))/(60*60*24));
}
public function day_before($fyear, $fmonth, $fday){
return date ("Y-m-d", mktime (0,0,0,$fmonth,$fday-1,$fyear));
return date ("Y-m-d", mktime (0,0,0,$fmonth,$fday-1,$fyear));
}
public function next_day($fyear, $fmonth, $fday){
return date ("Y-m-d", mktime (0,0,0,$fmonth,$fday+1,$fyear));
return date ("Y-m-d", mktime (0,0,0,$fmonth,$fday+1,$fyear));
}
public function weekday($fyear, $fmonth, $fday){ // 0 is a Monday
return (((mktime ( 0, 0, 0, $fmonth, $fday, $fyear) - mktime ( 0, 0, 0, 7, 17, 2006))/(60*60*24))+700000) % 7;
return (((mktime ( 0, 0, 0, $fmonth, $fday, $fyear) - mktime ( 0, 0, 0, 7, 17, 2006))/(60*60*24))+700000) % 7;
}
public function prior_monday($fyear, $fmonth, $fday){
return date ("Y-m-d", mktime (0,0,0,$fmonth,$fday-$this->weekday($fyear, $fmonth, $fday),$fyear));
return date ("Y-m-d", mktime (0,0,0,$fmonth,$fday-$this->weekday($fyear, $fmonth, $fday),$fyear));
}
/**

View File

@ -33,7 +33,7 @@ class Text extends StringField {
'NoHTML' => 'Text',
);
/**
/**
* (non-PHPdoc)
* @see DBField::requireField()
*/

View File

@ -17,8 +17,8 @@ class Varchar extends StringField {
);
protected $size;
/**
/**
* Construct a new short text field
*
* @param $name string The name of the field
@ -27,12 +27,12 @@ class Varchar extends StringField {
* See {@link StringField::setOptions()} for information on the available options
* @return unknown_type
*/
public function __construct($name = null, $size = 50, $options = array()) {
public function __construct($name = null, $size = 50, $options = array()) {
$this->size = $size ? $size : 50;
parent::__construct($name, $options);
}
/**
/**
* (non-PHPdoc)
* @see DBField::requireField()
*/

View File

@ -27,7 +27,7 @@ class BBCodeParser extends TextParser {
* @var Boolean
*/
protected static $allowSimilies = false;
/**
* Set the location of the smiles folder. By default use the ones in framework
* but this can be overridden by setting BBCodeParser::set_icon_folder('themes/yourtheme/images/');
@ -165,7 +165,7 @@ class BBCodeParser extends TextParser {
'#(?<!\w):\((?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/sad.gif'> ", // :(
'#(?<!\w):-\((?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/sad.gif'> ", // :-(
'#(?<!\w):p(?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/tongue.gif'> ", // :p
'#(?<!\w)8-\)(?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/cool.gif'> ", // 8-)
'#(?<!\w)8-\)(?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/cool.gif'> ", // 8-)
'#(?<!\w):\^\)(?!\w)#i' => " <img src='".BBCodeParser::smilies_location(). "/confused.gif'> " // :^)
);
$this->content = preg_replace(array_keys($smilies), array_values($smilies), $this->content);

View File

@ -55,819 +55,818 @@
*/
class SSHTMLBBCodeParser
{
/**
* An array of tags parsed by the engine, should be overwritten by filters
*
* @access private
* @var array
*/
var $_definedTags = array();
/**
* An array of tags parsed by the engine, should be overwritten by filters
*
* @access private
* @var array
*/
var $_definedTags = array();
/**
* A string containing the input
*
* @access private
* @var string
*/
var $_text = '';
/**
* A string containing the input
*
* @access private
* @var string
*/
var $_text = '';
/**
* A string containing the preparsed input
*
* @access private
* @var string
*/
var $_preparsed = '';
/**
* A string containing the preparsed input
*
* @access private
* @var string
*/
var $_preparsed = '';
/**
* An array tags and texts build from the input text
*
* @access private
* @var array
*/
var $_tagArray = array();
/**
* An array tags and texts build from the input text
*
* @access private
* @var array
*/
var $_tagArray = array();
/**
* A string containing the parsed version of the text
*
* @access private
* @var string
*/
var $_parsed = '';
/**
* A string containing the parsed version of the text
*
* @access private
* @var string
*/
var $_parsed = '';
/**
* An array of options, filled by an ini file or through the contructor
*
* @access private
* @var array
*/
var $_options = array(
'quotestyle' => 'double',
'quotewhat' => 'all',
'open' => '[',
'close' => ']',
'xmlclose' => true,
'filters' => 'Basic'
);
/**
* An array of options, filled by an ini file or through the contructor
*
* @access private
* @var array
*/
var $_options = array(
'quotestyle' => 'double',
'quotewhat' => 'all',
'open' => '[',
'close' => ']',
'xmlclose' => true,
'filters' => 'Basic'
);
/**
* An array of filters used for parsing
*
* @access private
* @var array
*/
var $_filters = array();
/**
* An array of filters used for parsing
*
* @access private
* @var array
*/
var $_filters = array();
/**
* Constructor, initialises the options and filters
*
* Sets the private variable _options with base options defined with
* &PEAR::getStaticProperty(), overwriting them with (if present)
* the argument to this method.
* Then it sets the extra options to properly escape the tag
* characters in preg_replace() etc. The set options are
* then stored back with &PEAR::getStaticProperty(), so that the filter
* classes can use them.
* All the filters in the options are initialised and their defined tags
* are copied into the private variable _definedTags.
*
* @param array options to use, can be left out
* @return none
* @access public
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function SSHTMLBBCodeParser($options = array())
{
// set the already set options
$baseoptions = &SSHTMLBBCodeParser::getStaticProperty('SSHTMLBBCodeParser', '_options');
if (is_array($baseoptions)) {
foreach ($baseoptions as $k => $v) {
$this->_options[$k] = $v;
}
}
/**
* Constructor, initialises the options and filters
*
* Sets the private variable _options with base options defined with
* &PEAR::getStaticProperty(), overwriting them with (if present)
* the argument to this method.
* Then it sets the extra options to properly escape the tag
* characters in preg_replace() etc. The set options are
* then stored back with &PEAR::getStaticProperty(), so that the filter
* classes can use them.
* All the filters in the options are initialised and their defined tags
* are copied into the private variable _definedTags.
*
* @param array options to use, can be left out
* @return none
* @access public
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function SSHTMLBBCodeParser($options = array())
{
// set the already set options
$baseoptions = &SSHTMLBBCodeParser::getStaticProperty('SSHTMLBBCodeParser', '_options');
if (is_array($baseoptions)) {
foreach ($baseoptions as $k => $v) {
$this->_options[$k] = $v;
}
}
// set the options passed as an argument
foreach ($options as $k => $v ) {
$this->_options[$k] = $v;
}
// set the options passed as an argument
foreach ($options as $k => $v ) {
$this->_options[$k] = $v;
}
// add escape open and close chars to the options for preg escaping
$preg_escape = '\^$.[]|()?*+{}';
if ($this->_options['open'] != '' && strpos($preg_escape, $this->_options['open'])) {
$this->_options['open_esc'] = "\\".$this->_options['open'];
} else {
$this->_options['open_esc'] = $this->_options['open'];
}
if ($this->_options['close'] != '' && strpos($preg_escape, $this->_options['close'])) {
$this->_options['close_esc'] = "\\".$this->_options['close'];
} else {
$this->_options['close_esc'] = $this->_options['close'];
}
// add escape open and close chars to the options for preg escaping
$preg_escape = '\^$.[]|()?*+{}';
if ($this->_options['open'] != '' && strpos($preg_escape, $this->_options['open'])) {
$this->_options['open_esc'] = "\\".$this->_options['open'];
} else {
$this->_options['open_esc'] = $this->_options['open'];
}
if ($this->_options['close'] != '' && strpos($preg_escape, $this->_options['close'])) {
$this->_options['close_esc'] = "\\".$this->_options['close'];
} else {
$this->_options['close_esc'] = $this->_options['close'];
}
// set the options back so that child classes can use them */
$baseoptions = $this->_options;
unset($baseoptions);
// set the options back so that child classes can use them */
$baseoptions = $this->_options;
unset($baseoptions);
// return if this is a subclass
if (is_subclass_of($this, 'SSHTMLBBCodeParser_Filter')) {
return;
}
// return if this is a subclass
if (is_subclass_of($this, 'SSHTMLBBCodeParser_Filter')) {
return;
}
// extract the definedTags from subclasses */
$this->addFilters($this->_options['filters']);
}
static function &getStaticProperty($class, $var)
{
static $properties;
if (!isset($properties[$class])) {
$properties[$class] = array();
}
if (!array_key_exists($var, $properties[$class])) {
$properties[$class][$var] = null;
}
return $properties[$class][$var];
}
// extract the definedTags from subclasses */
$this->addFilters($this->_options['filters']);
}
static function &getStaticProperty($class, $var)
{
static $properties;
if (!isset($properties[$class])) {
$properties[$class] = array();
}
if (!array_key_exists($var, $properties[$class])) {
$properties[$class][$var] = null;
}
return $properties[$class][$var];
}
/**
* Option setter
*
* @param string option name
* @param mixed option value
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
public function setOption($name, $value)
{
$this->_options[$name] = $value;
}
/**
* Option setter
*
* @param string option name
* @param mixed option value
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
public function setOption($name, $value)
{
$this->_options[$name] = $value;
}
/**
* Add a new filter
*
* @param string filter
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
public function addFilter($filter)
{
$filter = ucfirst($filter);
if (!array_key_exists($filter, $this->_filters)) {
$class = 'SSHTMLBBCodeParser_Filter_'.$filter;
if (fopen('BBCodeParser/Filter/'.$filter.'.php','r',true)) {
include_once 'BBCodeParser/Filter/'.$filter.'.php';
}
if (!class_exists($class)) {
/**
* Add a new filter
*
* @param string filter
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
public function addFilter($filter)
{
$filter = ucfirst($filter);
if (!array_key_exists($filter, $this->_filters)) {
$class = 'SSHTMLBBCodeParser_Filter_'.$filter;
if (fopen('BBCodeParser/Filter/'.$filter.'.php','r',true)) {
include_once 'BBCodeParser/Filter/'.$filter.'.php';
}
if (!class_exists($class)) {
//PEAR::raiseError("Failed to load filter $filter", null, PEAR_ERROR_DIE);
}
//PEAR::raiseError("Failed to load filter $filter", null, PEAR_ERROR_DIE);
}
else {
$this->_filters[$filter] = new $class;
$this->_definedTags = array_merge(
$this->_definedTags,
$this->_filters[$filter]->_definedTags
);
$this->_definedTags = array_merge(
$this->_definedTags,
$this->_filters[$filter]->_definedTags
);
}
}
}
}
}
/**
* Remove an existing filter
*
* @param string $filter
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
public function removeFilter($filter)
{
$filter = ucfirst(trim($filter));
if (!empty($filter) && array_key_exists($filter, $this->_filters)) {
unset($this->_filters[$filter]);
}
// also remove the related $this->_definedTags for this filter,
// preserving the others
$this->_definedTags = array();
foreach (array_keys($this->_filters) as $filter) {
$this->_definedTags = array_merge(
$this->_definedTags,
$this->_filters[$filter]->_definedTags
);
}
}
/**
* Remove an existing filter
*
* @param string $filter
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
public function removeFilter($filter)
{
$filter = ucfirst(trim($filter));
if (!empty($filter) && array_key_exists($filter, $this->_filters)) {
unset($this->_filters[$filter]);
}
// also remove the related $this->_definedTags for this filter,
// preserving the others
$this->_definedTags = array();
foreach (array_keys($this->_filters) as $filter) {
$this->_definedTags = array_merge(
$this->_definedTags,
$this->_filters[$filter]->_definedTags
);
}
}
/**
* Add new filters
*
* @param mixed (array or string)
* @return boolean true if all ok, false if not.
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
public function addFilters($filters)
{
if (is_string($filters)) {
//comma-separated list
if (strpos($filters, ',') !== false) {
$filters = explode(',', $filters);
} else {
$filters = array($filters);
}
}
if (!is_array($filters)) {
//invalid format
return false;
}
foreach ($filters as $filter) {
if (trim($filter)){
$this->addFilter($filter);
}
}
return true;
}
/**
* Add new filters
*
* @param mixed (array or string)
* @return boolean true if all ok, false if not.
* @author Lorenzo Alberton <l.alberton@quipo.it>
*/
public function addFilters($filters)
{
if (is_string($filters)) {
//comma-separated list
if (strpos($filters, ',') !== false) {
$filters = explode(',', $filters);
} else {
$filters = array($filters);
}
}
if (!is_array($filters)) {
//invalid format
return false;
}
foreach ($filters as $filter) {
if (trim($filter)){
$this->addFilter($filter);
}
}
return true;
}
/**
* Executes statements before the actual array building starts
*
* This method should be overwritten in a filter if you want to do
* something before the parsing process starts. This can be useful to
* allow certain short alternative tags which then can be converted into
* proper tags with preg_replace() calls.
* The main class walks through all the filters and and calls this
* method. The filters should modify their private $_preparsed
* variable, with input from $_text.
*
* @return none
* @access private
* @see $_text
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function _preparse()
{
// default: assign _text to _preparsed, to be overwritten by filters
$this->_preparsed = $this->_text;
/**
* Executes statements before the actual array building starts
*
* This method should be overwritten in a filter if you want to do
* something before the parsing process starts. This can be useful to
* allow certain short alternative tags which then can be converted into
* proper tags with preg_replace() calls.
* The main class walks through all the filters and and calls this
* method. The filters should modify their private $_preparsed
* variable, with input from $_text.
*
* @return none
* @access private
* @see $_text
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function _preparse()
{
// default: assign _text to _preparsed, to be overwritten by filters
$this->_preparsed = $this->_text;
// return if this is a subclass
if (is_subclass_of($this, 'SSHTMLBBCodeParser')) {
return;
}
// return if this is a subclass
if (is_subclass_of($this, 'SSHTMLBBCodeParser')) {
return;
}
// walk through the filters and execute _preparse
foreach ($this->_filters as $filter) {
$filter->setText($this->_preparsed);
$filter->_preparse();
$this->_preparsed = $filter->getPreparsed();
}
}
// walk through the filters and execute _preparse
foreach ($this->_filters as $filter) {
$filter->setText($this->_preparsed);
$filter->_preparse();
$this->_preparsed = $filter->getPreparsed();
}
}
/**
* Builds the tag array from the input string $_text
*
* An array consisting of tag and text elements is contructed from the
* $_preparsed variable. The method uses _buildTag() to check if a tag is
* valid and to build the actual tag to be added to the tag array.
*
* @todo - rewrite whole method, as this one is old and probably slow
* - see if a recursive method would be better than an iterative one
*
* @return none
* @access private
* @see _buildTag()
* @see $_text
* @see $_tagArray
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function _buildTagArray()
{
$this->_tagArray = array();
$str = $this->_preparsed;
$strPos = 0;
$strLength = strlen($str);
/**
* Builds the tag array from the input string $_text
*
* An array consisting of tag and text elements is contructed from the
* $_preparsed variable. The method uses _buildTag() to check if a tag is
* valid and to build the actual tag to be added to the tag array.
*
* @todo - rewrite whole method, as this one is old and probably slow
* - see if a recursive method would be better than an iterative one
*
* @return none
* @access private
* @see _buildTag()
* @see $_text
* @see $_tagArray
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function _buildTagArray()
{
$this->_tagArray = array();
$str = $this->_preparsed;
$strPos = 0;
$strLength = strlen($str);
while (($strPos < $strLength)) {
$tag = array();
$openPos = strpos($str, $this->_options['open'], $strPos);
if ($openPos === false) {
$openPos = $strLength;
$nextOpenPos = $strLength;
}
if ($openPos + 1 > $strLength) {
$nextOpenPos = $strLength;
} else {
$nextOpenPos = strpos($str, $this->_options['open'], $openPos + 1);
if ($nextOpenPos === false) {
$nextOpenPos = $strLength;
}
}
$closePos = strpos($str, $this->_options['close'], $strPos);
if ($closePos === false) {
$closePos = $strLength + 1;
}
while (($strPos < $strLength)) {
$tag = array();
$openPos = strpos($str, $this->_options['open'], $strPos);
if ($openPos === false) {
$openPos = $strLength;
$nextOpenPos = $strLength;
}
if ($openPos + 1 > $strLength) {
$nextOpenPos = $strLength;
} else {
$nextOpenPos = strpos($str, $this->_options['open'], $openPos + 1);
if ($nextOpenPos === false) {
$nextOpenPos = $strLength;
}
}
$closePos = strpos($str, $this->_options['close'], $strPos);
if ($closePos === false) {
$closePos = $strLength + 1;
}
if ($openPos == $strPos) {
if (($nextOpenPos < $closePos)) {
// new open tag before closing tag: treat as text
$newPos = $nextOpenPos;
$tag['text'] = substr($str, $strPos, $nextOpenPos - $strPos);
$tag['type'] = 0;
} else {
// possible valid tag
$newPos = $closePos + 1;
$newTag = $this->_buildTag(substr($str, $strPos, $closePos - $strPos + 1));
if (($newTag !== false)) {
$tag = $newTag;
} else {
// no valid tag after all
$tag['text'] = substr($str, $strPos, $closePos - $strPos + 1);
$tag['type'] = 0;
}
}
} else {
// just text
$newPos = $openPos;
$tag['text'] = substr($str, $strPos, $openPos - $strPos);
$tag['type'] = 0;
}
if ($openPos == $strPos) {
if (($nextOpenPos < $closePos)) {
// new open tag before closing tag: treat as text
$newPos = $nextOpenPos;
$tag['text'] = substr($str, $strPos, $nextOpenPos - $strPos);
$tag['type'] = 0;
} else {
// possible valid tag
$newPos = $closePos + 1;
$newTag = $this->_buildTag(substr($str, $strPos, $closePos - $strPos + 1));
if (($newTag !== false)) {
$tag = $newTag;
} else {
// no valid tag after all
$tag['text'] = substr($str, $strPos, $closePos - $strPos + 1);
$tag['type'] = 0;
}
}
} else {
// just text
$newPos = $openPos;
$tag['text'] = substr($str, $strPos, $openPos - $strPos);
$tag['type'] = 0;
}
// join 2 following text elements
if ($tag['type'] === 0 && isset($prev) && $prev['type'] === 0) {
$tag['text'] = $prev['text'].$tag['text'];
array_pop($this->_tagArray);
}
// join 2 following text elements
if ($tag['type'] === 0 && isset($prev) && $prev['type'] === 0) {
$tag['text'] = $prev['text'].$tag['text'];
array_pop($this->_tagArray);
}
$this->_tagArray[] = $tag;
$prev = $tag;
$strPos = $newPos;
}
}
$this->_tagArray[] = $tag;
$prev = $tag;
$strPos = $newPos;
}
}
/**
* Builds a tag from the input string
*
* This method builds a tag array based on the string it got as an
* argument. If the tag is invalid, <false> is returned. The tag
* attributes are extracted from the string and stored in the tag
* array as an associative array.
*
* @param string string to build tag from
* @return array tag in array format
* @access private
* @see _buildTagArray()
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function _buildTag($str)
{
$tag = array('text' => $str, 'attributes' => array());
/**
* Builds a tag from the input string
*
* This method builds a tag array based on the string it got as an
* argument. If the tag is invalid, <false> is returned. The tag
* attributes are extracted from the string and stored in the tag
* array as an associative array.
*
* @param string string to build tag from
* @return array tag in array format
* @access private
* @see _buildTagArray()
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function _buildTag($str)
{
$tag = array('text' => $str, 'attributes' => array());
if (substr($str, 1, 1) == '/') { // closing tag
if (substr($str, 1, 1) == '/') { // closing tag
$tag['tag'] = strtolower(substr($str, 2, strlen($str) - 3));
if (!in_array($tag['tag'], array_keys($this->_definedTags))) {
return false; // nope, it's not valid
} else {
$tag['type'] = 2;
return $tag;
}
} else { // opening tag
$tag['tag'] = strtolower(substr($str, 2, strlen($str) - 3));
if (!in_array($tag['tag'], array_keys($this->_definedTags))) {
return false; // nope, it's not valid
} else {
$tag['type'] = 2;
return $tag;
}
} else { // opening tag
$tag['type'] = 1;
if (strpos($str, ' ') && (strpos($str, '=') === false)) {
return false; // nope, it's not valid
}
$tag['type'] = 1;
if (strpos($str, ' ') && (strpos($str, '=') === false)) {
return false; // nope, it's not valid
}
// tnx to Onno for the regex
// split the tag with arguments and all
$oe = $this->_options['open_esc'];
$ce = $this->_options['close_esc'];
$tagArray = array();
if (preg_match("!$oe([a-z0-9]+)[^$ce]*$ce!i", $str, $tagArray) == 0) {
return false;
}
$tag['tag'] = strtolower($tagArray[1]);
if (!in_array($tag['tag'], array_keys($this->_definedTags))) {
return false; // nope, it's not valid
}
// tnx to Onno for the regex
// split the tag with arguments and all
$oe = $this->_options['open_esc'];
$ce = $this->_options['close_esc'];
$tagArray = array();
if (preg_match("!$oe([a-z0-9]+)[^$ce]*$ce!i", $str, $tagArray) == 0) {
return false;
}
$tag['tag'] = strtolower($tagArray[1]);
if (!in_array($tag['tag'], array_keys($this->_definedTags))) {
return false; // nope, it's not valid
}
// tnx to Onno for the regex
// validate the arguments
$attributeArray = array();
$regex = "![\s$oe]([a-z0-9]+)=(\"[^\s$ce]+\"|[^\s$ce]";
if ($tag['tag'] != 'url') {
$regex .= "[^=]";
}
$regex .= "+)(?=[\s$ce])!i";
preg_match_all($regex, $str, $attributeArray, PREG_SET_ORDER);
foreach ($attributeArray as $attribute) {
$attNam = strtolower($attribute[1]);
if (in_array($attNam, array_keys($this->_definedTags[$tag['tag']]['attributes']))) {
if ($attribute[2][0] == '"' && $attribute[2][strlen($attribute[2])-1] == '"') {
$tag['attributes'][$attNam] = substr($attribute[2], 1, -1);
} else {
$tag['attributes'][$attNam] = $attribute[2];
}
}
}
return $tag;
}
}
// tnx to Onno for the regex
// validate the arguments
$attributeArray = array();
$regex = "![\s$oe]([a-z0-9]+)=(\"[^\s$ce]+\"|[^\s$ce]";
if ($tag['tag'] != 'url') {
$regex .= "[^=]";
}
$regex .= "+)(?=[\s$ce])!i";
preg_match_all($regex, $str, $attributeArray, PREG_SET_ORDER);
foreach ($attributeArray as $attribute) {
$attNam = strtolower($attribute[1]);
if (in_array($attNam, array_keys($this->_definedTags[$tag['tag']]['attributes']))) {
if ($attribute[2][0] == '"' && $attribute[2][strlen($attribute[2])-1] == '"') {
$tag['attributes'][$attNam] = substr($attribute[2], 1, -1);
} else {
$tag['attributes'][$attNam] = $attribute[2];
}
}
}
return $tag;
}
}
/**
* Validates the tag array, regarding the allowed tags
*
* While looping through the tag array, two following text tags are
* joined, and it is checked that the tag is allowed inside the
* last opened tag.
* By remembering what tags have been opened it is checked that
* there is correct (xml compliant) nesting.
* In the end all still opened tags are closed.
*
* @return none
* @access private
* @see _isAllowed()
* @see $_tagArray
* @author Stijn de Reede <sjr@gmx.co.uk>, Seth Price <seth@pricepages.org>
*/
public function _validateTagArray()
{
$newTagArray = array();
$openTags = array();
foreach ($this->_tagArray as $tag) {
$prevTag = end($newTagArray);
switch ($tag['type']) {
case 0:
if (($child = $this->_childNeeded(end($openTags), 'text')) &&
$child !== false &&
/*
* No idea what to do in this case: A child is needed, but
* no valid one is returned. We'll ignore it here and live
* with it until someone reports a valid bug.
*/
$child !== true )
{
if (trim($tag['text']) == '') {
//just an empty indentation or newline without value?
continue;
}
$newTagArray[] = $child;
$openTags[] = $child['tag'];
}
if ($prevTag['type'] === 0) {
$tag['text'] = $prevTag['text'].$tag['text'];
array_pop($newTagArray);
}
$newTagArray[] = $tag;
break;
/**
* Validates the tag array, regarding the allowed tags
*
* While looping through the tag array, two following text tags are
* joined, and it is checked that the tag is allowed inside the
* last opened tag.
* By remembering what tags have been opened it is checked that
* there is correct (xml compliant) nesting.
* In the end all still opened tags are closed.
*
* @return none
* @access private
* @see _isAllowed()
* @see $_tagArray
* @author Stijn de Reede <sjr@gmx.co.uk>, Seth Price <seth@pricepages.org>
*/
public function _validateTagArray()
{
$newTagArray = array();
$openTags = array();
foreach ($this->_tagArray as $tag) {
$prevTag = end($newTagArray);
switch ($tag['type']) {
case 0:
if (($child = $this->_childNeeded(end($openTags), 'text')) &&
$child !== false &&
/*
* No idea what to do in this case: A child is needed, but
* no valid one is returned. We'll ignore it here and live
* with it until someone reports a valid bug.
*/
$child !== true )
{
if (trim($tag['text']) == '') {
//just an empty indentation or newline without value?
continue;
}
$newTagArray[] = $child;
$openTags[] = $child['tag'];
}
if ($prevTag['type'] === 0) {
$tag['text'] = $prevTag['text'].$tag['text'];
array_pop($newTagArray);
}
$newTagArray[] = $tag;
break;
case 1:
if (!$this->_isAllowed(end($openTags), $tag['tag']) ||
($parent = $this->_parentNeeded(end($openTags), $tag['tag'])) === true ||
($child = $this->_childNeeded(end($openTags), $tag['tag'])) === true) {
$tag['type'] = 0;
if ($prevTag['type'] === 0) {
$tag['text'] = $prevTag['text'].$tag['text'];
array_pop($newTagArray);
}
} else {
if ($parent) {
/*
* Avoid use of parent if we can help it. If we are
* trying to insert a new parent, but the current tag is
* the same as the previous tag, then assume that the
* previous tag structure is valid, and add this tag as
* a sibling. To add as a sibling, we need to close the
* current tag.
*/
if ($tag['tag'] == end($openTags)){
$newTagArray[] = $this->_buildTag('[/'.$tag['tag'].']');
array_pop($openTags);
} else {
$newTagArray[] = $parent;
$openTags[] = $parent['tag'];
}
}
if ($child) {
$newTagArray[] = $child;
$openTags[] = $child['tag'];
}
$openTags[] = $tag['tag'];
}
$newTagArray[] = $tag;
break;
case 1:
if (!$this->_isAllowed(end($openTags), $tag['tag']) ||
($parent = $this->_parentNeeded(end($openTags), $tag['tag'])) === true ||
($child = $this->_childNeeded(end($openTags), $tag['tag'])) === true) {
$tag['type'] = 0;
if ($prevTag['type'] === 0) {
$tag['text'] = $prevTag['text'].$tag['text'];
array_pop($newTagArray);
}
} else {
if ($parent) {
/*
* Avoid use of parent if we can help it. If we are
* trying to insert a new parent, but the current tag is
* the same as the previous tag, then assume that the
* previous tag structure is valid, and add this tag as
* a sibling. To add as a sibling, we need to close the
* current tag.
*/
if ($tag['tag'] == end($openTags)){
$newTagArray[] = $this->_buildTag('[/'.$tag['tag'].']');
array_pop($openTags);
} else {
$newTagArray[] = $parent;
$openTags[] = $parent['tag'];
}
}
if ($child) {
$newTagArray[] = $child;
$openTags[] = $child['tag'];
}
$openTags[] = $tag['tag'];
}
$newTagArray[] = $tag;
break;
case 2:
if (($tag['tag'] == end($openTags) || $this->_isAllowed(end($openTags), $tag['tag']))) {
if (in_array($tag['tag'], $openTags)) {
$tmpOpenTags = array();
while (end($openTags) != $tag['tag']) {
$newTagArray[] = $this->_buildTag('[/'.end($openTags).']');
$tmpOpenTags[] = end($openTags);
array_pop($openTags);
}
$newTagArray[] = $tag;
array_pop($openTags);
/* why is this here? it just seems to break things
* (nested lists where closing tags need to be
* generated)
while (end($tmpOpenTags)) {
$tmpTag = $this->_buildTag('['.end($tmpOpenTags).']');
$newTagArray[] = $tmpTag;
$openTags[] = $tmpTag['tag'];
array_pop($tmpOpenTags);
}*/
}
} else {
$tag['type'] = 0;
if ($prevTag['type'] === 0) {
$tag['text'] = $prevTag['text'].$tag['text'];
array_pop($newTagArray);
}
$newTagArray[] = $tag;
}
break;
}
}
while (end($openTags)) {
$newTagArray[] = $this->_buildTag('[/'.end($openTags).']');
array_pop($openTags);
}
$this->_tagArray = $newTagArray;
}
case 2:
if (($tag['tag'] == end($openTags) || $this->_isAllowed(end($openTags), $tag['tag']))) {
if (in_array($tag['tag'], $openTags)) {
$tmpOpenTags = array();
while (end($openTags) != $tag['tag']) {
$newTagArray[] = $this->_buildTag('[/'.end($openTags).']');
$tmpOpenTags[] = end($openTags);
array_pop($openTags);
}
$newTagArray[] = $tag;
array_pop($openTags);
/* why is this here? it just seems to break things
* (nested lists where closing tags need to be
* generated)
while (end($tmpOpenTags)) {
$tmpTag = $this->_buildTag('['.end($tmpOpenTags).']');
$newTagArray[] = $tmpTag;
$openTags[] = $tmpTag['tag'];
array_pop($tmpOpenTags);
}*/
}
} else {
$tag['type'] = 0;
if ($prevTag['type'] === 0) {
$tag['text'] = $prevTag['text'].$tag['text'];
array_pop($newTagArray);
}
$newTagArray[] = $tag;
}
break;
}
}
while (end($openTags)) {
$newTagArray[] = $this->_buildTag('[/'.end($openTags).']');
array_pop($openTags);
}
$this->_tagArray = $newTagArray;
}
/**
* Checks to see if a parent is needed
*
* Checks to see if the current $in tag has an appropriate parent. If it
* does, then it returns false. If a parent is needed, then it returns the
* first tag in the list to add to the stack.
*
* @param array tag that is on the outside
* @param array tag that is on the inside
* @return boolean false if not needed, tag if needed, true if out
* of our minds
* @access private
* @see _validateTagArray()
* @author Seth Price <seth@pricepages.org>
*/
public function _parentNeeded($out, $in)
{
if (!isset($this->_definedTags[$in]['parent']) ||
($this->_definedTags[$in]['parent'] == 'all')
) {
return false;
}
/**
* Checks to see if a parent is needed
*
* Checks to see if the current $in tag has an appropriate parent. If it
* does, then it returns false. If a parent is needed, then it returns the
* first tag in the list to add to the stack.
*
* @param array tag that is on the outside
* @param array tag that is on the inside
* @return boolean false if not needed, tag if needed, true if out
* of our minds
* @access private
* @see _validateTagArray()
* @author Seth Price <seth@pricepages.org>
*/
public function _parentNeeded($out, $in)
{
if (!isset($this->_definedTags[$in]['parent']) ||
($this->_definedTags[$in]['parent'] == 'all')
) {
return false;
}
$ar = explode('^', $this->_definedTags[$in]['parent']);
$tags = explode(',', $ar[1]);
if ($ar[0] == 'none'){
if ($out && in_array($out, $tags)) {
return false;
}
//Create a tag from the first one on the list
return $this->_buildTag('['.$tags[0].']');
}
if ($ar[0] == 'all' && $out && !in_array($out, $tags)) {
return false;
}
// Tag is needed, we don't know which one. We could make something up,
// but it would be so random, I think that it would be worthless.
return true;
}
$ar = explode('^', $this->_definedTags[$in]['parent']);
$tags = explode(',', $ar[1]);
if ($ar[0] == 'none'){
if ($out && in_array($out, $tags)) {
return false;
}
//Create a tag from the first one on the list
return $this->_buildTag('['.$tags[0].']');
}
if ($ar[0] == 'all' && $out && !in_array($out, $tags)) {
return false;
}
// Tag is needed, we don't know which one. We could make something up,
// but it would be so random, I think that it would be worthless.
return true;
}
/**
* Checks to see if a child is needed
*
* Checks to see if the current $out tag has an appropriate child. If it
* does, then it returns false. If a child is needed, then it returns the
* first tag in the list to add to the stack.
*
* @param array tag that is on the outside
* @param array tag that is on the inside
* @return boolean false if not needed, tag if needed, true if out
* of our minds
* @access private
* @see _validateTagArray()
* @author Seth Price <seth@pricepages.org>
*/
public function _childNeeded($out, $in)
{
if (!isset($this->_definedTags[$out]['child']) ||
($this->_definedTags[$out]['child'] == 'all')
) {
return false;
}
/**
* Checks to see if a child is needed
*
* Checks to see if the current $out tag has an appropriate child. If it
* does, then it returns false. If a child is needed, then it returns the
* first tag in the list to add to the stack.
*
* @param array tag that is on the outside
* @param array tag that is on the inside
* @return boolean false if not needed, tag if needed, true if out
* of our minds
* @access private
* @see _validateTagArray()
* @author Seth Price <seth@pricepages.org>
*/
public function _childNeeded($out, $in)
{
if (!isset($this->_definedTags[$out]['child']) ||
($this->_definedTags[$out]['child'] == 'all')
) {
return false;
}
$ar = explode('^', $this->_definedTags[$out]['child']);
$tags = explode(',', $ar[1]);
if ($ar[0] == 'none'){
if ($in && in_array($in, $tags)) {
return false;
}
//Create a tag from the first one on the list
return $this->_buildTag('['.$tags[0].']');
}
if ($ar[0] == 'all' && $in && !in_array($in, $tags)) {
return false;
}
// Tag is needed, we don't know which one. We could make something up,
// but it would be so random, I think that it would be worthless.
return true;
}
$ar = explode('^', $this->_definedTags[$out]['child']);
$tags = explode(',', $ar[1]);
if ($ar[0] == 'none'){
if ($in && in_array($in, $tags)) {
return false;
}
//Create a tag from the first one on the list
return $this->_buildTag('['.$tags[0].']');
}
if ($ar[0] == 'all' && $in && !in_array($in, $tags)) {
return false;
}
// Tag is needed, we don't know which one. We could make something up,
// but it would be so random, I think that it would be worthless.
return true;
}
/**
* Checks to see if a tag is allowed inside another tag
*
* The allowed tags are extracted from the private _definedTags array.
*
* @param array tag that is on the outside
* @param array tag that is on the inside
* @return boolean return true if the tag is allowed, false
* otherwise
* @access private
* @see _validateTagArray()
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function _isAllowed($out, $in)
{
if (!$out || ($this->_definedTags[$out]['allowed'] == 'all')) {
return true;
}
if ($this->_definedTags[$out]['allowed'] == 'none') {
return false;
}
/**
* Checks to see if a tag is allowed inside another tag
*
* The allowed tags are extracted from the private _definedTags array.
*
* @param array tag that is on the outside
* @param array tag that is on the inside
* @return boolean return true if the tag is allowed, false
* otherwise
* @access private
* @see _validateTagArray()
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function _isAllowed($out, $in)
{
if (!$out || ($this->_definedTags[$out]['allowed'] == 'all')) {
return true;
}
if ($this->_definedTags[$out]['allowed'] == 'none') {
return false;
}
$ar = explode('^', $this->_definedTags[$out]['allowed']);
$tags = explode(',', $ar[1]);
if ($ar[0] == 'none' && in_array($in, $tags)) {
return true;
}
if ($ar[0] == 'all' && in_array($in, $tags)) {
return false;
}
return false;
}
$ar = explode('^', $this->_definedTags[$out]['allowed']);
$tags = explode(',', $ar[1]);
if ($ar[0] == 'none' && in_array($in, $tags)) {
return true;
}
if ($ar[0] == 'all' && in_array($in, $tags)) {
return false;
}
return false;
}
/**
* Builds a parsed string based on the tag array
*
* The correct html and attribute values are extracted from the private
* _definedTags array.
*
* @return none
* @access private
* @see $_tagArray
* @see $_parsed
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function _buildParsedString()
{
$this->_parsed = '';
foreach ($this->_tagArray as $tag) {
switch ($tag['type']) {
/**
* Builds a parsed string based on the tag array
*
* The correct html and attribute values are extracted from the private
* _definedTags array.
*
* @return none
* @access private
* @see $_tagArray
* @see $_parsed
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function _buildParsedString()
{
$this->_parsed = '';
foreach ($this->_tagArray as $tag) {
switch ($tag['type']) {
// just text
case 0:
$this->_parsed .= $tag['text'];
break;
// just text
case 0:
$this->_parsed .= $tag['text'];
break;
// opening tag
case 1:
$this->_parsed .= '<'.$this->_definedTags[$tag['tag']]['htmlopen'];
if ($this->_options['quotestyle'] == 'single') $q = "'";
if ($this->_options['quotestyle'] == 'double') $q = '"';
foreach ($tag['attributes'] as $a => $v) {
//prevent XSS attacks. IMHO this is not enough, though...
//@see http://pear.php.net/bugs/bug.php?id=5609
$v = preg_replace('#(script|about|applet|activex|chrome):#is', "\\1&#058;", $v);
$v = htmlspecialchars($v);
$v = str_replace('&amp;amp;', '&amp;', $v);
// opening tag
case 1:
$this->_parsed .= '<'.$this->_definedTags[$tag['tag']]['htmlopen'];
if ($this->_options['quotestyle'] == 'single') $q = "'";
if ($this->_options['quotestyle'] == 'double') $q = '"';
foreach ($tag['attributes'] as $a => $v) {
//prevent XSS attacks. IMHO this is not enough, though...
//@see http://pear.php.net/bugs/bug.php?id=5609
$v = preg_replace('#(script|about|applet|activex|chrome):#is', "\\1&#058;", $v);
$v = htmlspecialchars($v);
$v = str_replace('&amp;amp;', '&amp;', $v);
if (($this->_options['quotewhat'] == 'nothing') ||
(($this->_options['quotewhat'] == 'strings') && is_numeric($v))
) {
$this->_parsed .= ' '.sprintf($this->_definedTags[$tag['tag']]['attributes'][$a], $v, '');
} else {
$this->_parsed .= ' '.sprintf($this->_definedTags[$tag['tag']]['attributes'][$a], $v, $q);
}
}
if ($this->_definedTags[$tag['tag']]['htmlclose'] == '' && $this->_options['xmlclose']) {
$this->_parsed .= ' /';
}
$this->_parsed .= '>';
break;
if (($this->_options['quotewhat'] == 'nothing') ||
(($this->_options['quotewhat'] == 'strings') && is_numeric($v))
) {
$this->_parsed .= ' '.sprintf($this->_definedTags[$tag['tag']]['attributes'][$a], $v, '');
} else {
$this->_parsed .= ' '.sprintf($this->_definedTags[$tag['tag']]['attributes'][$a], $v, $q);
}
}
if ($this->_definedTags[$tag['tag']]['htmlclose'] == '' && $this->_options['xmlclose']) {
$this->_parsed .= ' /';
}
$this->_parsed .= '>';
break;
// closing tag
case 2:
if ($this->_definedTags[$tag['tag']]['htmlclose'] != '') {
$this->_parsed .= '</'.$this->_definedTags[$tag['tag']]['htmlclose'].'>';
}
break;
}
}
}
// closing tag
case 2:
if ($this->_definedTags[$tag['tag']]['htmlclose'] != '') {
$this->_parsed .= '</'.$this->_definedTags[$tag['tag']]['htmlclose'].'>';
}
break;
}
}
}
/**
* Sets text in the object to be parsed
*
* @param string the text to set in the object
* @return none
* @access public
* @see getText()
* @see $_text
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function setText($str)
{
$this->_text = $str;
}
/**
* Sets text in the object to be parsed
*
* @param string the text to set in the object
* @return none
* @access public
* @see getText()
* @see $_text
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function setText($str)
{
$this->_text = $str;
}
/**
* Gets the unparsed text from the object
*
* @return string the text set in the object
* @access public
* @see setText()
* @see $_text
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function getText()
{
return $this->_text;
}
/**
* Gets the unparsed text from the object
*
* @return string the text set in the object
* @access public
* @see setText()
* @see $_text
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function getText()
{
return $this->_text;
}
/**
* Gets the preparsed text from the object
*
* @return string the text set in the object
* @access public
* @see _preparse()
* @see $_preparsed
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function getPreparsed()
{
return $this->_preparsed;
}
/**
* Gets the preparsed text from the object
*
* @return string the text set in the object
* @access public
* @see _preparse()
* @see $_preparsed
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function getPreparsed()
{
return $this->_preparsed;
}
/**
* Gets the parsed text from the object
*
* @return string the parsed text set in the object
* @access public
* @see parse()
* @see $_parsed
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function getParsed()
{
return $this->_parsed;
}
/**
* Gets the parsed text from the object
*
* @return string the parsed text set in the object
* @access public
* @see parse()
* @see $_parsed
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function getParsed()
{
return $this->_parsed;
}
/**
* Parses the text set in the object
*
* @return none
* @access public
* @see _preparse()
* @see _buildTagArray()
* @see _validateTagArray()
* @see _buildParsedString()
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function parse()
{
$this->_preparse();
$this->_buildTagArray();
$this->_validateTagArray();
$this->_buildParsedString();
}
/**
* Parses the text set in the object
*
* @return none
* @access public
* @see _preparse()
* @see _buildTagArray()
* @see _validateTagArray()
* @see _buildParsedString()
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function parse()
{
$this->_preparse();
$this->_buildTagArray();
$this->_validateTagArray();
$this->_buildParsedString();
}
/**
* Quick method to do setText(), parse() and getParsed at once
*
* @return none
* @access public
* @see parse()
* @see $_text
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function qparse($str)
{
$this->_text = $str;
$this->parse();
return $this->_parsed;
}
/**
* Quick method to do setText(), parse() and getParsed at once
*
* @return none
* @access public
* @see parse()
* @see $_text
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function qparse($str)
{
$this->_text = $str;
$this->parse();
return $this->_parsed;
}
/**
* Quick static method to do setText(), parse() and getParsed at once
*
* @return none
* @access public
* @see parse()
* @see $_text
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function staticQparse($str)
{
$p = new SSHTMLBBCodeParser();
$str = $p->qparse($str);
unset($p);
return $str;
}
/**
* Quick static method to do setText(), parse() and getParsed at once
*
* @return none
* @access public
* @see parse()
* @see $_text
* @author Stijn de Reede <sjr@gmx.co.uk>
*/
public function staticQparse($str)
{
$p = new SSHTMLBBCodeParser();
$str = $p->qparse($str);
unset($p);
return $str;
}
}

View File

@ -147,7 +147,7 @@ class SearchContext extends Object {
$searchParamArray = $searchParams;
}
foreach($searchParamArray as $key => $value) {
foreach($searchParamArray as $key => $value) {
$key = str_replace('__', '.', $key);
if($filter = $this->getFilter($key)) {
$filter->setModel($this->modelClass);
@ -158,9 +158,9 @@ class SearchContext extends Object {
}
}
if($this->connective != "AND") {
throw new Exception("SearchContext connective '$this->connective' not supported after ORM-rewrite.");
}
if($this->connective != "AND") {
throw new Exception("SearchContext connective '$this->connective' not supported after ORM-rewrite.");
}
return $query;
}

View File

@ -11,95 +11,95 @@
*/
abstract class Authenticator extends Object {
/**
* This variable holds all authenticators that should be used
*
* @var array
*/
private static $authenticators = array('MemberAuthenticator');
/**
* Used to influence the order of authenticators on the login-screen
* (default shows first).
*
* @var string
*/
private static $default_authenticator = 'MemberAuthenticator';
/**
* This variable holds all authenticators that should be used
*
* @var array
*/
private static $authenticators = array('MemberAuthenticator');
/**
* Used to influence the order of authenticators on the login-screen
* (default shows first).
*
* @var string
*/
private static $default_authenticator = 'MemberAuthenticator';
/**
* Method to authenticate an user
*
* @param array $RAW_data Raw data to authenticate the user
* @param Form $form Optional: If passed, better error messages can be
* produced by using
* {@link Form::sessionMessage()}
* @return bool|Member Returns FALSE if authentication fails, otherwise
* the member object
*/
/**
* Method to authenticate an user
*
* @param array $RAW_data Raw data to authenticate the user
* @param Form $form Optional: If passed, better error messages can be
* produced by using
* {@link Form::sessionMessage()}
* @return bool|Member Returns FALSE if authentication fails, otherwise
* the member object
*/
public static function authenticate($RAW_data, Form $form = null) {
}
/**
* Method that creates the login form for this authentication method
*
* @param Controller The parent controller, necessary to create the
* appropriate form action tag
* @return Form Returns the login form to use with this authentication
* method
*/
/**
* Method that creates the login form for this authentication method
*
* @param Controller The parent controller, necessary to create the
* appropriate form action tag
* @return Form Returns the login form to use with this authentication
* method
*/
public static function get_login_form(Controller $controller) {
}
/**
* Get the name of the authentication method
*
* @return string Returns the name of the authentication method.
*/
/**
* Get the name of the authentication method
*
* @return string Returns the name of the authentication method.
*/
public static function get_name() {
}
public static function register($authenticator) {
public static function register($authenticator) {
self::register_authenticator($authenticator);
}
}
/**
* Register a new authenticator
*
* The new authenticator has to exist and to be derived from the
* {@link Authenticator}.
* Every authenticator can be registered only once.
*
* @param string $authenticator Name of the authenticator class to
* register
* @return bool Returns TRUE on success, FALSE otherwise.
*/
public static function register_authenticator($authenticator) {
$authenticator = trim($authenticator);
/**
* Register a new authenticator
*
* The new authenticator has to exist and to be derived from the
* {@link Authenticator}.
* Every authenticator can be registered only once.
*
* @param string $authenticator Name of the authenticator class to
* register
* @return bool Returns TRUE on success, FALSE otherwise.
*/
public static function register_authenticator($authenticator) {
$authenticator = trim($authenticator);
if(class_exists($authenticator) == false)
return false;
if(class_exists($authenticator) == false)
return false;
if(is_subclass_of($authenticator, 'Authenticator') == false)
return false;
if(is_subclass_of($authenticator, 'Authenticator') == false)
return false;
if(in_array($authenticator, self::$authenticators) == false) {
if(call_user_func(array($authenticator, 'on_register')) === true) {
array_push(self::$authenticators, $authenticator);
} else {
return false;
}
}
if(in_array($authenticator, self::$authenticators) == false) {
if(call_user_func(array($authenticator, 'on_register')) === true) {
array_push(self::$authenticators, $authenticator);
} else {
return false;
}
}
return true;
}
public static function unregister($authenticator) {
self::unregister_authenticator($authenticator);
}
return true;
}
public static function unregister($authenticator) {
self::unregister_authenticator($authenticator);
}
/**
* Remove a previously registered authenticator
*
@ -108,82 +108,82 @@ abstract class Authenticator extends Object {
*/
public static function unregister_authenticator($authenticator) {
if(call_user_func(array($authenticator, 'on_unregister')) === true) {
if(in_array($authenticator, self::$authenticators)) {
unset(self::$authenticators[array_search($authenticator, self::$authenticators)]);
}
if(in_array($authenticator, self::$authenticators)) {
unset(self::$authenticators[array_search($authenticator, self::$authenticators)]);
}
};
}
/**
* Check if a given authenticator is registered
*
* @param string $authenticator Name of the authenticator class to check
* @return bool Returns TRUE if the authenticator is registered, FALSE
* otherwise.
*/
public static function is_registered($authenticator) {
return in_array($authenticator, self::$authenticators);
}
/**
* Check if a given authenticator is registered
*
* @param string $authenticator Name of the authenticator class to check
* @return bool Returns TRUE if the authenticator is registered, FALSE
* otherwise.
*/
public static function is_registered($authenticator) {
return in_array($authenticator, self::$authenticators);
}
/**
* Get all registered authenticators
*
* @return array Returns an array with the class names of all registered
* authenticators.
*/
public static function get_authenticators() {
// put default authenticator first (mainly for tab-order on loginform)
if($key = array_search(self::$default_authenticator,self::$authenticators)) {
unset(self::$authenticators[$key]);
array_unshift(self::$authenticators, self::$default_authenticator);
}
/**
* Get all registered authenticators
*
* @return array Returns an array with the class names of all registered
* authenticators.
*/
public static function get_authenticators() {
// put default authenticator first (mainly for tab-order on loginform)
if($key = array_search(self::$default_authenticator,self::$authenticators)) {
unset(self::$authenticators[$key]);
array_unshift(self::$authenticators, self::$default_authenticator);
}
return self::$authenticators;
}
/**
* Set a default authenticator (shows first in tabs)
*
* @param string
*/
public static function set_default_authenticator($authenticator) {
self::$default_authenticator = $authenticator;
}
/**
* @return string
*/
public static function get_default_authenticator() {
return self::$default_authenticator;
}
return self::$authenticators;
}
/**
* Set a default authenticator (shows first in tabs)
*
* @param string
*/
public static function set_default_authenticator($authenticator) {
self::$default_authenticator = $authenticator;
}
/**
* @return string
*/
public static function get_default_authenticator() {
return self::$default_authenticator;
}
/**
* Callback function that is called when the authenticator is registered
*
* Use this method for initialization of a newly registered authenticator.
* Just overload this method and it will be called when the authenticator
* is registered.
* <b>If the method returns FALSE, the authenticator won't be
* registered!</b>
*
* @return bool Returns TRUE on success, FALSE otherwise.
*/
protected static function on_register() {
return true;
}
/**
* Callback function that is called when an authenticator is removed.
*
* @return bool
*/
protected static function on_unregister() {
return true;
}
/**
* Callback function that is called when the authenticator is registered
*
* Use this method for initialization of a newly registered authenticator.
* Just overload this method and it will be called when the authenticator
* is registered.
* <b>If the method returns FALSE, the authenticator won't be
* registered!</b>
*
* @return bool Returns TRUE on success, FALSE otherwise.
*/
protected static function on_register() {
return true;
}
/**
* Callback function that is called when an authenticator is removed.
*
* @return bool
*/
protected static function on_unregister() {
return true;
}
}

View File

@ -154,7 +154,7 @@ class Group extends DataObject {
// but tabstrip.js doesn't display tabs when directly adressed through a URL pragma
_t('Group.RolesAddEditLink', 'Manage roles')
) .
"</p>"
"</p>"
)
);
@ -315,7 +315,7 @@ class Group extends DataObject {
}
public function getTreeTitle() {
if($this->hasMethod('alternateTreeTitle')) return $this->alternateTreeTitle();
if($this->hasMethod('alternateTreeTitle')) return $this->alternateTreeTitle();
else return htmlspecialchars($this->Title, ENT_QUOTES);
}
@ -367,7 +367,7 @@ class Group extends DataObject {
$results = $this->extend('canEdit', $member);
if($results && is_array($results)) if(!min($results)) return false;
if(
if(
// either we have an ADMIN
(bool)Permission::checkMember($member, "ADMIN")
|| (

View File

@ -561,7 +561,7 @@ class Member extends DataObject implements TemplateGlobalProvider {
* It should return fields that are editable by the admin and the logged-in user.
*
* @return FieldList Returns a {@link FieldList} containing the fields for
* the member form.
* the member form.
*/
public function getMemberFormFields() {
$fields = parent::getFrontendFields();
@ -658,10 +658,10 @@ class Member extends DataObject implements TemplateGlobalProvider {
return $word . $number;
} else {
$random = rand();
$string = md5($random);
$output = substr($string, 0, 6);
return $output;
$random = rand();
$string = md5($random);
$output = substr($string, 0, 6);
return $output;
}
}
@ -1149,7 +1149,7 @@ class Member extends DataObject implements TemplateGlobalProvider {
*
* @param array $groupList An array of group code names.
* @param array $memberGroups A component set of groups (if set to NULL,
* $this->groups() will be used)
* $this->groups() will be used)
* @return array Groups in which the member is NOT in.
*/
public function memberNotInGroups($groupList, $memberGroups = null){
@ -1171,7 +1171,7 @@ class Member extends DataObject implements TemplateGlobalProvider {
* this member.
*
* @return FieldList Return a FieldList of fields that would appropriate for
* editing this member.
* editing this member.
*/
public function getCMSFields() {
require_once('Zend/Date.php');
@ -1535,14 +1535,14 @@ class Member_GroupSet extends ManyManyList {
* @subpackage security
*/
class Member_ChangePasswordEmail extends Email {
protected $from = ''; // setting a blank from address uses the site's default administrator email
protected $subject = '';
protected $ss_template = 'ChangePasswordEmail';
public function __construct() {
protected $from = ''; // setting a blank from address uses the site's default administrator email
protected $subject = '';
protected $ss_template = 'ChangePasswordEmail';
public function __construct() {
parent::__construct();
$this->subject = _t('Member.SUBJECTPASSWORDCHANGED', "Your password has been changed", 'Email subject');
}
$this->subject = _t('Member.SUBJECTPASSWORDCHANGED', "Your password has been changed", 'Email subject');
}
}
@ -1553,14 +1553,14 @@ class Member_ChangePasswordEmail extends Email {
* @subpackage security
*/
class Member_ForgotPasswordEmail extends Email {
protected $from = ''; // setting a blank from address uses the site's default administrator email
protected $subject = '';
protected $ss_template = 'ForgotPasswordEmail';
public function __construct() {
protected $from = ''; // setting a blank from address uses the site's default administrator email
protected $subject = '';
protected $ss_template = 'ForgotPasswordEmail';
public function __construct() {
parent::__construct();
$this->subject = _t('Member.SUBJECTPASSWORDRESET', "Your password reset link", 'Email subject');
}
$this->subject = _t('Member.SUBJECTPASSWORDRESET', "Your password reset link", 'Email subject');
}
}
/**

View File

@ -18,103 +18,103 @@ class MemberAuthenticator extends Authenticator {
'sha1' => 'sha1_v2.4'
);
/**
* Method to authenticate an user
*
* @param array $RAW_data Raw data to authenticate the user
* @param Form $form Optional: If passed, better error messages can be
* produced by using
* {@link Form::sessionMessage()}
* @return bool|Member Returns FALSE if authentication fails, otherwise
* the member object
* @see Security::setDefaultAdmin()
*/
public static function authenticate($RAW_data, Form $form = null) {
if(array_key_exists('Email', $RAW_data) && $RAW_data['Email']){
$SQL_user = Convert::raw2sql($RAW_data['Email']);
} else {
return false;
}
$isLockedOut = false;
$result = null;
// Default login (see Security::setDefaultAdmin())
if(Security::check_default_admin($RAW_data['Email'], $RAW_data['Password'])) {
$member = Security::findAnAdministrator();
} else {
$member = DataObject::get_one(
"Member",
"\"" . Member::get_unique_identifier_field() . "\" = '$SQL_user' AND \"Password\" IS NOT NULL"
);
if($member) {
$result = $member->checkPassword($RAW_data['Password']);
} else {
$result = new ValidationResult(false, _t('Member.ERRORWRONGCRED'));
}
if($member && !$result->valid()) {
$member->registerFailedLogin();
$member = false;
}
}
// Optionally record every login attempt as a {@link LoginAttempt} object
/**
* TODO We could handle this with an extension
* Method to authenticate an user
*
* @param array $RAW_data Raw data to authenticate the user
* @param Form $form Optional: If passed, better error messages can be
* produced by using
* {@link Form::sessionMessage()}
* @return bool|Member Returns FALSE if authentication fails, otherwise
* the member object
* @see Security::setDefaultAdmin()
*/
if(Security::login_recording()) {
$attempt = new LoginAttempt();
if($member) {
// successful login (member is existing with matching password)
$attempt->MemberID = $member->ID;
$attempt->Status = 'Success';
// Audit logging hook
$member->extend('authenticated');
public static function authenticate($RAW_data, Form $form = null) {
if(array_key_exists('Email', $RAW_data) && $RAW_data['Email']){
$SQL_user = Convert::raw2sql($RAW_data['Email']);
} else {
// failed login - we're trying to see if a user exists with this email (disregarding wrong passwords)
$existingMember = DataObject::get_one(
"Member",
"\"" . Member::get_unique_identifier_field() . "\" = '$SQL_user'"
);
if($existingMember) {
$attempt->MemberID = $existingMember->ID;
// Audit logging hook
$existingMember->extend('authenticationFailed');
} else {
// Audit logging hook
singleton('Member')->extend('authenticationFailedUnknownUser', $RAW_data);
}
$attempt->Status = 'Failure';
}
if(is_array($RAW_data['Email'])) {
user_error("Bad email passed to MemberAuthenticator::authenticate(): $RAW_data[Email]", E_USER_WARNING);
return false;
}
$isLockedOut = false;
$result = null;
// Default login (see Security::setDefaultAdmin())
if(Security::check_default_admin($RAW_data['Email'], $RAW_data['Password'])) {
$member = Security::findAnAdministrator();
} else {
$member = DataObject::get_one(
"Member",
"\"" . Member::get_unique_identifier_field() . "\" = '$SQL_user' AND \"Password\" IS NOT NULL"
);
if($member) {
$result = $member->checkPassword($RAW_data['Password']);
} else {
$result = new ValidationResult(false, _t('Member.ERRORWRONGCRED'));
}
if($member && !$result->valid()) {
$member->registerFailedLogin();
$member = false;
}
}
$attempt->Email = $RAW_data['Email'];
$attempt->IP = Controller::curr()->getRequest()->getIP();
$attempt->write();
}
// Legacy migration to precision-safe password hashes.
// A login-event with cleartext passwords is the only time
// when we can rehash passwords to a different hashing algorithm,
// bulk-migration doesn't work due to the nature of hashing.
// See PasswordEncryptor_LegacyPHPHash class.
if(
$member // only migrate after successful login
&& self::$migrate_legacy_hashes
&& array_key_exists($member->PasswordEncryption, self::$migrate_legacy_hashes)
) {
$member->Password = $RAW_data['Password'];
$member->PasswordEncryption = self::$migrate_legacy_hashes[$member->PasswordEncryption];
$member->write();
}
// Optionally record every login attempt as a {@link LoginAttempt} object
/**
* TODO We could handle this with an extension
*/
if(Security::login_recording()) {
$attempt = new LoginAttempt();
if($member) {
// successful login (member is existing with matching password)
$attempt->MemberID = $member->ID;
$attempt->Status = 'Success';
// Audit logging hook
$member->extend('authenticated');
} else {
// failed login - we're trying to see if a user exists with this email (disregarding wrong passwords)
$existingMember = DataObject::get_one(
"Member",
"\"" . Member::get_unique_identifier_field() . "\" = '$SQL_user'"
);
if($existingMember) {
$attempt->MemberID = $existingMember->ID;
// Audit logging hook
$existingMember->extend('authenticationFailed');
} else {
// Audit logging hook
singleton('Member')->extend('authenticationFailedUnknownUser', $RAW_data);
}
$attempt->Status = 'Failure';
}
if(is_array($RAW_data['Email'])) {
user_error("Bad email passed to MemberAuthenticator::authenticate(): $RAW_data[Email]", E_USER_WARNING);
return false;
}
$attempt->Email = $RAW_data['Email'];
$attempt->IP = Controller::curr()->getRequest()->getIP();
$attempt->write();
}
// Legacy migration to precision-safe password hashes.
// A login-event with cleartext passwords is the only time
// when we can rehash passwords to a different hashing algorithm,
// bulk-migration doesn't work due to the nature of hashing.
// See PasswordEncryptor_LegacyPHPHash class.
if(
$member // only migrate after successful login
&& self::$migrate_legacy_hashes
&& array_key_exists($member->PasswordEncryption, self::$migrate_legacy_hashes)
) {
$member->Password = $RAW_data['Password'];
$member->PasswordEncryption = self::$migrate_legacy_hashes[$member->PasswordEncryption];
$member->write();
}
if($member) {
Session::clear('BackURL');
@ -126,25 +126,25 @@ class MemberAuthenticator extends Authenticator {
}
/**
* Method that creates the login form for this authentication method
*
* @param Controller The parent controller, necessary to create the
* appropriate form action tag
* @return Form Returns the login form to use with this authentication
* method
*/
public static function get_login_form(Controller $controller) {
return Object::create("MemberLoginForm", $controller, "LoginForm");
}
/**
* Method that creates the login form for this authentication method
*
* @param Controller The parent controller, necessary to create the
* appropriate form action tag
* @return Form Returns the login form to use with this authentication
* method
*/
public static function get_login_form(Controller $controller) {
return Object::create("MemberLoginForm", $controller, "LoginForm");
}
/**
* Get the name of the authentication method
*
* @return string Returns the name of the authentication method.
*/
public static function get_name() {
/**
* Get the name of the authentication method
*
* @return string Returns the name of the authentication method.
*/
public static function get_name() {
return _t('MemberAuthenticator.TITLE', "E-mail &amp; Password");
}
}

View File

@ -33,7 +33,7 @@ class MemberLoginForm extends LoginForm {
* @param string $authenticatorClassName Name of the authenticator class that this form uses.
*/
public function __construct($controller, $name, $fields = null, $actions = null,
$checkCurrentUser = true) {
$checkCurrentUser = true) {
// This is now set on the class directly to make it easier to create subclasses
// $this->authenticator_class = $authenticatorClassName;
@ -226,13 +226,13 @@ JS
}
/**
* Try to authenticate the user
*
* @param array Submitted data
* @return Member Returns the member object on successful authentication
* or NULL on failure.
*/
/**
* Try to authenticate the user
*
* @param array Submitted data
* @return Member Returns the member object on successful authentication
* or NULL on failure.
*/
public function performLogin($data) {
$member = call_user_func_array(array($this->authenticator_class, 'authenticate'), array($data, $this));
if($member) {

View File

@ -6,7 +6,7 @@
*/
class Permission extends DataObject implements TemplateGlobalProvider {
// the (1) after Type specifies the DB default value which is needed for
// the (1) after Type specifies the DB default value which is needed for
// upgrades from older SilverStripe versions
static $db = array(
"Code" => "Varchar",
@ -55,7 +55,7 @@ class Permission extends DataObject implements TemplateGlobalProvider {
*/
static $declared_permissions = null;
/**
/**
* Linear list of declared permissions in the system.
*
* @var array

View File

@ -157,7 +157,7 @@ class PermissionCheckboxSetField extends FormField {
}
}
}
$odd = 0;
$options = '';
if($this->source) {
@ -256,7 +256,7 @@ class PermissionCheckboxSetField extends FormField {
$idList = array();
if($this->value) foreach($this->value as $id => $bool) {
if($bool) {
if($bool) {
$perm = new $managedClass();
$perm->{$this->filterField} = $record->ID;
$perm->Code = $id;

View File

@ -7,18 +7,18 @@
class Security extends Controller {
static $allowed_actions = array(
'index',
'login',
'logout',
'basicauthlogin',
'lostpassword',
'passwordsent',
'changepassword',
'index',
'login',
'logout',
'basicauthlogin',
'lostpassword',
'passwordsent',
'changepassword',
'ping',
'LoginForm',
'ChangePasswordForm',
'LostPasswordForm',
);
);
/**
* Default user name. Only used in dev-mode by {@link setDefaultAdmin()}
@ -138,22 +138,22 @@ class Security extends Controller {
* If you don't provide a messageSet, a default will be used.
*
* @param Controller $controller The controller that you were on to cause the permission
* failure.
* failure.
* @param string|array $messageSet The message to show to the user. This
* can be a string, or a map of different
* messages for different contexts.
* If you pass an array, you can use the
* following keys:
* - default: The default message
* - logInAgain: The message to show
* if the user has just
* logged out and the
* - alreadyLoggedIn: The message to
* show if the user
* is already logged
* in and lacks the
* permission to
* access the item.
* can be a string, or a map of different
* messages for different contexts.
* If you pass an array, you can use the
* following keys:
* - default: The default message
* - logInAgain: The message to show
* if the user has just
* logged out and the
* - alreadyLoggedIn: The message to
* show if the user
* is already logged
* in and lacks the
* permission to
* access the item.
*
* The alreadyLoggedIn value can contain a '%s' placeholder that will be replaced with a link
* to log in.
@ -240,7 +240,7 @@ class Security extends Controller {
}
/**
/**
* Get the login form to process according to the submitted data
*/
protected function LoginForm() {
@ -262,7 +262,7 @@ class Security extends Controller {
}
/**
/**
* Get the login forms for all available authentication methods
*
* @return array Returns an array of available login forms (array of Form
@ -276,8 +276,8 @@ class Security extends Controller {
$authenticators = Authenticator::get_authenticators();
foreach($authenticators as $authenticator) {
array_push($forms,
call_user_func(array($authenticator, 'get_login_form'),
array_push($forms,
call_user_func(array($authenticator, 'get_login_form'),
$this));
}
@ -307,9 +307,9 @@ class Security extends Controller {
* Log the currently logged in user out
*
* @param bool $redirect Redirect the user back to where they came.
* - If it's false, the code calling logout() is
* responsible for sending the user where-ever
* they should go.
* - If it's false, the code calling logout() is
* responsible for sending the user where-ever
* they should go.
*/
public function logout($redirect = true) {
$member = Member::currentUser();
@ -675,7 +675,7 @@ class Security extends Controller {
}
if ($adminGroup) {
$member = $adminGroup->Members()->First();
$member = $adminGroup->Members()->First();
}
if(!$adminGroup) {

View File

@ -37,7 +37,7 @@ class RestfulServiceTest extends SapphireTest {
$service->setQueryString($params);
$responseBody = $service->request($url)->getBody();
foreach ($params as $key => $value) {
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $responseBody);
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $responseBody);
$this->assertContains("<get_item name=\"$key\">$value</get_item>", $responseBody);
}
}
@ -52,7 +52,7 @@ class RestfulServiceTest extends SapphireTest {
$service->setQueryString($params);
$responseBody = $service->request($url)->getBody();
foreach ($params as $key => $value) {
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $responseBody);
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $responseBody);
$this->assertContains("<get_item name=\"$key\">$value</get_item>", $responseBody);
}
}
@ -67,7 +67,7 @@ class RestfulServiceTest extends SapphireTest {
$url .= '?' . http_build_query($params);
$responseBody = $service->request($url)->getBody();
foreach ($params as $key => $value) {
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $responseBody);
$this->assertContains("<request_item name=\"$key\">$value</request_item>", $responseBody);
$this->assertContains("<get_item name=\"$key\">$value</get_item>", $responseBody);
}
}

View File

@ -3,10 +3,10 @@
namespace SilverStripe\Framework\Test\Behaviour;
use SilverStripe\BehatExtension\Context\SilverStripeContext,
SilverStripe\BehatExtension\Context\BasicContext,
SilverStripe\BehatExtension\Context\LoginContext,
SilverStripe\Framework\Test\Behaviour\CmsFormsContext,
SilverStripe\Framework\Test\Behaviour\CmsUiContext;
SilverStripe\BehatExtension\Context\BasicContext,
SilverStripe\BehatExtension\Context\LoginContext,
SilverStripe\Framework\Test\Behaviour\CmsFormsContext,
SilverStripe\Framework\Test\Behaviour\CmsUiContext;
// PHPUnit
require_once 'PHPUnit/Autoload.php';
@ -20,19 +20,19 @@ require_once 'PHPUnit/Framework/Assert/Functions.php';
*/
class FeatureContext extends SilverStripeContext
{
/**
* Initializes context.
* Every scenario gets it's own context object.
*
* @param array $parameters context parameters (set them up through behat.yml)
*/
public function __construct(array $parameters)
{
$this->useContext('BasicContext', new BasicContext($parameters));
$this->useContext('LoginContext', new LoginContext($parameters));
$this->useContext('CmsFormsContext', new CmsFormsContext($parameters));
$this->useContext('CmsUiContext', new CmsUiContext($parameters));
/**
* Initializes context.
* Every scenario gets it's own context object.
*
* @param array $parameters context parameters (set them up through behat.yml)
*/
public function __construct(array $parameters)
{
$this->useContext('BasicContext', new BasicContext($parameters));
$this->useContext('LoginContext', new LoginContext($parameters));
$this->useContext('CmsFormsContext', new CmsFormsContext($parameters));
$this->useContext('CmsUiContext', new CmsUiContext($parameters));
parent::__construct($parameters);
}
parent::__construct($parameters);
}
}

View File

@ -3,12 +3,12 @@
namespace SilverStripe\Framework\Test\Behaviour;
use Behat\Behat\Context\ClosuredContextInterface,
Behat\Behat\Context\TranslatedContextInterface,
Behat\Behat\Context\BehatContext,
Behat\Behat\Context\Step,
Behat\Behat\Exception\PendingException;
Behat\Behat\Context\TranslatedContextInterface,
Behat\Behat\Context\BehatContext,
Behat\Behat\Context\Step,
Behat\Behat\Exception\PendingException;
use Behat\Gherkin\Node\PyStringNode,
Behat\Gherkin\Node\TableNode;
Behat\Gherkin\Node\TableNode;
// PHPUnit
require_once 'PHPUnit/Autoload.php';
@ -21,81 +21,81 @@ require_once 'PHPUnit/Framework/Assert/Functions.php';
*/
class CmsFormsContext extends BehatContext
{
protected $context;
protected $context;
/**
* Initializes context.
* Every scenario gets it's own context object.
*
* @param array $parameters context parameters (set them up through behat.yml)
*/
public function __construct(array $parameters)
{
// Initialize your context here
$this->context = $parameters;
}
/**
* Initializes context.
* Every scenario gets it's own context object.
*
* @param array $parameters context parameters (set them up through behat.yml)
*/
public function __construct(array $parameters)
{
// Initialize your context here
$this->context = $parameters;
}
/**
* Get Mink session from MinkContext
*/
public function getSession($name = null)
{
return $this->getMainContext()->getSession($name);
}
/**
* Get Mink session from MinkContext
*/
public function getSession($name = null)
{
return $this->getMainContext()->getSession($name);
}
/**
* @Then /^I should see an edit page form$/
*/
public function stepIShouldSeeAnEditPageForm()
{
$page = $this->getSession()->getPage();
/**
* @Then /^I should see an edit page form$/
*/
public function stepIShouldSeeAnEditPageForm()
{
$page = $this->getSession()->getPage();
$form = $page->find('css', '#Form_EditForm');
assertNotNull($form, 'I should see an edit page form');
}
$form = $page->find('css', '#Form_EditForm');
assertNotNull($form, 'I should see an edit page form');
}
/**
* @When /^I fill in the "(?P<field>([^"]*))" HTML field with "(?P<value>([^"]*))"$/
* @When /^I fill in "(?P<value>([^"]*))" for the "(?P<field>([^"]*))" HTML field$/
*/
public function stepIFillInTheHtmlFieldWith($field, $value)
{
$page = $this->getSession()->getPage();
$inputField = $page->findField($field);
assertNotNull($inputField, sprintf('HTML field "%s" not found', $field));
/**
* @When /^I fill in the "(?P<field>([^"]*))" HTML field with "(?P<value>([^"]*))"$/
* @When /^I fill in "(?P<value>([^"]*))" for the "(?P<field>([^"]*))" HTML field$/
*/
public function stepIFillInTheHtmlFieldWith($field, $value)
{
$page = $this->getSession()->getPage();
$inputField = $page->findField($field);
assertNotNull($inputField, sprintf('HTML field "%s" not found', $field));
$this->getSession()->evaluateScript(sprintf(
"jQuery('#%s').entwine('ss').getEditor().setContent('%s')",
$inputField->getAttribute('id'),
addcslashes($value, "'")
));
}
$this->getSession()->evaluateScript(sprintf(
"jQuery('#%s').entwine('ss').getEditor().setContent('%s')",
$inputField->getAttribute('id'),
addcslashes($value, "'")
));
}
/**
* @When /^I append "(?P<value>([^"]*))" to the "(?P<field>([^"]*))" HTML field$/
*/
public function stepIAppendTotheHtmlField($field, $value)
{
$page = $this->getSession()->getPage();
$inputField = $page->findField($field);
assertNotNull($inputField, sprintf('HTML field "%s" not found', $field));
/**
* @When /^I append "(?P<value>([^"]*))" to the "(?P<field>([^"]*))" HTML field$/
*/
public function stepIAppendTotheHtmlField($field, $value)
{
$page = $this->getSession()->getPage();
$inputField = $page->findField($field);
assertNotNull($inputField, sprintf('HTML field "%s" not found', $field));
$this->getSession()->evaluateScript(sprintf(
"jQuery('#%s').entwine('ss').getEditor().insertContent('%s')",
$inputField->getAttribute('id'),
addcslashes($value, "'")
));
}
$this->getSession()->evaluateScript(sprintf(
"jQuery('#%s').entwine('ss').getEditor().insertContent('%s')",
$inputField->getAttribute('id'),
addcslashes($value, "'")
));
}
/**
* @Then /^the "(?P<field>([^"]*))" HTML field should contain "(?P<value>([^"]*))"$/
*/
public function theHtmlFieldShouldContain($field, $value)
{
$page = $this->getSession()->getPage();
$inputField = $page->findField($field);
assertNotNull($inputField, sprintf('HTML field "%s" not found', $field));
/**
* @Then /^the "(?P<field>([^"]*))" HTML field should contain "(?P<value>([^"]*))"$/
*/
public function theHtmlFieldShouldContain($field, $value)
{
$page = $this->getSession()->getPage();
$inputField = $page->findField($field);
assertNotNull($inputField, sprintf('HTML field "%s" not found', $field));
$this->getMainContext()->assertElementContains('#' . $inputField->getAttribute('id'), $value);
}
$this->getMainContext()->assertElementContains('#' . $inputField->getAttribute('id'), $value);
}
}

View File

@ -3,13 +3,13 @@
namespace SilverStripe\Framework\Test\Behaviour;
use Behat\Behat\Context\ClosuredContextInterface,
Behat\Behat\Context\TranslatedContextInterface,
Behat\Behat\Context\BehatContext,
Behat\Behat\Context\Step,
Behat\Behat\Exception\PendingException,
Behat\Mink\Exception\ElementNotFoundException;
Behat\Behat\Context\TranslatedContextInterface,
Behat\Behat\Context\BehatContext,
Behat\Behat\Context\Step,
Behat\Behat\Exception\PendingException,
Behat\Mink\Exception\ElementNotFoundException;
use Behat\Gherkin\Node\PyStringNode,
Behat\Gherkin\Node\TableNode;
Behat\Gherkin\Node\TableNode;
// PHPUnit
@ -23,376 +23,376 @@ require_once 'PHPUnit/Framework/Assert/Functions.php';
*/
class CmsUiContext extends BehatContext
{
protected $context;
protected $context;
/**
* Initializes context.
* Every scenario gets it's own context object.
*
* @param array $parameters context parameters (set them up through behat.yml)
*/
public function __construct(array $parameters)
{
// Initialize your context here
$this->context = $parameters;
}
/**
* Initializes context.
* Every scenario gets it's own context object.
*
* @param array $parameters context parameters (set them up through behat.yml)
*/
public function __construct(array $parameters)
{
// Initialize your context here
$this->context = $parameters;
}
/**
* Get Mink session from MinkContext
*/
public function getSession($name = null)
{
return $this->getMainContext()->getSession($name);
}
/**
* Get Mink session from MinkContext
*/
public function getSession($name = null)
{
return $this->getMainContext()->getSession($name);
}
/**
* @Then /^I should see the CMS$/
*/
public function iShouldSeeTheCms()
{
$page = $this->getSession()->getPage();
$cms_element = $page->find('css', '.cms');
assertNotNull($cms_element, 'CMS not found');
}
/**
* @Then /^I should see the CMS$/
*/
public function iShouldSeeTheCms()
{
$page = $this->getSession()->getPage();
$cms_element = $page->find('css', '.cms');
assertNotNull($cms_element, 'CMS not found');
}
/**
* @Then /^I should see a "([^"]*)" notice$/
*/
public function iShouldSeeANotice($notice)
{
$this->getMainContext()->assertElementContains('.notice-wrap', $notice);
}
/**
* @Then /^I should see a "([^"]*)" notice$/
*/
public function iShouldSeeANotice($notice)
{
$this->getMainContext()->assertElementContains('.notice-wrap', $notice);
}
/**
* @Then /^I should see a "([^"]*)" message$/
*/
public function iShouldSeeAMessage($message)
{
$this->getMainContext()->assertElementContains('.message', $message);
}
/**
* @Then /^I should see a "([^"]*)" message$/
*/
public function iShouldSeeAMessage($message)
{
$this->getMainContext()->assertElementContains('.message', $message);
}
protected function getCmsTabsElement()
{
$this->getSession()->wait(5000, "window.jQuery('.cms-content-header-tabs').size() > 0");
protected function getCmsTabsElement()
{
$this->getSession()->wait(5000, "window.jQuery('.cms-content-header-tabs').size() > 0");
$page = $this->getSession()->getPage();
$cms_content_header_tabs = $page->find('css', '.cms-content-header-tabs');
assertNotNull($cms_content_header_tabs, 'CMS tabs not found');
$page = $this->getSession()->getPage();
$cms_content_header_tabs = $page->find('css', '.cms-content-header-tabs');
assertNotNull($cms_content_header_tabs, 'CMS tabs not found');
return $cms_content_header_tabs;
}
return $cms_content_header_tabs;
}
protected function getCmsContentToolbarElement()
{
$this->getSession()->wait(
5000,
"window.jQuery('.cms-content-toolbar').size() > 0 "
. "&& window.jQuery('.cms-content-toolbar').children().size() > 0"
);
protected function getCmsContentToolbarElement()
{
$this->getSession()->wait(
5000,
"window.jQuery('.cms-content-toolbar').size() > 0 "
. "&& window.jQuery('.cms-content-toolbar').children().size() > 0"
);
$page = $this->getSession()->getPage();
$cms_content_toolbar_element = $page->find('css', '.cms-content-toolbar');
assertNotNull($cms_content_toolbar_element, 'CMS content toolbar not found');
$page = $this->getSession()->getPage();
$cms_content_toolbar_element = $page->find('css', '.cms-content-toolbar');
assertNotNull($cms_content_toolbar_element, 'CMS content toolbar not found');
return $cms_content_toolbar_element;
}
return $cms_content_toolbar_element;
}
protected function getCmsTreeElement()
{
$this->getSession()->wait(5000, "window.jQuery('.cms-tree').size() > 0");
protected function getCmsTreeElement()
{
$this->getSession()->wait(5000, "window.jQuery('.cms-tree').size() > 0");
$page = $this->getSession()->getPage();
$cms_tree_element = $page->find('css', '.cms-tree');
assertNotNull($cms_tree_element, 'CMS tree not found');
$page = $this->getSession()->getPage();
$cms_tree_element = $page->find('css', '.cms-tree');
assertNotNull($cms_tree_element, 'CMS tree not found');
return $cms_tree_element;
}
return $cms_tree_element;
}
protected function getGridfieldTable($title)
{
$page = $this->getSession()->getPage();
$table_elements = $page->findAll('css', '.ss-gridfield-table');
assertNotNull($table_elements, 'Table elements not found');
protected function getGridfieldTable($title)
{
$page = $this->getSession()->getPage();
$table_elements = $page->findAll('css', '.ss-gridfield-table');
assertNotNull($table_elements, 'Table elements not found');
$table_element = null;
foreach ($table_elements as $table) {
$table_title_element = $table->find('css', '.title');
if ($table_title_element->getText() === $title) {
$table_element = $table;
break;
}
}
assertNotNull($table_element, sprintf('Table `%s` not found', $title));
$table_element = null;
foreach ($table_elements as $table) {
$table_title_element = $table->find('css', '.title');
if ($table_title_element->getText() === $title) {
$table_element = $table;
break;
}
}
assertNotNull($table_element, sprintf('Table `%s` not found', $title));
return $table_element;
}
return $table_element;
}
/**
* @Given /^I should see a "([^"]*)" button in CMS Content Toolbar$/
*/
public function iShouldSeeAButtonInCmsContentToolbar($text)
{
$cms_content_toolbar_element = $this->getCmsContentToolbarElement();
/**
* @Given /^I should see a "([^"]*)" button in CMS Content Toolbar$/
*/
public function iShouldSeeAButtonInCmsContentToolbar($text)
{
$cms_content_toolbar_element = $this->getCmsContentToolbarElement();
$element = $cms_content_toolbar_element->find('named', array('link_or_button', "'$text'"));
assertNotNull($element, sprintf('%s button not found', $text));
}
$element = $cms_content_toolbar_element->find('named', array('link_or_button', "'$text'"));
assertNotNull($element, sprintf('%s button not found', $text));
}
/**
* @When /^I should see "([^"]*)" in CMS Tree$/
*/
public function stepIShouldSeeInCmsTree($text)
{
$cms_tree_element = $this->getCmsTreeElement();
/**
* @When /^I should see "([^"]*)" in CMS Tree$/
*/
public function stepIShouldSeeInCmsTree($text)
{
$cms_tree_element = $this->getCmsTreeElement();
$element = $cms_tree_element->find('named', array('content', "'$text'"));
assertNotNull($element, sprintf('%s not found', $text));
}
$element = $cms_tree_element->find('named', array('content', "'$text'"));
assertNotNull($element, sprintf('%s not found', $text));
}
/**
* @When /^I should not see "([^"]*)" in CMS Tree$/
*/
public function stepIShouldNotSeeInCmsTree($text)
{
$cms_tree_element = $this->getCmsTreeElement();
/**
* @When /^I should not see "([^"]*)" in CMS Tree$/
*/
public function stepIShouldNotSeeInCmsTree($text)
{
$cms_tree_element = $this->getCmsTreeElement();
$element = $cms_tree_element->find('named', array('content', "'$text'"));
assertNull($element, sprintf('%s found', $text));
}
$element = $cms_tree_element->find('named', array('content', "'$text'"));
assertNull($element, sprintf('%s found', $text));
}
/**
* @When /^I expand the "([^"]*)" CMS Panel$/
*/
public function iExpandTheCmsPanel()
{
// TODO Make dynamic, currently hardcoded to first panel
$page = $this->getSession()->getPage();
/**
* @When /^I expand the "([^"]*)" CMS Panel$/
*/
public function iExpandTheCmsPanel()
{
// TODO Make dynamic, currently hardcoded to first panel
$page = $this->getSession()->getPage();
$panel_toggle_element = $page->find('css', '.cms-content > .cms-panel > .cms-panel-toggle > .toggle-expand');
assertNotNull($panel_toggle_element, 'Panel toggle not found');
$panel_toggle_element = $page->find('css', '.cms-content > .cms-panel > .cms-panel-toggle > .toggle-expand');
assertNotNull($panel_toggle_element, 'Panel toggle not found');
if ($panel_toggle_element->isVisible()) {
$panel_toggle_element->click();
}
}
if ($panel_toggle_element->isVisible()) {
$panel_toggle_element->click();
}
}
/**
* @When /^I click the "([^"]*)" CMS tab$/
*/
public function iClickTheCmsTab($tab)
{
$this->getSession()->wait(5000, "window.jQuery('.ui-tabs-nav').size() > 0");
/**
* @When /^I click the "([^"]*)" CMS tab$/
*/
public function iClickTheCmsTab($tab)
{
$this->getSession()->wait(5000, "window.jQuery('.ui-tabs-nav').size() > 0");
$page = $this->getSession()->getPage();
$tabsets = $page->findAll('css', '.ui-tabs-nav');
assertNotNull($tabsets, 'CMS tabs not found');
$page = $this->getSession()->getPage();
$tabsets = $page->findAll('css', '.ui-tabs-nav');
assertNotNull($tabsets, 'CMS tabs not found');
$tab_element = null;
foreach($tabsets as $tabset) {
if($tab_element) continue;
$tab_element = $tabset->find('named', array('link_or_button', "'$tab'"));
}
assertNotNull($tab_element, sprintf('%s tab not found', $tab));
$tab_element = null;
foreach($tabsets as $tabset) {
if($tab_element) continue;
$tab_element = $tabset->find('named', array('link_or_button', "'$tab'"));
}
assertNotNull($tab_element, sprintf('%s tab not found', $tab));
$tab_element->click();
}
$tab_element->click();
}
/**
* @Then /^the "([^"]*)" table should contain "([^"]*)"$/
*/
public function theTableShouldContain($table, $text)
{
$table_element = $this->getGridfieldTable($table);
/**
* @Then /^the "([^"]*)" table should contain "([^"]*)"$/
*/
public function theTableShouldContain($table, $text)
{
$table_element = $this->getGridfieldTable($table);
$element = $table_element->find('named', array('content', "'$text'"));
assertNotNull($element, sprintf('Element containing `%s` not found in `%s` table', $text, $table));
}
$element = $table_element->find('named', array('content', "'$text'"));
assertNotNull($element, sprintf('Element containing `%s` not found in `%s` table', $text, $table));
}
/**
* @Then /^the "([^"]*)" table should not contain "([^"]*)"$/
*/
public function theTableShouldNotContain($table, $text)
{
$table_element = $this->getGridfieldTable($table);
/**
* @Then /^the "([^"]*)" table should not contain "([^"]*)"$/
*/
public function theTableShouldNotContain($table, $text)
{
$table_element = $this->getGridfieldTable($table);
$element = $table_element->find('named', array('content', "'$text'"));
assertNull($element, sprintf('Element containing `%s` not found in `%s` table', $text, $table));
}
$element = $table_element->find('named', array('content', "'$text'"));
assertNull($element, sprintf('Element containing `%s` not found in `%s` table', $text, $table));
}
/**
* @Given /^I click on "([^"]*)" in the "([^"]*)" table$/
*/
public function iClickOnInTheTable($text, $table)
{
$table_element = $this->getGridfieldTable($table);
/**
* @Given /^I click on "([^"]*)" in the "([^"]*)" table$/
*/
public function iClickOnInTheTable($text, $table)
{
$table_element = $this->getGridfieldTable($table);
$element = $table_element->find('xpath', sprintf('//*[count(*)=0 and contains(.,"%s")]', $text));
assertNotNull($element, sprintf('Element containing `%s` not found', $text));
$element->click();
}
$element = $table_element->find('xpath', sprintf('//*[count(*)=0 and contains(.,"%s")]', $text));
assertNotNull($element, sprintf('Element containing `%s` not found', $text));
$element->click();
}
/**
* @Then /^I can see the preview panel$/
*/
public function iCanSeeThePreviewPanel()
{
$this->getMainContext()->assertElementOnPage('.cms-preview');
}
/**
* @Then /^I can see the preview panel$/
*/
public function iCanSeeThePreviewPanel()
{
$this->getMainContext()->assertElementOnPage('.cms-preview');
}
/**
* @Given /^the preview contains "([^"]*)"$/
*/
public function thePreviewContains($content)
{
$driver = $this->getSession()->getDriver();
$driver->switchToIFrame('cms-preview-iframe');
/**
* @Given /^the preview contains "([^"]*)"$/
*/
public function thePreviewContains($content)
{
$driver = $this->getSession()->getDriver();
$driver->switchToIFrame('cms-preview-iframe');
$this->getMainContext()->assertPageContainsText($content);
$driver->switchToWindow();
}
$this->getMainContext()->assertPageContainsText($content);
$driver->switchToWindow();
}
/**
* @Given /^I set the CMS mode to "([^"]*)"$/
*/
public function iSetTheCmsToMode($mode)
{
return array(
new Step\When(sprintf('I fill in the "Change view mode" dropdown with "%s"', $mode)),
new Step\When('I wait for 1 second') // wait for CMS layout to redraw
);
}
/**
* @Given /^I set the CMS mode to "([^"]*)"$/
*/
public function iSetTheCmsToMode($mode)
{
return array(
new Step\When(sprintf('I fill in the "Change view mode" dropdown with "%s"', $mode)),
new Step\When('I wait for 1 second') // wait for CMS layout to redraw
);
}
/**
* @Given /^I wait for the preview to load$/
*/
public function iWaitForThePreviewToLoad()
{
$driver = $this->getSession()->getDriver();
$driver->switchToIFrame('cms-preview-iframe');
$this->getSession()->wait(
5000,
"!jQuery('iframe[name=cms-preview-iframe]').hasClass('loading')"
);
/**
* @Given /^I wait for the preview to load$/
*/
public function iWaitForThePreviewToLoad()
{
$driver = $this->getSession()->getDriver();
$driver->switchToIFrame('cms-preview-iframe');
$this->getSession()->wait(
5000,
"!jQuery('iframe[name=cms-preview-iframe]').hasClass('loading')"
);
$driver->switchToWindow();
}
$driver->switchToWindow();
}
/**
* @Given /^I switch the preview to "([^"]*)"$/
*/
public function iSwitchThePreviewToMode($mode)
{
$controls = $this->getSession()->getPage()->find('css', '.cms-preview-controls');
assertNotNull($controls, 'Preview controls not found');
/**
* @Given /^I switch the preview to "([^"]*)"$/
*/
public function iSwitchThePreviewToMode($mode)
{
$controls = $this->getSession()->getPage()->find('css', '.cms-preview-controls');
assertNotNull($controls, 'Preview controls not found');
$label = $controls->find('xpath', sprintf(
'.//label[(@for="%s")]',
$mode
));
assertNotNull($label, 'Preview mode switch not found');
$label = $controls->find('xpath', sprintf(
'.//label[(@for="%s")]',
$mode
));
assertNotNull($label, 'Preview mode switch not found');
$label->click();
$label->click();
return new Step\When('I wait for the preview to load');
}
return new Step\When('I wait for the preview to load');
}
/**
* @Given /^the preview does not contain "([^"]*)"$/
*/
public function thePreviewDoesNotContain($content)
{
$driver = $this->getSession()->getDriver();
$driver->switchToIFrame('cms-preview-iframe');
/**
* @Given /^the preview does not contain "([^"]*)"$/
*/
public function thePreviewDoesNotContain($content)
{
$driver = $this->getSession()->getDriver();
$driver->switchToIFrame('cms-preview-iframe');
$this->getMainContext()->assertPageNotContainsText($content);
$driver->switchToWindow();
}
$this->getMainContext()->assertPageNotContainsText($content);
$driver->switchToWindow();
}
/**
* Workaround for chosen.js dropdowns which hide the original dropdown field.
*
* @When /^(?:|I )fill in the "(?P<field>(?:[^"]|\\")*)" dropdown with "(?P<value>(?:[^"]|\\")*)"$/
* @When /^(?:|I )fill in "(?P<value>(?:[^"]|\\")*)" for the "(?P<field>(?:[^"]|\\")*)" dropdown$/
*/
public function theIFillInTheDropdownWith($field, $value)
{
$field = $this->fixStepArgument($field);
$value = $this->fixStepArgument($value);
/**
* Workaround for chosen.js dropdowns which hide the original dropdown field.
*
* @When /^(?:|I )fill in the "(?P<field>(?:[^"]|\\")*)" dropdown with "(?P<value>(?:[^"]|\\")*)"$/
* @When /^(?:|I )fill in "(?P<value>(?:[^"]|\\")*)" for the "(?P<field>(?:[^"]|\\")*)" dropdown$/
*/
public function theIFillInTheDropdownWith($field, $value)
{
$field = $this->fixStepArgument($field);
$value = $this->fixStepArgument($value);
// Given the fuzzy matching, we might get more than one matching field.
$formFields = array();
// Given the fuzzy matching, we might get more than one matching field.
$formFields = array();
// Find by label
$formField = $this->getSession()->getPage()->findField($field);
if($formField) $formFields[] = $formField;
// Find by label
$formField = $this->getSession()->getPage()->findField($field);
if($formField) $formFields[] = $formField;
// Fall back to finding by title (for dropdowns without a label)
if(!$formFields) {
$formFields = $this->getSession()->getPage()->findAll(
'xpath',
sprintf(
'//*[self::select][(./@title="%s")]',
$field
)
);
}
// Fall back to finding by title (for dropdowns without a label)
if(!$formFields) {
$formFields = $this->getSession()->getPage()->findAll(
'xpath',
sprintf(
'//*[self::select][(./@title="%s")]',
$field
)
);
}
assertGreaterThan(0, count($formFields), sprintf(
'Chosen.js dropdown named "%s" not found',
$field
));
assertGreaterThan(0, count($formFields), sprintf(
'Chosen.js dropdown named "%s" not found',
$field
));
$containers = array();
foreach($formFields as $formField) {
// Traverse up to field holder
$containerCandidate = $formField;
do {
$containerCandidate = $containerCandidate->getParent();
} while($containerCandidate && !preg_match('/field/', $containerCandidate->getAttribute('class')));
$containers = array();
foreach($formFields as $formField) {
// Traverse up to field holder
$containerCandidate = $formField;
do {
$containerCandidate = $containerCandidate->getParent();
} while($containerCandidate && !preg_match('/field/', $containerCandidate->getAttribute('class')));
if(
$containerCandidate
&& $containerCandidate->isVisible()
&& preg_match('/field/', $containerCandidate->getAttribute('class'))
) {
$containers[] = $containerCandidate;
}
}
assertGreaterThan(0, count($containers), 'Chosen.js field container not found');
if(
$containerCandidate
&& $containerCandidate->isVisible()
&& preg_match('/field/', $containerCandidate->getAttribute('class'))
) {
$containers[] = $containerCandidate;
}
}
assertGreaterThan(0, count($containers), 'Chosen.js field container not found');
// Default to first visible container
$container = $containers[0];
// Click on newly expanded list element, indirectly setting the dropdown value
$linkEl = $container->find('xpath', './/a[./@href]');
assertNotNull($linkEl, 'Chosen.js link element not found');
$this->getSession()->wait(100); // wait for dropdown overlay to appear
$linkEl->click();
// Default to first visible container
$container = $containers[0];
// Click on newly expanded list element, indirectly setting the dropdown value
$linkEl = $container->find('xpath', './/a[./@href]');
assertNotNull($linkEl, 'Chosen.js link element not found');
$this->getSession()->wait(100); // wait for dropdown overlay to appear
$linkEl->click();
$listEl = $container->find('xpath', sprintf('.//li[contains(normalize-space(string(.)), \'%s\')]', $value));
assertNotNull($listEl, sprintf(
'Chosen.js list element with title "%s" not found',
$value
));
$listEl = $container->find('xpath', sprintf('.//li[contains(normalize-space(string(.)), \'%s\')]', $value));
assertNotNull($listEl, sprintf(
'Chosen.js list element with title "%s" not found',
$value
));
// Dropdown flyout might be animated
// $this->getSession()->wait(1000, 'jQuery(":animated").length == 0');
$this->getSession()->wait(300);
// Dropdown flyout might be animated
// $this->getSession()->wait(1000, 'jQuery(":animated").length == 0');
$this->getSession()->wait(300);
$listEl->click();
}
$listEl->click();
}
/**
* Returns fixed step argument (with \\" replaced back to ").
*
* @param string $argument
*
* @return string
*/
protected function fixStepArgument($argument)
{
return str_replace('\\"', '"', $argument);
}
/**
* Returns fixed step argument (with \\" replaced back to ").
*
* @param string $argument
*
* @return string
*/
protected function fixStepArgument($argument)
{
return str_replace('\\"', '"', $argument);
}
}

View File

@ -27,18 +27,18 @@ if(!defined('BASE_PATH')) define('BASE_PATH', dirname($frameworkPath));
// Copied from cli-script.php, to enable same behaviour through phpunit runner.
if(isset($_SERVER['argv'][2])) {
$args = array_slice($_SERVER['argv'],2);
if(!isset($_GET)) $_GET = array();
if(!isset($_REQUEST)) $_REQUEST = array();
foreach($args as $arg) {
if(strpos($arg,'=') == false) {
$_GET['args'][] = $arg;
} else {
$newItems = array();
parse_str( (substr($arg,0,2) == '--') ? substr($arg,2) : $arg, $newItems );
$_GET = array_merge($_GET, $newItems);
}
}
$args = array_slice($_SERVER['argv'],2);
if(!isset($_GET)) $_GET = array();
if(!isset($_REQUEST)) $_REQUEST = array();
foreach($args as $arg) {
if(strpos($arg,'=') == false) {
$_GET['args'][] = $arg;
} else {
$newItems = array();
parse_str( (substr($arg,0,2) == '--') ? substr($arg,2) : $arg, $newItems );
$_GET = array_merge($_GET, $newItems);
}
}
$_REQUEST = array_merge($_REQUEST, $_GET);
}
@ -70,4 +70,4 @@ if(!isset($_GET['flush']) || !$_GET['flush']) {
"Add flush=1 as an argument to discover new classes or files.\n",
false
);
}
}

View File

@ -10,8 +10,8 @@ class HTTPTest extends SapphireTest {
/**
* Tests {@link HTTP::getLinksIn()}
*/
public function testGetLinksIn() {
$content = '
public function testGetLinksIn() {
$content = '
<h2><a href="/">My Cool Site</a></h2>
<p>
@ -26,13 +26,13 @@ class HTTPTest extends SapphireTest {
played a part in his <a href=journey"extra id="JourneyLink">journey</a>. HE ALSO DISCOVERED THE
<A HREF="CAPS LOCK">KEY</a>. Later he got his <a href="quotes \'mixed\' up">mixed up</a>.
</p>
';
';
$expected = array (
'/', 'home/', 'mother/', '$Journey', 'space travel', 'unquoted', 'single quote', '/father', 'attributes',
'journey', 'CAPS LOCK', 'quotes \'mixed\' up'
);
$result = HTTP::getLinksIn($content);
// Results don't neccesarily come out in the order they are in the $content param.
@ -41,7 +41,7 @@ class HTTPTest extends SapphireTest {
$this->assertTrue(is_array($result));
$this->assertEquals($expected, $result, 'Test that all links within the content are found.');
}
}
/**
* Tests {@link HTTP::setGetVar()}

View File

@ -11,7 +11,7 @@ class ArrayDataTest extends SapphireTest {
$this->assertEquals("Varchar", get_class($arrayData->A));
$this->assertEquals("ArrayData", get_class($arrayData->B));
}
public function testWrappingANonEmptyObjectWorks() {
$object = new ArrayDataTest_NonEmptyObject();
$this->assertTrue(is_object($object));

View File

@ -4,5 +4,5 @@
*/
namespace silverstripe\test;
class ClassB extends ClassA { }

View File

@ -55,7 +55,7 @@ class CsvBulkLoaderTest extends SapphireTest {
$this->assertEquals(4, $resultDataObject->Count(),
'Test if existing data is deleted before new data is added');
}
}
/**
* Test import with manual column mapping

View File

@ -18,11 +18,11 @@ class FileFieldTest extends FunctionalTest {
new FieldList()
);
$fileFieldValue = array(
'name' => 'aCV.txt',
'type' => 'application/octet-stream',
'tmp_name' => '/private/var/tmp/phpzTQbqP',
'error' => 0,
'size' => 3471
'name' => 'aCV.txt',
'type' => 'application/octet-stream',
'tmp_name' => '/private/var/tmp/phpzTQbqP',
'error' => 0,
'size' => 3471
);
$fileField->setValue($fileFieldValue);
@ -46,11 +46,11 @@ class FileFieldTest extends FunctionalTest {
);
// All fields are filled but for some reason an error occured when uploading the file => fails
$fileFieldValue = array(
'name' => 'aCV.txt',
'type' => 'application/octet-stream',
'tmp_name' => '/private/var/tmp/phpzTQbqP',
'error' => 1,
'size' => 3471
'name' => 'aCV.txt',
'type' => 'application/octet-stream',
'tmp_name' => '/private/var/tmp/phpzTQbqP',
'error' => 1,
'size' => 3471
);
$fileField->setValue($fileFieldValue);

View File

@ -368,7 +368,7 @@ class RequirementsTest extends SapphireTest {
);
}
}
public function assertFileNotIncluded($backend, $type, $files) {
$type = strtolower($type);
switch ($type) {
@ -412,4 +412,4 @@ class RequirementsTest extends SapphireTest {
);
}
}
}
}

View File

@ -4,7 +4,7 @@
* @subpackage tests
*/
class UploadFieldTest extends FunctionalTest {
class UploadFieldTest extends FunctionalTest {
static $fixture_file = 'UploadFieldTest.yml';

View File

@ -2,11 +2,11 @@
class SampleService
{
public $constructorVarOne;
public $constructorVarOne;
public $constructorVarTwo;
public function __construct($v1 = null, $v2 = null) {
$this->constructorVarOne = $v1;
$this->constructorVarTwo = $v2;
}
}
}

View File

@ -49,7 +49,7 @@
'<input type="hidden" name="testfield" value="1" />' +
'</div>'
);
});
});
afterEach(function() {
$('#testfield').remove();
@ -114,7 +114,7 @@
'<input type="hidden" name="testfield" value="1" />' +
'</div>'
);
});
});
afterEach(function() {
$('#testfield').remove();
@ -146,7 +146,7 @@
'<input type="hidden" name="testfield" value="4,5" />' +
'</div>'
);
});
});
afterEach(function() {
$('#testfield').remove();
@ -222,7 +222,7 @@
'<input type="hidden" name="MyFormValue" value="foo" />' +
'</form>'
);
});
});
afterEach(function() {
$('#testfield').remove();
@ -236,4 +236,4 @@
});
});
});
}(jQuery));
}(jQuery));

View File

@ -60,7 +60,6 @@ class ComponentSetTest_Player extends Member implements TestOnly {
static $belongs_many_many = array(
'Teams' => 'ComponentSetTest_Team'
);
}
class ComponentSetTest_Team extends DataObject implements TestOnly {

View File

@ -624,11 +624,11 @@ class DataListTest extends SapphireTest {
*/
public function testExcludeOnFilter() {
$list = DataObjectTest_TeamComment::get();
$list = $list->filter('Comment', 'Phil is a unique guy, and comments on team2');
$list = $list->filter('Comment', 'Phil is a unique guy, and comments on team2');
$list = $list->exclude('Name', 'Bob');
$this->assertContains(
'WHERE ("DataObjectTest_TeamComment"."Comment" = '
'WHERE ("DataObjectTest_TeamComment"."Comment" = '
. '\'Phil is a unique guy, and comments on team2\') '
. 'AND (("DataObjectTest_TeamComment"."Name" != \'Bob\'))',
$list->sql());

View File

@ -1125,7 +1125,6 @@ class DataObjectTest_Player extends Member implements TestOnly {
static $belongs_many_many = array(
'Teams' => 'DataObjectTest_Team'
);
}
class DataObjectTest_Team extends DataObject implements TestOnly {

View File

@ -71,12 +71,12 @@ class MoneyTest extends SapphireTest {
}
/**
* Write a Money object to the database, then re-read it to ensure it
* is re-read properly.
*/
public function testGettingWrittenDataObject() {
$local = i18n::get_locale();
//make sure that the $ amount is not prefixed by US$, as it would be in non-US locale
* Write a Money object to the database, then re-read it to ensure it
* is re-read properly.
*/
public function testGettingWrittenDataObject() {
$local = i18n::get_locale();
//make sure that the $ amount is not prefixed by US$, as it would be in non-US locale
i18n::set_locale('en_US');
$obj = new MoneyTest_DataObject();
@ -99,8 +99,8 @@ class MoneyTest extends SapphireTest {
"Money field not added to data object properly when read."
);
i18n::set_locale($local);
}
i18n::set_locale($local);
}
public function testToCurrency() {
$USD = new Money();

View File

@ -43,11 +43,11 @@ class PaginatedListTest extends SapphireTest {
public function testSetPaginationFromQuery() {
$query = $this->getMock('SQLQuery');
$query->expects($this->once())
->method('getLimit')
->will($this->returnValue(array('limit' => 15, 'start' => 30)));
->method('getLimit')
->will($this->returnValue(array('limit' => 15, 'start' => 30)));
$query->expects($this->once())
->method('unlimitedRowCount')
->will($this->returnValue(100));
->method('unlimitedRowCount')
->will($this->returnValue(100));
$list = new PaginatedList(new ArrayList());
$list->setPaginationFromQuery($query);

View File

@ -254,12 +254,12 @@ class VersionedTest extends SapphireTest {
* Test that SQLQuery::queriedTables() applies the version-suffixes properly.
*/
public function testQueriedTables() {
Versioned::reading_stage('Live');
Versioned::reading_stage('Live');
$this->assertEquals(array(
'VersionedTest_DataObject_Live',
'VersionedTest_Subclass_Live',
), DataObject::get('VersionedTest_Subclass')->dataQuery()->query()->queriedTables());
$this->assertEquals(array(
'VersionedTest_DataObject_Live',
'VersionedTest_Subclass_Live',
), DataObject::get('VersionedTest_Subclass')->dataQuery()->query()->queriedTables());
}
public function testGetVersionWhenClassnameChanged() {

18
tests/phpcs/tabs.xml Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="SilverStripe.Tabs">
<description>CodeSniffer ruleset for SilverStripe indentation conventions.</description>
<!-- exclude SCSS-generated CSS files -->
<exclude-pattern>*/css/*</exclude-pattern>
<exclude-pattern>css/*</exclude-pattern>
<!-- exclude thirdparty content -->
<exclude-pattern>thirdparty/*</exclude-pattern>
<exclude-pattern>*/jquery-changetracker/*</exclude-pattern>
<exclude-pattern>parsers/HTML/BBCodeParser/*</exclude-pattern>
<!-- PHP-PEG generated file not intended for human consumption -->
<exclude-pattern>*/SSTemplateParser.php$</exclude-pattern>
<rule ref="Generic.WhiteSpace.DisallowSpaceIndent"/>
</ruleset>

View File

@ -41,40 +41,40 @@ class SearchContextTest extends SapphireTest {
}
public function testPartialMatchUsedByDefaultWhenNotExplicitlySet() {
$person = singleton('SearchContextTest_Person');
$context = $person->getDefaultSearchContext();
$this->assertEquals(
array(
"Name" => new PartialMatchFilter("Name"),
"HairColor" => new PartialMatchFilter("HairColor"),
"EyeColor" => new PartialMatchFilter("EyeColor")
),
$context->getFilters()
);
$person = singleton('SearchContextTest_Person');
$context = $person->getDefaultSearchContext();
$this->assertEquals(
array(
"Name" => new PartialMatchFilter("Name"),
"HairColor" => new PartialMatchFilter("HairColor"),
"EyeColor" => new PartialMatchFilter("EyeColor")
),
$context->getFilters()
);
}
public function testDefaultFiltersDefinedWhenNotSetInDataObject() {
$book = singleton('SearchContextTest_Book');
$context = $book->getDefaultSearchContext();
$this->assertEquals(
array(
"Title" => new PartialMatchFilter("Title")
),
$context->getFilters()
);
$this->assertEquals(
array(
"Title" => new PartialMatchFilter("Title")
),
$context->getFilters()
);
}
public function testUserDefinedFiltersAppearInSearchContext() {
$company = singleton('SearchContextTest_Company');
$context = $company->getDefaultSearchContext();
$this->assertEquals(
array(
"Name" => new PartialMatchFilter("Name"),
"Industry" => new PartialMatchFilter("Industry"),
"AnnualProfit" => new PartialMatchFilter("AnnualProfit")
"Industry" => new PartialMatchFilter("Industry"),
"AnnualProfit" => new PartialMatchFilter("AnnualProfit")
),
$context->getFilters()
);
@ -87,8 +87,8 @@ class SearchContextTest extends SapphireTest {
$this->assertEquals(
new FieldList(
new TextField("Name", 'Name'),
new TextareaField("Industry", 'Industry'),
new NumericField("AnnualProfit", 'The Almighty Annual Profit')
new TextareaField("Industry", 'Industry'),
new NumericField("AnnualProfit", 'The Almighty Annual Profit')
),
$context->getFields()
);

View File

@ -52,47 +52,47 @@ class GroupTest extends FunctionalTest {
public function testMemberGroupRelationForm() {
Session::set('loggedInAs', $this->idFromFixture('GroupTest_Member', 'admin'));
$adminGroup = $this->objFromFixture('Group', 'admingroup');
$parentGroup = $this->objFromFixture('Group', 'parentgroup');
$childGroup = $this->objFromFixture('Group', 'childgroup');
$adminGroup = $this->objFromFixture('Group', 'admingroup');
$parentGroup = $this->objFromFixture('Group', 'parentgroup');
$childGroup = $this->objFromFixture('Group', 'childgroup');
// Test single group relation through checkboxsetfield
$form = new GroupTest_MemberForm($this, 'Form');
$member = $this->objFromFixture('GroupTest_Member', 'admin');
$form->loadDataFrom($member);
$checkboxSetField = $form->Fields()->fieldByName('Groups');
$checkboxSetField->setValue(array(
$adminGroup->ID => $adminGroup->ID, // keep existing relation
$parentGroup->ID => $parentGroup->ID, // add new relation
));
$form->saveInto($member);
$updatedGroups = $member->Groups();
// Test single group relation through checkboxsetfield
$form = new GroupTest_MemberForm($this, 'Form');
$member = $this->objFromFixture('GroupTest_Member', 'admin');
$form->loadDataFrom($member);
$checkboxSetField = $form->Fields()->fieldByName('Groups');
$checkboxSetField->setValue(array(
$adminGroup->ID => $adminGroup->ID, // keep existing relation
$parentGroup->ID => $parentGroup->ID, // add new relation
));
$form->saveInto($member);
$updatedGroups = $member->Groups();
$this->assertEquals(
$this->assertEquals(
array($adminGroup->ID, $parentGroup->ID),
$updatedGroups->column(),
"Adding a toplevel group works"
);
$updatedGroups->column(),
"Adding a toplevel group works"
);
// Test unsetting relationship
$form->loadDataFrom($member);
$checkboxSetField = $form->Fields()->fieldByName('Groups');
$checkboxSetField->setValue(array(
$adminGroup->ID => $adminGroup->ID, // keep existing relation
//$parentGroup->ID => $parentGroup->ID, // remove previously set relation
));
$form->saveInto($member);
$member->flushCache();
$updatedGroups = $member->Groups();
$this->assertEquals(
// Test unsetting relationship
$form->loadDataFrom($member);
$checkboxSetField = $form->Fields()->fieldByName('Groups');
$checkboxSetField->setValue(array(
$adminGroup->ID => $adminGroup->ID, // keep existing relation
//$parentGroup->ID => $parentGroup->ID, // remove previously set relation
));
$form->saveInto($member);
$member->flushCache();
$updatedGroups = $member->Groups();
$this->assertEquals(
array($adminGroup->ID),
$updatedGroups->column(),
"Removing a previously added toplevel group works"
);
$updatedGroups->column(),
"Removing a previously added toplevel group works"
);
// Test adding child group
// Test adding child group
}
}
public function testCollateAncestorIDs() {
$parentGroup = $this->objFromFixture('Group', 'parentgroup');
@ -139,37 +139,37 @@ class GroupTest extends FunctionalTest {
}
class GroupTest_Member extends Member implements TestOnly {
public function getCMSFields() {
$groups = DataObject::get('Group');
$groupsMap = ($groups) ? $groups->map() : false;
$fields = new FieldList(
new HiddenField('ID', 'ID'),
new CheckboxSetField(
'Groups',
'Groups',
$groupsMap
)
);
return $fields;
}
public function getCMSFields() {
$groups = DataObject::get('Group');
$groupsMap = ($groups) ? $groups->map() : false;
$fields = new FieldList(
new HiddenField('ID', 'ID'),
new CheckboxSetField(
'Groups',
'Groups',
$groupsMap
)
);
return $fields;
}
}
class GroupTest_MemberForm extends Form {
public function __construct($controller, $name) {
$fields = singleton('GroupTest_Member')->getCMSFields();
$actions = new FieldList(
new FormAction('doSave','save')
);
parent::__construct($controller, $name, $fields, $actions);
}
public function doSave($data, $form) {
// done in testing methods
}
public function __construct($controller, $name) {
$fields = singleton('GroupTest_Member')->getCMSFields();
$actions = new FieldList(
new FormAction('doSave','save')
);
parent::__construct($controller, $name, $fields, $actions);
}
public function doSave($data, $form) {
// done in testing methods
}
}

View File

@ -29,8 +29,8 @@ class MemberTest extends FunctionalTest {
}
public function __destruct() {
i18n::set_default_locale($this->local);
}
i18n::set_default_locale($this->local);
}
public function setUp() {
parent::setUp();

View File

@ -155,9 +155,9 @@ class ViewableDataTest_Castable extends ViewableData {
return $this->unsafeXML();
}
public function forTemplate() {
return 'castable';
}
public function forTemplate() {
return 'castable';
}
}
class ViewableDataTest_RequiresCasting extends ViewableData {

View File

@ -65,7 +65,7 @@ class ArrayData extends ViewableData {
return new ArrayData($value);
} elseif (ArrayLib::is_associative($value)) {
return new ArrayData($value);
} else {
} else {
return $value;
}
}

View File

@ -22,7 +22,7 @@ class Requirements {
* @return boolean
*/
public static function get_combined_files_enabled() {
return self::backend()->get_combined_files_enabled();
return self::backend()->get_combined_files_enabled();
}
/**
@ -656,7 +656,7 @@ class Requirements_Backend {
$jsRequirements = '';
// Combine files - updates $this->javascript and $this->css
$this->process_combined_files();
$this->process_combined_files();
foreach(array_diff_key($this->javascript,$this->blocked) as $file => $dummy) {
$path = $this->path_for_file($file);
@ -1022,9 +1022,9 @@ class Requirements_Backend {
// file exists, check modification date of every contained file
$srcLastMod = 0;
foreach($fileList as $file) {
if(file_exists($base . $file)) {
$srcLastMod = max(filemtime($base . $file), $srcLastMod);
}
if(file_exists($base . $file)) {
$srcLastMod = max(filemtime($base . $file), $srcLastMod);
}
}
$refresh = $srcLastMod > filemtime($combinedFilePath);
} else {
@ -1070,9 +1070,9 @@ class Requirements_Backend {
// method repeatedly - it will behave different on the second call!
$this->javascript = $newJSRequirements;
$this->css = $newCSSRequirements;
}
public function get_custom_scripts() {
}
public function get_custom_scripts() {
$requirements = "";
if($this->customScript) {

View File

@ -453,7 +453,7 @@ class SSTemplateParser extends Parser {
function Require_Call(&$res, $sub) {
$res['php'] = "Requirements::".$sub['Method']['text'].'('.$sub['CallArguments']['php'].');';
}
/*!*
@ -617,7 +617,7 @@ class SSTemplateParser extends Parser {
function OldTTag_OldTPart(&$res, $sub) {
$res['php'] = $sub['php'];
}
/*!*
# This is the old <% sprintf(_t()) %> tag

View File

@ -664,10 +664,10 @@ class SSViewer {
}
if(!$this->chosenTemplates) {
$templateList = (is_array($templateList)) ? $templateList : array($templateList);
user_error("None of these templates can be found in theme '"
. self::current_theme() . "': ". implode(".ss, ", $templateList) . ".ss", E_USER_WARNING);
$templateList = (is_array($templateList)) ? $templateList : array($templateList);
user_error("None of these templates can be found in theme '"
. self::current_theme() . "': ". implode(".ss, ", $templateList) . ".ss", E_USER_WARNING);
}
}
@ -717,7 +717,7 @@ class SSViewer {
protected static $options = array(
'rewriteHashlinks' => true,
);
protected static $topLevel = array();
public static function topLevel() {