mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merged changes from 2.3 branch
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@71172 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
2eb73817c2
commit
60f75c5ca4
@ -25,7 +25,6 @@ Director::addRules(10, array(
|
|||||||
'$Controller//$Action/$ID/$OtherID' => '*',
|
'$Controller//$Action/$ID/$OtherID' => '*',
|
||||||
'images' => 'Image_Uploader',
|
'images' => 'Image_Uploader',
|
||||||
'' => 'RootURLController',
|
'' => 'RootURLController',
|
||||||
'sitemap.xml' => 'GoogleSitemap',
|
|
||||||
'api/v1' => 'RestfulServer',
|
'api/v1' => 'RestfulServer',
|
||||||
'soap/v1' => 'SOAPModelAccess',
|
'soap/v1' => 'SOAPModelAccess',
|
||||||
'dev' => 'DevelopmentAdmin',
|
'dev' => 'DevelopmentAdmin',
|
||||||
@ -47,7 +46,7 @@ Object::useCustomClass('Datetime','SSDatetime',true);
|
|||||||
* Add pear parser to include path
|
* Add pear parser to include path
|
||||||
*/
|
*/
|
||||||
$path = Director::baseFolder().'/sapphire/parsers/';
|
$path = Director::baseFolder().'/sapphire/parsers/';
|
||||||
set_include_path(get_include_path() . PATH_SEPARATOR . $path);
|
set_include_path(str_replace('.' . PATH_SEPARATOR, '.' . PATH_SEPARATOR . $path . PATH_SEPARATOR, get_include_path()));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define a default language different than english
|
* Define a default language different than english
|
||||||
@ -70,7 +69,4 @@ define('MCE_ROOT', 'jsparty/tiny_mce2/');
|
|||||||
*/
|
*/
|
||||||
define('EMAIL_BOUNCEHANDLER_KEY', '1aaaf8fb60ea253dbf6efa71baaacbb3');
|
define('EMAIL_BOUNCEHANDLER_KEY', '1aaaf8fb60ea253dbf6efa71baaacbb3');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -193,6 +193,7 @@ class RSSFeed extends ViewableData {
|
|||||||
* Return the content of the RSS feed
|
* Return the content of the RSS feed
|
||||||
*/
|
*/
|
||||||
function feedContent() {
|
function feedContent() {
|
||||||
|
SSViewer::set_source_file_comments(false);
|
||||||
return str_replace(' ', ' ', $this->renderWith('RSSFeed'));
|
return str_replace(' ', ' ', $this->renderWith('RSSFeed'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,6 +137,11 @@ class RestfulServer extends Controller {
|
|||||||
$id = (isset($this->urlParams['ID'])) ? $this->urlParams['ID'] : null;
|
$id = (isset($this->urlParams['ID'])) ? $this->urlParams['ID'] : null;
|
||||||
$relation = (isset($this->urlParams['Relation'])) ? $this->urlParams['Relation'] : null;
|
$relation = (isset($this->urlParams['Relation'])) ? $this->urlParams['Relation'] : null;
|
||||||
|
|
||||||
|
// Check input formats
|
||||||
|
if(!class_exists($className)) return $this->notFound();
|
||||||
|
if($id && !is_numeric($id)) return $this->notFound();
|
||||||
|
if($relation && !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $relation)) return $this->notFound();
|
||||||
|
|
||||||
// if api access is disabled, don't proceed
|
// if api access is disabled, don't proceed
|
||||||
$apiAccess = singleton($className)->stat('api_access');
|
$apiAccess = singleton($className)->stat('api_access');
|
||||||
if(!$apiAccess) return $this->permissionFailure();
|
if(!$apiAccess) return $this->permissionFailure();
|
||||||
|
@ -125,7 +125,14 @@ class RestfulService extends ViewableData {
|
|||||||
$responseBody = curl_exec($ch);
|
$responseBody = curl_exec($ch);
|
||||||
$curlError = curl_error($ch);
|
$curlError = curl_error($ch);
|
||||||
|
|
||||||
if($curlError) {
|
// Problem verifying the server SSL certificate; just ignore it as it's not mandatory
|
||||||
|
if(strpos($curlError,'14090086') !== false) {
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||||
|
$responseBody = curl_exec($ch);
|
||||||
|
$curlError = curl_error($ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($responseBody === false) {
|
||||||
user_error("Curl Error:" . $curlError, E_USER_WARNING);
|
user_error("Curl Error:" . $curlError, E_USER_WARNING);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ class XMLDataFormatter extends DataFormatter {
|
|||||||
* @return String XML
|
* @return String XML
|
||||||
*/
|
*/
|
||||||
public function convertDataObject(DataObjectInterface $obj, $fields = null) {
|
public function convertDataObject(DataObjectInterface $obj, $fields = null) {
|
||||||
Controller::curr()->getResponse()->addHeader("Content-type", "text/xml");
|
Controller::curr()->getResponse()->addHeader("Content-Type", "text/xml");
|
||||||
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" . $this->convertDataObjectWithoutHeader($obj, $fields);
|
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" . $this->convertDataObjectWithoutHeader($obj, $fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ class XMLDataFormatter extends DataFormatter {
|
|||||||
* @return String XML
|
* @return String XML
|
||||||
*/
|
*/
|
||||||
public function convertDataObjectSet(DataObjectSet $set, $fields = null) {
|
public function convertDataObjectSet(DataObjectSet $set, $fields = null) {
|
||||||
Controller::curr()->getResponse()->addHeader("Content-type", "text/xml");
|
Controller::curr()->getResponse()->addHeader("Content-Type", "text/xml");
|
||||||
$className = $set->class;
|
$className = $set->class;
|
||||||
|
|
||||||
$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||||
|
@ -11,8 +11,10 @@
|
|||||||
*/
|
*/
|
||||||
abstract class CliController extends Controller {
|
abstract class CliController extends Controller {
|
||||||
function init() {
|
function init() {
|
||||||
$this->disableBasicAuth();
|
$this->disableBasicAuth();
|
||||||
parent::init();
|
parent::init();
|
||||||
|
// Unless called from the command line, all CliControllers need ADMIN privileges
|
||||||
|
if(!Director::is_cli() && !Permission::check("ADMIN")) return Security::permissionFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
function index() {
|
function index() {
|
||||||
@ -30,4 +32,5 @@ abstract class CliController extends Controller {
|
|||||||
*/
|
*/
|
||||||
function process() {}
|
function process() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
@ -93,16 +93,36 @@ class ClassInfo {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of classes that inherit from the given class.
|
* Returns a list of classes that inherit from the given class.
|
||||||
|
* The resulting array includes the base class passed
|
||||||
|
* through the $class parameter as the first array value.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* <example>
|
||||||
|
* ClassInfo::subclassesFor('BaseClass');
|
||||||
|
* array(
|
||||||
|
* 0 => 'BaseClass',
|
||||||
|
* 'ChildClass' => 'ChildClass',
|
||||||
|
* 'GrandChildClass' => 'GrandChildClass'
|
||||||
|
* )
|
||||||
|
* </example>
|
||||||
*
|
*
|
||||||
* @param mixed $class string of the classname or instance of the class
|
* @param mixed $class string of the classname or instance of the class
|
||||||
* @return array
|
* @return array Names of all subclasses as an associative array.
|
||||||
*/
|
*/
|
||||||
static function subclassesFor($class){
|
static function subclassesFor($class){
|
||||||
global $_ALL_CLASSES;
|
global $_ALL_CLASSES;
|
||||||
if (is_object($class)) $class = get_class($class);
|
if (is_object($class)) $class = get_class($class);
|
||||||
|
|
||||||
|
// get all classes from the manifest
|
||||||
$subclasses = isset($_ALL_CLASSES['children'][$class]) ? $_ALL_CLASSES['children'][$class] : null;
|
$subclasses = isset($_ALL_CLASSES['children'][$class]) ? $_ALL_CLASSES['children'][$class] : null;
|
||||||
if(isset($subclasses)) array_unshift($subclasses, $class);
|
|
||||||
else $subclasses[$class] = $class;
|
// add the base class to the array
|
||||||
|
if(isset($subclasses)) {
|
||||||
|
array_unshift($subclasses, $class);
|
||||||
|
} else {
|
||||||
|
$subclasses[$class] = $class;
|
||||||
|
}
|
||||||
|
|
||||||
return $subclasses;
|
return $subclasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,5 +286,4 @@ function _t($entity, $string = "", $priority = 40, $context = "") {
|
|||||||
return i18n::_t($entity, $string, $priority, $context);
|
return i18n::_t($entity, $string, $priority, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -102,11 +102,9 @@ class HTTP {
|
|||||||
|
|
||||||
static function findByTagAndAttribute($content, $attribs) {
|
static function findByTagAndAttribute($content, $attribs) {
|
||||||
$regExps = array();
|
$regExps = array();
|
||||||
$content = '';
|
|
||||||
|
|
||||||
foreach($attribs as $tag => $attrib) {
|
foreach($attribs as $tag => $attrib) {
|
||||||
if(!is_numeric($tag)) $tagPrefix = "$tag ";
|
$tagPrefix = (is_numeric($tag)) ? '' : "$tag ";
|
||||||
else $tagPrefix = "";
|
|
||||||
|
|
||||||
$regExps[] = "/(<{$tagPrefix}[^>]*$attrib *= *\")([^\"]*)(\")/ie";
|
$regExps[] = "/(<{$tagPrefix}[^>]*$attrib *= *\")([^\"]*)(\")/ie";
|
||||||
$regExps[] = "/(<{$tagPrefix}[^>]*$attrib *= *')([^']*)(')/ie";
|
$regExps[] = "/(<{$tagPrefix}[^>]*$attrib *= *')([^']*)(')/ie";
|
||||||
@ -125,6 +123,7 @@ class HTTP {
|
|||||||
static function getLinksIn($content) {
|
static function getLinksIn($content) {
|
||||||
return self::findByTagAndAttribute($content, array("a" => "href"));
|
return self::findByTagAndAttribute($content, array("a" => "href"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static function getImagesIn($content) {
|
static function getImagesIn($content) {
|
||||||
return self::findByTagAndAttribute($content, array("img" => "src"));
|
return self::findByTagAndAttribute($content, array("img" => "src"));
|
||||||
}
|
}
|
||||||
@ -362,5 +361,4 @@ class HTTP {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -549,5 +549,4 @@ class ManifestBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -516,10 +516,6 @@ class Object {
|
|||||||
Object::$extraStatics[$className]['extensions'] = array_diff(Object::$extraStatics[$className]['extensions'], array($extensionName));
|
Object::$extraStatics[$className]['extensions'] = array_diff(Object::$extraStatics[$className]['extensions'], array($extensionName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// CACHE METHODS (added by simon_w (simon -at- simon -dot- geek -dot- nz))
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a current cache from the filesystem, if it can.
|
* Loads a current cache from the filesystem, if it can.
|
||||||
*
|
*
|
||||||
@ -606,8 +602,6 @@ class Object {
|
|||||||
* @param string|int $id An id for the cache
|
* @param string|int $id An id for the cache
|
||||||
* @return mixed The cached return of the method
|
* @return mixed The cached return of the method
|
||||||
*/
|
*/
|
||||||
// I know this is almost exactly the same as cacheToFile, but call_user_func_array() is slow.
|
|
||||||
// Which is why there's two separate functions
|
|
||||||
public function cacheToFileWithArgs($callback, $args = array(), $expire = 3600, $id = false) {
|
public function cacheToFileWithArgs($callback, $args = array(), $expire = 3600, $id = false) {
|
||||||
if(!$this->class) {
|
if(!$this->class) {
|
||||||
$this->class = get_class($this);
|
$this->class = get_class($this);
|
||||||
|
@ -54,16 +54,17 @@ class Requirements {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the CSS styling to the header of the page
|
* Include custom CSS styling to the header of the page.
|
||||||
*
|
*
|
||||||
* See {@link Requirements_Backend::customCSS()}
|
* See {@link Requirements_Backend::customCSS()}
|
||||||
|
*
|
||||||
|
* @param string $script CSS selectors as a string (without <style> tag enclosing selectors).
|
||||||
|
* @param int $uniquenessID Group CSS by a unique ID as to avoid duplicate custom CSS in header
|
||||||
*/
|
*/
|
||||||
static function customCSS($script, $uniquenessID = null) {
|
static function customCSS($script, $uniquenessID = null) {
|
||||||
self::backend()->custom($script, $uniquenessID);
|
self::backend()->customCSS($script, $uniquenessID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the following custom code to the <head> section of the page.
|
* Add the following custom code to the <head> section of the page.
|
||||||
* See {@link Requirements_Backend::insertHeadTags()}
|
* See {@link Requirements_Backend::insertHeadTags()}
|
||||||
@ -245,7 +246,7 @@ class Requirements {
|
|||||||
* Set whether you want to write the JS to the body of the page or
|
* Set whether you want to write the JS to the body of the page or
|
||||||
* in the head section
|
* in the head section
|
||||||
*
|
*
|
||||||
* @see {@link Requirements_Backend::set_write_js_to_body()}
|
* @see Requirements_Backend::set_write_js_to_body()
|
||||||
* @param boolean
|
* @param boolean
|
||||||
*/
|
*/
|
||||||
static function set_write_js_to_body($var) {
|
static function set_write_js_to_body($var) {
|
||||||
@ -390,7 +391,12 @@ class Requirements_Backend {
|
|||||||
$script .= "\n";
|
$script .= "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Include custom CSS styling to the header of the page.
|
||||||
|
*
|
||||||
|
* @param string $script CSS selectors as a string (without <style> tag enclosing selectors).
|
||||||
|
* @param int $uniquenessID Group CSS by a unique ID as to avoid duplicate custom CSS in header
|
||||||
|
*/
|
||||||
function customCSS($script, $uniquenessID = null) {
|
function customCSS($script, $uniquenessID = null) {
|
||||||
if($uniquenessID)
|
if($uniquenessID)
|
||||||
$this->customCSS[$uniquenessID] = $script;
|
$this->customCSS[$uniquenessID] = $script;
|
||||||
@ -399,7 +405,6 @@ class Requirements_Backend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the following custom code to the <head> section of the page.
|
* Add the following custom code to the <head> section of the page.
|
||||||
*
|
*
|
||||||
@ -444,7 +449,7 @@ class Requirements_Backend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function get_css() {
|
function get_css() {
|
||||||
return array_diff_key($this->css,$this->blocked);
|
return array_diff_key($this->css, $this->blocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -561,7 +566,7 @@ class Requirements_Backend {
|
|||||||
$requirements .= "<link rel=\"stylesheet\" type=\"text/css\"{$media} href=\"$path\" />\n";
|
$requirements .= "<link rel=\"stylesheet\" type=\"text/css\"{$media} href=\"$path\" />\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach(array_diff_key($this->customCSS,$this->blocked) as $css) {
|
foreach(array_diff_key($this->customCSS, $this->blocked) as $css) {
|
||||||
$requirements .= "<style type=\"text/css\">\n$css\n</style>\n";
|
$requirements .= "<style type=\"text/css\">\n$css\n</style>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -775,6 +780,7 @@ class Requirements_Backend {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function process_combined_files() {
|
function process_combined_files() {
|
||||||
|
|
||||||
if(Director::isDev() && !SapphireTest::is_running_test()) {
|
if(Director::isDev() && !SapphireTest::is_running_test()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -861,16 +867,7 @@ class Requirements_Backend {
|
|||||||
// Unsuccessful write - just include the regular JS files, rather than the combined one
|
// Unsuccessful write - just include the regular JS files, rather than the combined one
|
||||||
if(!$successfulWrite) {
|
if(!$successfulWrite) {
|
||||||
user_error("Requirements_Backend::process_combined_files(): Couldn't create '$base$combinedFile'", E_USER_WARNING);
|
user_error("Requirements_Backend::process_combined_files(): Couldn't create '$base$combinedFile'", E_USER_WARNING);
|
||||||
$keyedFileList = array();
|
return;
|
||||||
foreach($fileList as $file) $keyedFileList[$file] = true;
|
|
||||||
$combinedPos = array_search($combinedFile, array_keys($newJSRequirements));
|
|
||||||
if($combinedPos) {
|
|
||||||
$newJSRequirements = array_merge(
|
|
||||||
array_slice($newJSRequirements, 0, $combinedPos),
|
|
||||||
$keyedFileList,
|
|
||||||
array_slice($newJSRequirements, $combinedPos+1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -925,5 +922,4 @@ class Requirements_Backend {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
@ -48,16 +48,29 @@
|
|||||||
* @subpackage view
|
* @subpackage view
|
||||||
*/
|
*/
|
||||||
class SSViewer extends Object {
|
class SSViewer extends Object {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var boolean $source_file_comments
|
||||||
|
*/
|
||||||
protected static $source_file_comments = true;
|
protected static $source_file_comments = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether HTML comments indicating the source .SS file used to render this page should be
|
* Set whether HTML comments indicating the source .SS file used to render this page should be
|
||||||
* included in the output. This is enabled by default
|
* included in the output. This is enabled by default
|
||||||
|
*
|
||||||
|
* @param boolean $val
|
||||||
*/
|
*/
|
||||||
function set_source_file_comments($val) {
|
static function set_source_file_comments($val) {
|
||||||
self::$source_file_comments = $val;
|
self::$source_file_comments = $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
static function get_source_file_comments() {
|
||||||
|
return self::$source_file_comments;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array $chosenTemplates Associative array for the different
|
* @var array $chosenTemplates Associative array for the different
|
||||||
* template containers: "main" and "Layout".
|
* template containers: "main" and "Layout".
|
||||||
@ -355,6 +368,7 @@ class SSViewer extends Object {
|
|||||||
|
|
||||||
static function parseTemplateContent($content, $template="") {
|
static function parseTemplateContent($content, $template="") {
|
||||||
// Add template filename comments on dev sites
|
// Add template filename comments on dev sites
|
||||||
|
|
||||||
if(Director::isDev() && self::$source_file_comments && $template) {
|
if(Director::isDev() && self::$source_file_comments && $template) {
|
||||||
// If this template is a full HTML page, then put the comments just inside the HTML tag to prevent any IE glitches
|
// If this template is a full HTML page, then put the comments just inside the HTML tag to prevent any IE glitches
|
||||||
if(stripos($content, "<html") !== false) {
|
if(stripos($content, "<html") !== false) {
|
||||||
@ -369,9 +383,9 @@ class SSViewer extends Object {
|
|||||||
$oldContent = $content;
|
$oldContent = $content;
|
||||||
|
|
||||||
// Add include filename comments on dev sites
|
// Add include filename comments on dev sites
|
||||||
if(Director::isDev()) $replacementCode = 'return "<!-- include " . SSViewer::getTemplateFile($matches[1]) . "-->\n"
|
if(Director::isDev() && self::$source_file_comments) $replacementCode = 'return "<!-- include " . SSViewer::getTemplateFile($matches[1]) . " -->\n"
|
||||||
. SSViewer::getTemplateContent($matches[1])
|
. SSViewer::getTemplateContent($matches[1])
|
||||||
. "\n<!-- end include " . SSViewer::getTemplateFile($matches[1]) . "-->";';
|
. "\n<!-- end include " . SSViewer::getTemplateFile($matches[1]) . " -->";';
|
||||||
else $replacementCode = 'return SSViewer::getTemplateContent($matches[1]);';
|
else $replacementCode = 'return SSViewer::getTemplateContent($matches[1]);';
|
||||||
|
|
||||||
$content = preg_replace_callback('/<' . '% include +([A-Za-z0-9_]+) +%' . '>/', create_function(
|
$content = preg_replace_callback('/<' . '% include +([A-Za-z0-9_]+) +%' . '>/', create_function(
|
||||||
|
@ -224,7 +224,7 @@ JS
|
|||||||
if($this->dataRecord){
|
if($this->dataRecord){
|
||||||
$thisPage = $this->dataRecord->Link();
|
$thisPage = $this->dataRecord->Link();
|
||||||
$cmsLink = 'admin/show/' . $this->dataRecord->ID;
|
$cmsLink = 'admin/show/' . $this->dataRecord->ID;
|
||||||
$cmsLink = "<a href=\"$cmsLink\" target=\"cms\">CMS</a>";
|
$cmsLink = "<a href=\"$cmsLink\" target=\"cms\">". _t('ContentController.CMS', 'CMS') ."</a>";
|
||||||
} else {
|
} else {
|
||||||
/**
|
/**
|
||||||
* HGS: If this variable is missing a notice is raised. Subclasses of ContentController
|
* HGS: If this variable is missing a notice is raised. Subclasses of ContentController
|
||||||
@ -241,30 +241,30 @@ JS
|
|||||||
$dateObj = Object::create('Datetime', $date, null);
|
$dateObj = Object::create('Datetime', $date, null);
|
||||||
// $dateObj->setVal($date);
|
// $dateObj->setVal($date);
|
||||||
|
|
||||||
$archiveLink = "<a class=\"current\">Archived Site</a>";
|
$archiveLink = "<a class=\"current\">". _t('ContentController.ARCHIVEDSITE', 'Archived Site') ."</a>";
|
||||||
$liveLink = "<a href=\"$thisPage?stage=Live\" target=\"site\" style=\"left : -3px;\">Published Site</a>";
|
$liveLink = "<a href=\"$thisPage?stage=Live\" target=\"site\" style=\"left : -3px;\">". _t('ContentController.PUBLISHEDSITE', 'Published Site') ."</a>";
|
||||||
$stageLink = "<a href=\"$thisPage?stage=Stage\" target=\"site\" style=\"left : -1px;\">Draft Site</a>";
|
$stageLink = "<a href=\"$thisPage?stage=Stage\" target=\"site\" style=\"left : -1px;\">". _t('ContentController.DRAFTSITE', 'Draft Site') ."</a>";
|
||||||
$message = "<div id=\"SilverStripeNavigatorMessage\" title=\"Note: this message won't be shown to your visitors\">Archived site from<br>" . $dateObj->Nice() . "</div>";
|
$message = "<div id=\"SilverStripeNavigatorMessage\" title='". _t('ContentControl.NOTEWONTBESHOWN', 'Note: this message won\'t be shown to your visitors') ."'>". _t('ContentController.ARCHIVEDSITEFROM', 'Archived site from') ."<br>" . $dateObj->Nice() . "</div>";
|
||||||
|
|
||||||
} else if(Versioned::current_stage() == 'Stage') {
|
} else if(Versioned::current_stage() == 'Stage') {
|
||||||
$stageLink = "<a class=\"current\">Draft Site</a>";
|
$stageLink = "<a class=\"current\">". _t('ContentController.DRAFTSITE', 'Draft Site') ."</a>";
|
||||||
$liveLink = "<a href=\"$thisPage?stage=Live\" target=\"site\" style=\"left : -3px;\">Published Site</a>";
|
$liveLink = "<a href=\"$thisPage?stage=Live\" target=\"site\" style=\"left : -3px;\">". _t('ContentController.PUBLISHEDSITE', 'Published Site') ."</a>";
|
||||||
$message = "<div id=\"SilverStripeNavigatorMessage\" title=\"Note: this message won't be shown to your visitors\">DRAFT SITE</div>";
|
$message = "<div id=\"SilverStripeNavigatorMessage\" title='". _t('ContentControl.NOTEWONTBESHOWN', 'Note: this message won\'t be shown to your visitors') ."'>". _t('ContentController.DRAFTSITE', 'Draft Site') ."</div>";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$liveLink = "<a class=\"current\">Published Site</a>";
|
$liveLink = "<a class=\"current\">". _t('ContentController.PUBLISHEDSITE', 'Published Site') ."</a>";
|
||||||
$stageLink = "<a href=\"$thisPage?stage=Stage\" target=\"site\" style=\"left : -1px;\">Draft Site</a>";
|
$stageLink = "<a href=\"$thisPage?stage=Stage\" target=\"site\" style=\"left : -1px;\">". _t('ContentController.DRAFTSITE', 'Draft Site') ."</a>";
|
||||||
$message = "<div id=\"SilverStripeNavigatorMessage\" title=\"Note: this message won't be shown to your visitors\">PUBLISHED SITE</div>";
|
$message = "<div id=\"SilverStripeNavigatorMessage\" title='". _t('ContentControl.NOTEWONTBESHOWN', 'Note: this message won\'t be shown to your visitors') ."'>". _t('ContentController.PUBLISHEDSITE', 'Published Site') ."</div>";
|
||||||
}
|
}
|
||||||
|
|
||||||
if($member) {
|
if($member) {
|
||||||
$firstname = Convert::raw2xml($member->FirstName);
|
$firstname = Convert::raw2xml($member->FirstName);
|
||||||
$surname = Convert::raw2xml($member->Surame);
|
$surname = Convert::raw2xml($member->Surame);
|
||||||
$logInMessage = "Logged in as {$firstname} {$surname} - <a href=\"Security/logout\">log out</a>";
|
$logInMessage = _t('ContentController.LOGGEDINAS', 'Logged in as') ." {$firstname} {$surname} - <a href=\"Security/logout\">". _t('ContentController.LOGOUT', 'Log out'). "</a>";
|
||||||
} else {
|
} else {
|
||||||
$logInMessage = "Not logged in - <a href=\"Security/login\">log in</a>";
|
$logInMessage = _t('ContentController.NOTLOGGEDIN', 'Not logged in') ." - <a href='Security/login'>". _t('ContentController.LOGIN', 'Login') ."</a>";
|
||||||
}
|
}
|
||||||
|
$viewPageIn = _t('ContentController.VIEWPAGEIN', 'View Page in:');
|
||||||
/**
|
/**
|
||||||
* HGS: cmsLink is now only set if there is a dataRecord. You can't view the page in the
|
* HGS: cmsLink is now only set if there is a dataRecord. You can't view the page in the
|
||||||
* CMS if there is no dataRecord
|
* CMS if there is no dataRecord
|
||||||
@ -277,7 +277,7 @@ JS
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="switchView" class="bottomTabs">
|
<div id="switchView" class="bottomTabs">
|
||||||
<div class="blank"> View page in: </div>
|
<div class="blank">$viewPageIn </div>
|
||||||
$cmsLink
|
$cmsLink
|
||||||
$stageLink
|
$stageLink
|
||||||
<div class="blank" style="width:1em;"> </div>
|
<div class="blank" style="width:1em;"> </div>
|
||||||
@ -295,7 +295,7 @@ HTML;
|
|||||||
Requirements::css(SAPPHIRE_DIR . '/css/SilverStripeNavigator.css');
|
Requirements::css(SAPPHIRE_DIR . '/css/SilverStripeNavigator.css');
|
||||||
$dateObj = Object::create('Datetime', $date, null);
|
$dateObj = Object::create('Datetime', $date, null);
|
||||||
// $dateObj->setVal($date);
|
// $dateObj->setVal($date);
|
||||||
return "<div id=\"SilverStripeNavigatorMessage\">Archived site from<br>" . $dateObj->Nice() . "</div>";
|
return "<div id=\"SilverStripeNavigatorMessage\">". _t('ContentController.ARCHIVEDSITEFROM') ."<br>" . $dateObj->Nice() . "</div>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,5 +423,4 @@ HTML
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -112,7 +112,7 @@ class ContentNegotiator {
|
|||||||
|
|
||||||
// Only serve "pure" XHTML if the XML header is present
|
// Only serve "pure" XHTML if the XML header is present
|
||||||
if(substr($content,0,5) == '<' . '?xml' ) {
|
if(substr($content,0,5) == '<' . '?xml' ) {
|
||||||
$response->addHeader("Content-type", "application/xhtml+xml; charset=" . self::$encoding);
|
$response->addHeader("Content-Type", "application/xhtml+xml; charset=" . self::$encoding);
|
||||||
$response->addHeader("Vary" , "Accept");
|
$response->addHeader("Vary" , "Accept");
|
||||||
|
|
||||||
$content = str_replace(' ',' ', $content);
|
$content = str_replace(' ',' ', $content);
|
||||||
@ -134,7 +134,7 @@ class ContentNegotiator {
|
|||||||
* Removes "xmlns" attributes and any <?xml> Pragmas.
|
* Removes "xmlns" attributes and any <?xml> Pragmas.
|
||||||
*/
|
*/
|
||||||
function html(HTTPResponse $response) {
|
function html(HTTPResponse $response) {
|
||||||
$response->addHeader("Content-type", "text/html; charset=" . self::$encoding);
|
$response->addHeader("Content-Type", "text/html; charset=" . self::$encoding);
|
||||||
$response->addHeader("Vary", "Accept");
|
$response->addHeader("Vary", "Accept");
|
||||||
|
|
||||||
$content = $response->getBody();
|
$content = $response->getBody();
|
||||||
@ -174,6 +174,11 @@ class ContentNegotiator {
|
|||||||
* By default, negotiation is only enabled for pages that have the xml header.
|
* By default, negotiation is only enabled for pages that have the xml header.
|
||||||
*/
|
*/
|
||||||
static function enabled_for($response) {
|
static function enabled_for($response) {
|
||||||
|
$contentType = $response->getHeader("Content-Type");
|
||||||
|
|
||||||
|
// Disable content negotation for other content types
|
||||||
|
if($contentType && substr($contentType, 0,9) != 'text/html' && substr($contentType, 0,21) != 'application/xhtml+xml') return false;
|
||||||
|
|
||||||
if(self::$enabled) return true;
|
if(self::$enabled) return true;
|
||||||
else return (substr($response->getBody(),0,5) == '<' . '?xml');
|
else return (substr($response->getBody(),0,5) == '<' . '?xml');
|
||||||
}
|
}
|
||||||
|
@ -217,7 +217,7 @@ class HTTPRequest extends Object implements ArrayAccess {
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
function getURL() {
|
function getURL() {
|
||||||
return $this->url;
|
return ($this->getExtension()) ? $this->url . '.' . $this->getExtension() : $this->url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,7 @@ class RootURLController extends Controller {
|
|||||||
$controller = new ModelAsController();
|
$controller = new ModelAsController();
|
||||||
|
|
||||||
$request = new HTTPRequest("GET", self::get_homepage_urlsegment().'/', $request->getVars(), $request->postVars());
|
$request = new HTTPRequest("GET", self::get_homepage_urlsegment().'/', $request->getVars(), $request->postVars());
|
||||||
$request->match('$URLSegment//$Action');
|
$request->match('$URLSegment//$Action', true);
|
||||||
|
|
||||||
$result = $controller->handleRequest($request);
|
$result = $controller->handleRequest($request);
|
||||||
|
|
||||||
|
@ -965,15 +965,26 @@ class i18n extends Object {
|
|||||||
* Given a file name (a php class name, without the .php ext, or a template name, including the .ss extension)
|
* Given a file name (a php class name, without the .php ext, or a template name, including the .ss extension)
|
||||||
* this helper function determines the module where this file is located
|
* this helper function determines the module where this file is located
|
||||||
*
|
*
|
||||||
* @param string $name php class name or template file name
|
* @param string $name php class name or template file name (including *.ss extension)
|
||||||
* @return string Module where the file is located
|
* @return string Module where the file is located
|
||||||
*/
|
*/
|
||||||
public static function get_owner_module($name) {
|
public static function get_owner_module($name) {
|
||||||
if (substr($name,-3) == '.ss') {
|
// if $name is a template file
|
||||||
|
if(substr($name,-3) == '.ss') {
|
||||||
global $_TEMPLATE_MANIFEST;
|
global $_TEMPLATE_MANIFEST;
|
||||||
$path = str_replace('\\','/',Director::makeRelative(current($_TEMPLATE_MANIFEST[substr($name,0,-3)])));
|
$templateManifest = $_TEMPLATE_MANIFEST[substr($name,0,-3)];
|
||||||
|
if(is_array($templateManifest) && isset($templateManifest['themes'])) {
|
||||||
|
$absolutePath = $templateManifest['themes'][SSViewer::current_theme()];
|
||||||
|
} else {
|
||||||
|
$absolutePath = $templateManifest;
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = str_replace('\\','/',Director::makeRelative(current($absolutePath)));
|
||||||
|
|
||||||
ereg('/([^/]+)/',$path,$module);
|
ereg('/([^/]+)/',$path,$module);
|
||||||
} else {
|
}
|
||||||
|
// $name is assumed to be a PHP class
|
||||||
|
else {
|
||||||
global $_CLASS_MANIFEST;
|
global $_CLASS_MANIFEST;
|
||||||
if(strpos($name,'_') !== false) $name = strtok($name,'_');
|
if(strpos($name,'_') !== false) $name = strtok($name,'_');
|
||||||
if(isset($_CLASS_MANIFEST[$name])) {
|
if(isset($_CLASS_MANIFEST[$name])) {
|
||||||
@ -1076,6 +1087,7 @@ class i18n extends Object {
|
|||||||
$module = self::get_owner_module($class);
|
$module = self::get_owner_module($class);
|
||||||
|
|
||||||
if(!$module) user_error("i18n::include_by_class: Class {$class} not found", E_USER_WARNING);
|
if(!$module) user_error("i18n::include_by_class: Class {$class} not found", E_USER_WARNING);
|
||||||
|
$locale = self::get_locale();
|
||||||
|
|
||||||
if (file_exists($file = Director::getAbsFile("$module/lang/". self::get_locale() . '.php'))) {
|
if (file_exists($file = Director::getAbsFile("$module/lang/". self::get_locale() . '.php'))) {
|
||||||
include($file);
|
include($file);
|
||||||
@ -1088,6 +1100,12 @@ class i18n extends Object {
|
|||||||
} else if(file_exists(Director::getAbsFile("$module/lang"))) {
|
} else if(file_exists(Director::getAbsFile("$module/lang"))) {
|
||||||
user_error("i18n::include_by_class: Locale file $file should exist", E_USER_WARNING);
|
user_error("i18n::include_by_class: Locale file $file should exist", E_USER_WARNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the language file wasn't included for this class, include an empty array to prevent
|
||||||
|
// this method from being called again
|
||||||
|
global $lang;
|
||||||
|
if(!isset($lang[$locale][$class])) $lang[$locale][$class] = array();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------------------//
|
//-----------------------------------------------------------------------------------------------//
|
||||||
|
@ -44,6 +44,23 @@ interface i18nEntityProvider {
|
|||||||
*
|
*
|
||||||
* Example usage in {@link DataObject->provideI18nEntities()}.
|
* Example usage in {@link DataObject->provideI18nEntities()}.
|
||||||
*
|
*
|
||||||
|
* You can ask textcollector to add the provided entity to a different module
|
||||||
|
* than the class is contained in by adding a 4th argument to the array:
|
||||||
|
* <code>
|
||||||
|
* class MyTestClass implements i18nEntityProvider {
|
||||||
|
* function provideI18nEntities() {
|
||||||
|
* $entities = array();
|
||||||
|
* $entities["MyOtherModuleClass.MYENTITY"] = array(
|
||||||
|
* $value,
|
||||||
|
* PR_MEDIUM,
|
||||||
|
* 'My context description',
|
||||||
|
* 'myothermodule'
|
||||||
|
* );
|
||||||
|
* }
|
||||||
|
* return $entities;
|
||||||
|
* }
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
* @return array All entites in an associative array, with
|
* @return array All entites in an associative array, with
|
||||||
* entity name as the key, and a numerical array of pseudo-arguments
|
* entity name as the key, and a numerical array of pseudo-arguments
|
||||||
* for _t() as a value.
|
* for _t() as a value.
|
||||||
|
@ -110,6 +110,16 @@ class i18nTextCollector extends Object {
|
|||||||
unset($entitiesByModule[$module][$fullName]);
|
unset($entitiesByModule[$module][$fullName]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extract all entities for "foreign" modules (fourth argument)
|
||||||
|
foreach($entitiesByModule[$module] as $fullName => $spec) {
|
||||||
|
if(isset($spec[3]) && $spec[3] != $module) {
|
||||||
|
$othermodule = $spec[3];
|
||||||
|
if(!isset($entitiesByModule[$othermodule])) $entitiesByModule[$othermodule] = array();
|
||||||
|
unset($spec[3]);
|
||||||
|
$entitiesByModule[$othermodule][$fullName] = $spec;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the generated master string tables
|
// Write the generated master string tables
|
||||||
|
@ -1581,7 +1581,7 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
|
|||||||
* Used for simple frontend forms without relation editing
|
* Used for simple frontend forms without relation editing
|
||||||
* or {@link TabSet} behaviour. Uses {@link scaffoldFormFields()}
|
* or {@link TabSet} behaviour. Uses {@link scaffoldFormFields()}
|
||||||
* by default. To customize, either overload this method in your
|
* by default. To customize, either overload this method in your
|
||||||
* subclass, or decorate it by {@link DataObjectDecorator->updateFormFields()}.
|
* subclass, or decorate it by {@link DataObjectDecorator->updateFrontEndFields()}.
|
||||||
*
|
*
|
||||||
* @todo Decide on naming for "website|frontend|site|page" and stick with it in the API
|
* @todo Decide on naming for "website|frontend|site|page" and stick with it in the API
|
||||||
*
|
*
|
||||||
@ -1590,7 +1590,7 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
|
|||||||
*/
|
*/
|
||||||
public function getFrontEndFields($params = null) {
|
public function getFrontEndFields($params = null) {
|
||||||
$untabbedFields = $this->scaffoldFormFields($params);
|
$untabbedFields = $this->scaffoldFormFields($params);
|
||||||
$this->extend('updateFormFields', $untabbedFields);
|
$this->extend('updateFrontEndFields', $untabbedFields);
|
||||||
|
|
||||||
return $untabbedFields;
|
return $untabbedFields;
|
||||||
}
|
}
|
||||||
@ -1836,7 +1836,10 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
|
|||||||
* Uses the rules for whether the table should exist rather than actually looking in the database.
|
* Uses the rules for whether the table should exist rather than actually looking in the database.
|
||||||
*/
|
*/
|
||||||
public function has_own_table($dataClass) {
|
public function has_own_table($dataClass) {
|
||||||
if(!is_subclass_of($dataClass,'DataObject')) return false;
|
// The condition below has the same effect as !is_subclass_of($dataClass,'DataObject'),
|
||||||
|
// which causes PHP < 5.3 to segfault in rare circumstances, see PHP bug #46753
|
||||||
|
if($dataClass == 'DataObject' || !in_array('DataObject', ClassInfo::ancestry($dataClass))) return false;
|
||||||
|
|
||||||
if(!isset(self::$cache_has_own_table[$dataClass])) {
|
if(!isset(self::$cache_has_own_table[$dataClass])) {
|
||||||
if(get_parent_class($dataClass) == 'DataObject') {
|
if(get_parent_class($dataClass) == 'DataObject') {
|
||||||
self::$cache_has_own_table[$dataClass] = true;
|
self::$cache_has_own_table[$dataClass] = true;
|
||||||
@ -2736,7 +2739,7 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
|
|||||||
$fields = array();
|
$fields = array();
|
||||||
// try to scaffold a couple of usual suspects
|
// try to scaffold a couple of usual suspects
|
||||||
if ($this->hasField('Name')) $fields['Name'] = 'Name';
|
if ($this->hasField('Name')) $fields['Name'] = 'Name';
|
||||||
if ($this->hasField('Title')) $fields['Title'] = 'Title';
|
if ($this->hasDataBaseField('Title')) $fields['Title'] = 'Title';
|
||||||
if ($this->hasField('Description')) $fields['Description'] = 'Description';
|
if ($this->hasField('Description')) $fields['Description'] = 'Description';
|
||||||
if ($this->hasField('FirstName')) $fields['FirstName'] = 'First Name';
|
if ($this->hasField('FirstName')) $fields['FirstName'] = 'First Name';
|
||||||
}
|
}
|
||||||
@ -2848,7 +2851,7 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
|
|||||||
/**
|
/**
|
||||||
* Inserts standard column-values when a DataObject
|
* Inserts standard column-values when a DataObject
|
||||||
* is instanciated. Does not insert default records {@see $default_records}.
|
* is instanciated. Does not insert default records {@see $default_records}.
|
||||||
* This is a map from classname to default value.
|
* This is a map from fieldname to default value.
|
||||||
*
|
*
|
||||||
* - If you would like to change a default value in a sub-class, just specify it.
|
* - If you would like to change a default value in a sub-class, just specify it.
|
||||||
* - If you would like to disable the default value given by a parent class, set the default value to 0,'',or false in your
|
* - If you would like to disable the default value given by a parent class, set the default value to 0,'',or false in your
|
||||||
|
@ -57,7 +57,6 @@ abstract class DataObjectDecorator extends Extension {
|
|||||||
return $this->loadExtraStatics();
|
return $this->loadExtraStatics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit the given query object to support queries for this extension
|
* Edit the given query object to support queries for this extension
|
||||||
*
|
*
|
||||||
@ -66,7 +65,6 @@ abstract class DataObjectDecorator extends Extension {
|
|||||||
function augmentSQL(SQLQuery &$query) {
|
function augmentSQL(SQLQuery &$query) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the database schema as required by this extension.
|
* Update the database schema as required by this extension.
|
||||||
*/
|
*/
|
||||||
@ -139,7 +137,8 @@ abstract class DataObjectDecorator extends Extension {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is used to provide modifications to the form in the CMS
|
* This function is used to provide modifications to the form in the CMS
|
||||||
* by the decorator. By default, no changes are made.
|
* by the decorator. By default, no changes are made. {@link DataObject->getCMSFields()}.
|
||||||
|
*
|
||||||
* Please consider using {@link updateFormFields()} to globally add
|
* Please consider using {@link updateFormFields()} to globally add
|
||||||
* formfields to the record. The method {@link updateCMSFields()}
|
* formfields to the record. The method {@link updateCMSFields()}
|
||||||
* should just be used to add or modify tabs, or fields which
|
* should just be used to add or modify tabs, or fields which
|
||||||
@ -153,16 +152,22 @@ abstract class DataObjectDecorator extends Extension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is used to provide modifications to the form in the CMS
|
* This function is used to provide modifications to the form used
|
||||||
* by the decorator.
|
* for front end forms. {@link DataObject->getFrontEndFields()}
|
||||||
*
|
*
|
||||||
* Caution: Use {@link FieldSet->push()} to add fields.
|
* Caution: Use {@link FieldSet->push()} to add fields.
|
||||||
*
|
*
|
||||||
* @param FieldSet $fields FieldSet without TabSet nesting
|
* @param FieldSet $fields FieldSet without TabSet nesting
|
||||||
*/
|
*/
|
||||||
function updateFormFields(FieldSet &$fields) {
|
function updateFrontEndFields(FieldSet &$fields) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is used to provide modifications to the form actions
|
||||||
|
* used in the CMS. {@link DataObject->getCMSActions()}.
|
||||||
|
*
|
||||||
|
* @param FieldSet $actions FieldSet
|
||||||
|
*/
|
||||||
function updateCMSActions(FieldSet &$actions) {
|
function updateCMSActions(FieldSet &$actions) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,6 +181,12 @@ abstract class DataObjectDecorator extends Extension {
|
|||||||
$extra_fields = $this->extraStatics();
|
$extra_fields = $this->extraStatics();
|
||||||
if(isset($extra_fields['summary_fields'])){
|
if(isset($extra_fields['summary_fields'])){
|
||||||
$summary_fields = $extra_fields['summary_fields'];
|
$summary_fields = $extra_fields['summary_fields'];
|
||||||
|
|
||||||
|
// if summary_fields were passed in numeric array,
|
||||||
|
// convert to an associative array
|
||||||
|
if($summary_fields && array_key_exists(0, $summary_fields)) {
|
||||||
|
$summary_fields = array_combine(array_values($summary_fields), array_values($summary_fields));
|
||||||
|
}
|
||||||
if($summary_fields) $fields = array_merge($fields, $summary_fields);
|
if($summary_fields) $fields = array_merge($fields, $summary_fields);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,5 +212,4 @@ abstract class DataObjectDecorator extends Extension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
@ -264,6 +264,85 @@ class DataObjectSet extends ViewableData implements IteratorAggregate {
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display a summarized pagination which limits the number of pages shown
|
||||||
|
* "around" the currently active page for visual balance.
|
||||||
|
* In case more paginated pages have to be displayed, only
|
||||||
|
*
|
||||||
|
* Example: 25 pages total, currently on page 6, context of 4 pages
|
||||||
|
* [prev] [1] ... [4] [5] [[6]] [7] [8] ... [25] [next]
|
||||||
|
*
|
||||||
|
* Example template usage:
|
||||||
|
* <code>
|
||||||
|
* <% if MyPages.MoreThanOnePage %>
|
||||||
|
* <% if MyPages.NotFirstPage %>
|
||||||
|
* <a class="prev" href="$MyPages.PrevLink">Prev</a>
|
||||||
|
* <% end_if %>
|
||||||
|
* <% control MyPages.PaginationSummary(4) %>
|
||||||
|
* <% if CurrentBool %>
|
||||||
|
* $PageNum
|
||||||
|
* <% else %>
|
||||||
|
* <% if Link %>
|
||||||
|
* <a href="$Link">$PageNum</a>
|
||||||
|
* <% else %>
|
||||||
|
* ...
|
||||||
|
* <% end_if %>
|
||||||
|
* <% end_if %>
|
||||||
|
* <% end_control %>
|
||||||
|
* <% if MyPages.NotLastPage %>
|
||||||
|
* <a class="next" href="$MyPages.NextLink">Next</a>
|
||||||
|
* <% end_if %>
|
||||||
|
* <% end_if %>
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @param integer $context Number of pages to display "around" the current page. Number should be even,
|
||||||
|
* because its halved to either side of the current page.
|
||||||
|
* @return DataObjectSet
|
||||||
|
*/
|
||||||
|
public function PaginationSummary($context = 4) {
|
||||||
|
$ret = new DataObjectSet();
|
||||||
|
|
||||||
|
// convert number of pages to even number for offset calculation
|
||||||
|
if($context % 2) $context--;
|
||||||
|
|
||||||
|
// find out the offset
|
||||||
|
$current = $this->CurrentPage();
|
||||||
|
$totalPages = $this->TotalPages();
|
||||||
|
|
||||||
|
// if the first or last page is shown, use all content on one side (either left or right of current page)
|
||||||
|
// otherwise half the number for usage "around" the current page
|
||||||
|
$offset = ($current == 1 || $current == $totalPages) ? $context : floor($context/2);
|
||||||
|
|
||||||
|
$leftOffset = $current - ($offset);
|
||||||
|
if($leftOffset < 1) $leftOffset = 1;
|
||||||
|
if($leftOffset + $context > $totalPages) $leftOffset = $totalPages - $context;
|
||||||
|
|
||||||
|
for($i=0; $i < $totalPages; $i++) {
|
||||||
|
$link = HTTP::setGetVar($this->paginationGetVar, $i*$this->pageLength);
|
||||||
|
$num = $i+1;
|
||||||
|
$currentBool = ($current == $i+1) ? true:false;
|
||||||
|
if(
|
||||||
|
($num == $leftOffset-1 && $num != 1 && $num != $totalPages)
|
||||||
|
|| ($num == $leftOffset+$context+1 && $num != 1 && $num != $totalPages)
|
||||||
|
) {
|
||||||
|
$ret->push(new ArrayData(array(
|
||||||
|
"PageNum" => null,
|
||||||
|
"Link" => null,
|
||||||
|
"CurrentBool" => $currentBool,
|
||||||
|
)
|
||||||
|
));
|
||||||
|
} else if($num == 1 || $num == $totalPages || in_array($num, range($current-$offset,$current+$offset))) {
|
||||||
|
$ret->push(new ArrayData(array(
|
||||||
|
"PageNum" => $num,
|
||||||
|
"Link" => $link,
|
||||||
|
"CurrentBool" => $currentBool,
|
||||||
|
)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the current page is not the first page.
|
* Returns true if the current page is not the first page.
|
||||||
* @return boolean
|
* @return boolean
|
||||||
@ -694,7 +773,7 @@ class DataObjectSet extends ViewableData implements IteratorAggregate {
|
|||||||
$myViewer = SSViewer::fromString($currentTemplate);
|
$myViewer = SSViewer::fromString($currentTemplate);
|
||||||
|
|
||||||
if(isset($nestingLevels[$level+1]['dataclass'])){
|
if(isset($nestingLevels[$level+1]['dataclass'])){
|
||||||
$childrenMethod = $nestingLevels[$level+1]['dataclass'];if($level==1){print_r($childrenMethod);die;}
|
$childrenMethod = $nestingLevels[$level+1]['dataclass'];
|
||||||
}
|
}
|
||||||
// sql-parts
|
// sql-parts
|
||||||
|
|
||||||
|
@ -236,6 +236,8 @@ abstract class Database extends Object {
|
|||||||
$this->checkAndRepairTable($table);
|
$this->checkAndRepairTable($table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->requireField($table, "ID", "int(11) not null auto_increment");
|
||||||
|
|
||||||
// Create custom fields
|
// Create custom fields
|
||||||
if($fieldSchema) {
|
if($fieldSchema) {
|
||||||
foreach($fieldSchema as $fieldName => $fieldSpec) {
|
foreach($fieldSchema as $fieldName => $fieldSpec) {
|
||||||
@ -591,10 +593,11 @@ abstract class Query extends Object implements Iterator {
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function column() {
|
public function column() {
|
||||||
|
$column = array();
|
||||||
foreach($this as $record) {
|
foreach($this as $record) {
|
||||||
$column[] = reset($record);
|
$column[] = reset($record);
|
||||||
}
|
}
|
||||||
return isset($column) ? $column : null;
|
return $column;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -603,6 +606,7 @@ abstract class Query extends Object implements Iterator {
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function keyedColumn() {
|
public function keyedColumn() {
|
||||||
|
$column = array();
|
||||||
foreach($this as $record) {
|
foreach($this as $record) {
|
||||||
$val = reset($record);
|
$val = reset($record);
|
||||||
$column[$val] = $val;
|
$column[$val] = $val;
|
||||||
@ -615,6 +619,7 @@ abstract class Query extends Object implements Iterator {
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function map() {
|
public function map() {
|
||||||
|
$column = array();
|
||||||
foreach($this as $record) {
|
foreach($this as $record) {
|
||||||
$key = reset($record);
|
$key = reset($record);
|
||||||
$val = next($record);
|
$val = next($record);
|
||||||
|
@ -103,6 +103,7 @@ class ErrorPage extends Page {
|
|||||||
|
|
||||||
$errorContent = $response->getBody();
|
$errorContent = $response->getBody();
|
||||||
|
|
||||||
|
// Check we have an assets base directory, creating if it we don't
|
||||||
if(!file_exists(ASSETS_PATH)) {
|
if(!file_exists(ASSETS_PATH)) {
|
||||||
mkdir(ASSETS_PATH, 02775);
|
mkdir(ASSETS_PATH, 02775);
|
||||||
}
|
}
|
||||||
@ -113,6 +114,17 @@ class ErrorPage extends Page {
|
|||||||
if($fh = fopen($filePath, "w")) {
|
if($fh = fopen($filePath, "w")) {
|
||||||
fwrite($fh, $errorContent);
|
fwrite($fh, $errorContent);
|
||||||
fclose($fh);
|
fclose($fh);
|
||||||
|
} else {
|
||||||
|
$fileErrorText = sprintf(
|
||||||
|
_t(
|
||||||
|
"ErrorPage.ERRORFILEPROBLEM",
|
||||||
|
"Error opening file \"%s\" for writing. Please check file permissions."
|
||||||
|
),
|
||||||
|
$errorFile
|
||||||
|
);
|
||||||
|
FormResponse::status_message($fileErrorText, 'bad');
|
||||||
|
FormResponse::respond();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the version we're currently connected to.
|
// Restore the version we're currently connected to.
|
||||||
|
@ -159,7 +159,7 @@ class Hierarchy extends DataObjectDecorator {
|
|||||||
protected function markingFinished() {
|
protected function markingFinished() {
|
||||||
// Mark childless nodes as expanded.
|
// Mark childless nodes as expanded.
|
||||||
foreach($this->markedNodes as $id => $node) {
|
foreach($this->markedNodes as $id => $node) {
|
||||||
if(!$node->numChildren()) {
|
if(!$node->isExpanded() && !$node->numChildren()) {
|
||||||
$node->markExpanded();
|
$node->markExpanded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,7 +351,18 @@ class Hierarchy extends DataObjectDecorator {
|
|||||||
* @return DataObjectSet
|
* @return DataObjectSet
|
||||||
*/
|
*/
|
||||||
public function Children() {
|
public function Children() {
|
||||||
return $this->owner->stageChildren(false);
|
if(!(isset($this->children) && $this->children)) {
|
||||||
|
$result = $this->owner->stageChildren(false);
|
||||||
|
if(isset($result)) {
|
||||||
|
$this->children = new DataObjectSet();
|
||||||
|
foreach($result as $child) {
|
||||||
|
if($child->canView()) {
|
||||||
|
$this->children->push($child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this->children;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,11 +174,12 @@ class MySQLDatabase extends Database {
|
|||||||
|
|
||||||
public function createTable($tableName, $fields = null, $indexes = null) {
|
public function createTable($tableName, $fields = null, $indexes = null) {
|
||||||
$fieldSchemas = $indexSchemas = "";
|
$fieldSchemas = $indexSchemas = "";
|
||||||
|
|
||||||
|
if(!isset($fields['ID'])) $fields['ID'] = "int(11) not null auto_increment";
|
||||||
if($fields) foreach($fields as $k => $v) $fieldSchemas .= "\"$k\" $v,\n";
|
if($fields) foreach($fields as $k => $v) $fieldSchemas .= "\"$k\" $v,\n";
|
||||||
if($indexes) foreach($indexes as $k => $v) $fieldSchemas .= $this->getIndexSqlDefinition($k, $v) . ",\n";
|
if($indexes) foreach($indexes as $k => $v) $fieldSchemas .= $this->getIndexSqlDefinition($k, $v) . ",\n";
|
||||||
|
|
||||||
$this->query("CREATE TABLE \"$tableName\" (
|
$this->query("CREATE TABLE \"$tableName\" (
|
||||||
ID int(11) not null auto_increment,
|
|
||||||
$fieldSchemas
|
$fieldSchemas
|
||||||
$indexSchemas
|
$indexSchemas
|
||||||
primary key (ID)
|
primary key (ID)
|
||||||
@ -468,7 +469,7 @@ class MySQLDatabase extends Database {
|
|||||||
//$parts=Array('datatype'=>'decimal', 'precision'=>"$this->wholeSize,$this->decimalSize");
|
//$parts=Array('datatype'=>'decimal', 'precision'=>"$this->wholeSize,$this->decimalSize");
|
||||||
//DB::requireField($this->tableName, $this->name, "decimal($this->wholeSize,$this->decimalSize)");
|
//DB::requireField($this->tableName, $this->name, "decimal($this->wholeSize,$this->decimalSize)");
|
||||||
|
|
||||||
return 'decimal(' . (int)$values['precision'] . ')';
|
return 'decimal(' . (int)$values['precision'] . ') not null';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -727,5 +727,4 @@ class PDOQuery extends Query {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -191,6 +191,42 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
*/
|
*/
|
||||||
private static $runCMSFieldsExtensions = true;
|
private static $runCMSFieldsExtensions = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a subclass map of SiteTree
|
||||||
|
* that shouldn't be hidden through
|
||||||
|
* {@link SiteTree::$hide_ancestor}
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function page_type_classes() {
|
||||||
|
$classes = ClassInfo::getValidSubClasses();
|
||||||
|
array_shift($classes);
|
||||||
|
$kill_ancestors = array();
|
||||||
|
|
||||||
|
// figure out if there are any classes we don't want to appear
|
||||||
|
foreach($classes as $class) {
|
||||||
|
$instance = singleton($class);
|
||||||
|
|
||||||
|
// do any of the progeny want to hide an ancestor?
|
||||||
|
if($ancestor_to_hide = $instance->stat('hide_ancestor')) {
|
||||||
|
// note for killing later
|
||||||
|
$kill_ancestors[] = $ancestor_to_hide;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any of the descendents don't want any of the elders to show up, cruelly render the elders surplus to requirements.
|
||||||
|
if($kill_ancestors) {
|
||||||
|
$kill_ancestors = array_unique($kill_ancestors);
|
||||||
|
foreach($kill_ancestors as $mark) {
|
||||||
|
// unset from $classes
|
||||||
|
$idx = array_search($mark, $classes);
|
||||||
|
unset($classes[$idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $classes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the URL for this page.
|
* Get the URL for this page.
|
||||||
*
|
*
|
||||||
@ -525,7 +561,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
* @todo Check we get a endless recursion if we use parent::can()
|
* @todo Check we get a endless recursion if we use parent::can()
|
||||||
*/
|
*/
|
||||||
function can($perm, $member = null) {
|
function can($perm, $member = null) {
|
||||||
if(!$member && $member !== FALSE) $member = Member::currentUser();
|
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) $member = Member::currentUser();
|
||||||
|
|
||||||
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
||||||
|
|
||||||
@ -562,7 +598,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
* @return boolean True if the current user can add children.
|
* @return boolean True if the current user can add children.
|
||||||
*/
|
*/
|
||||||
public function canAddChildren($member = null) {
|
public function canAddChildren($member = null) {
|
||||||
if(!$member && $member !== FALSE) $member = Member::currentUser();
|
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) $member = Member::currentUser();
|
||||||
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
||||||
|
|
||||||
// DEPRECATED 2.3: use canAddChildren() instead
|
// DEPRECATED 2.3: use canAddChildren() instead
|
||||||
@ -593,7 +629,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
* @return boolean True if the current user can view this page.
|
* @return boolean True if the current user can view this page.
|
||||||
*/
|
*/
|
||||||
public function canView($member = null) {
|
public function canView($member = null) {
|
||||||
if(!$member && $member !== FALSE) $member = Member::currentUser();
|
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) $member = Member::currentUser();
|
||||||
|
|
||||||
// admin override
|
// admin override
|
||||||
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
||||||
@ -648,7 +684,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
* @return boolean True if the current user can delete this page.
|
* @return boolean True if the current user can delete this page.
|
||||||
*/
|
*/
|
||||||
public function canDelete($member = null) {
|
public function canDelete($member = null) {
|
||||||
if(!$member && $member !== FALSE) $member = Member::currentUser();
|
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) $member = Member::currentUser();
|
||||||
|
|
||||||
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
||||||
|
|
||||||
@ -690,7 +726,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
* @return boolean True if the current user can create pages on this class.
|
* @return boolean True if the current user can create pages on this class.
|
||||||
*/
|
*/
|
||||||
public function canCreate($member = null) {
|
public function canCreate($member = null) {
|
||||||
if(!$member && $member !== FALSE) $member = Member::currentUser();
|
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) $member = Member::currentUser();
|
||||||
|
|
||||||
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
||||||
|
|
||||||
@ -726,7 +762,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
* @return boolean True if the current user can edit this page.
|
* @return boolean True if the current user can edit this page.
|
||||||
*/
|
*/
|
||||||
public function canEdit($member = null) {
|
public function canEdit($member = null) {
|
||||||
if(!$member && $member !== FALSE) $member = Member::currentUser();
|
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) $member = Member::currentUser();
|
||||||
|
|
||||||
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
||||||
|
|
||||||
@ -774,7 +810,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
* @return boolean True if the current user can publish this page.
|
* @return boolean True if the current user can publish this page.
|
||||||
*/
|
*/
|
||||||
public function canPublish($member = null) {
|
public function canPublish($member = null) {
|
||||||
if(!$member && $member !== FALSE) $member = Member::currentUser();
|
if(!$member || !(is_a($member, 'Member')) || is_numeric($member)) $member = Member::currentUser();
|
||||||
|
|
||||||
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
if($member && Permission::checkMember($member, "ADMIN")) return true;
|
||||||
|
|
||||||
@ -816,7 +852,6 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
/**
|
/**
|
||||||
* Return the title, description, keywords and language metatags.
|
* Return the title, description, keywords and language metatags.
|
||||||
*
|
*
|
||||||
* @todo Make generator tag dynamically determine version number (currently defaults to "2.0")
|
|
||||||
* @todo Move <title> tag in separate getter for easier customization and more obvious usage
|
* @todo Move <title> tag in separate getter for easier customization and more obvious usage
|
||||||
*
|
*
|
||||||
* @param boolean|string $includeTitle Show default <title>-tag, set to false for custom templating
|
* @param boolean|string $includeTitle Show default <title>-tag, set to false for custom templating
|
||||||
@ -831,7 +866,9 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
? $this->MetaTitle
|
? $this->MetaTitle
|
||||||
: $this->Title) . "</title>\n";
|
: $this->Title) . "</title>\n";
|
||||||
}
|
}
|
||||||
$tags .= "<meta name=\"generator\" http-equiv=\"generator\" content=\"SilverStripe - http://www.silverstripe.com\" />\n";
|
$version = new SapphireInfo();
|
||||||
|
|
||||||
|
$tags .= "<meta name=\"generator\" http-equiv=\"generator\" content=\"SilverStripe ". $version->Version() ." - http://www.silverstripe.com\" />\n";
|
||||||
|
|
||||||
$charset = ContentNegotiator::get_encoding();
|
$charset = ContentNegotiator::get_encoding();
|
||||||
$tags .= "<meta http-equiv=\"Content-type\" content=\"text/html; charset=$charset\" />\n";
|
$tags .= "<meta http-equiv=\"Content-type\" content=\"text/html; charset=$charset\" />\n";
|
||||||
@ -1076,26 +1113,6 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
Requirements::javascript(CMS_DIR . "/javascript/SitetreeAccess.js");
|
Requirements::javascript(CMS_DIR . "/javascript/SitetreeAccess.js");
|
||||||
Requirements::javascript(SAPPHIRE_DIR . '/javascript/UpdateURL.js');
|
Requirements::javascript(SAPPHIRE_DIR . '/javascript/UpdateURL.js');
|
||||||
|
|
||||||
// Backlink report
|
|
||||||
if($this->hasMethod('BackLinkTracking')) {
|
|
||||||
$links = $this->BackLinkTracking();
|
|
||||||
|
|
||||||
if($links->exists()) {
|
|
||||||
foreach($links as $link) {
|
|
||||||
$backlinks[] = "<li><a class=\"cmsEditlink\" href=\"admin/show/$link->ID\">" .
|
|
||||||
$link->Breadcrumbs(null,true) . "</a></li>";
|
|
||||||
}
|
|
||||||
$backlinks = "<div style=\"clear:left\">
|
|
||||||
" . _t('SiteTree.PAGESLINKING', 'The following pages link to this page:') .
|
|
||||||
"<ul>" . implode("",$backlinks) . "</ul></div>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!isset($backlinks)) {
|
|
||||||
$backlinks = "<p>" . _t('SiteTree.NOBACKLINKS', 'This page hasn\'t been linked to from any pages.') . "</p>";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Status / message
|
// Status / message
|
||||||
// Create a status message for multiple parents
|
// Create a status message for multiple parents
|
||||||
if($this->ID && is_numeric($this->ID)) {
|
if($this->ID && is_numeric($this->ID)) {
|
||||||
@ -1139,18 +1156,37 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
$message .= "NOTE: " . implode("<br />", $statusMessage);
|
$message .= "NOTE: " . implode("<br />", $statusMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$backLinksNote = '';
|
||||||
|
$backLinksTable = new LiteralField('BackLinksNote', '<p>' . _t('NOBACKLINKEDPAGES', 'There are no pages linked to this page.') . '</p>');
|
||||||
|
|
||||||
|
// Create a table for showing pages linked to this one
|
||||||
|
if($this->BackLinkTracking() && $this->BackLinkTracking()->Count() > 0) {
|
||||||
|
$backLinksNote = new LiteralField('BackLinksNote', '<p>' . _t('SiteTree.PAGESLINKING', 'The following pages link to this page:') . '</p>');
|
||||||
|
$backLinksTable = new TableListField(
|
||||||
|
'BackLinkTracking',
|
||||||
|
'SiteTree',
|
||||||
|
array(
|
||||||
|
'Title' => 'Title'
|
||||||
|
),
|
||||||
|
'ChildID = ' . $this->ID,
|
||||||
|
'',
|
||||||
|
'LEFT JOIN SiteTree_LinkTracking ON SiteTree.ID = SiteTree_LinkTracking.SiteTreeID'
|
||||||
|
);
|
||||||
|
$backLinksTable->setFieldFormatting(array(
|
||||||
|
'Title' => '<a href=\"admin/show/$ID\">$Title</a>'
|
||||||
|
));
|
||||||
|
$backLinksTable->setPermissions(array(
|
||||||
|
'show',
|
||||||
|
'export'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// Lay out the fields
|
// Lay out the fields
|
||||||
$fields = new FieldSet(
|
$fields = new FieldSet(
|
||||||
new TabSet("Root",
|
new TabSet("Root",
|
||||||
$tabContent = new TabSet('Content',
|
$tabContent = new TabSet('Content',
|
||||||
$tabMain = new Tab('Main',
|
$tabMain = new Tab('Main',
|
||||||
new TextField("Title", $this->fieldLabel('Title')),
|
new TextField("Title", $this->fieldLabel('Title')),
|
||||||
/*new UniqueTextField("Title",
|
|
||||||
"Title",
|
|
||||||
"SiteTree",
|
|
||||||
"Another page is using that name. Page names should be unique.",
|
|
||||||
"Page Name"
|
|
||||||
),*/
|
|
||||||
new TextField("MenuTitle", $this->fieldLabel('MenuTitle')),
|
new TextField("MenuTitle", $this->fieldLabel('MenuTitle')),
|
||||||
new HtmlEditorField("Content", _t('SiteTree.HTMLEDITORTITLE', "Content", PR_MEDIUM, 'HTML editor title'))
|
new HtmlEditorField("Content", _t('SiteTree.HTMLEDITORTITLE', "Content", PR_MEDIUM, 'HTML editor title'))
|
||||||
),
|
),
|
||||||
@ -1206,8 +1242,9 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
new TextareaField("ToDo", "")
|
new TextareaField("ToDo", "")
|
||||||
),
|
),
|
||||||
$tabReports = new TabSet('Reports',
|
$tabReports = new TabSet('Reports',
|
||||||
$tabBacklinks =new Tab('Backlinks',
|
$tabBacklinks = new Tab('Backlinks',
|
||||||
new LiteralField("Backlinks", $backlinks)
|
$backLinksNote,
|
||||||
|
$backLinksTable
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
$tabAccess = new Tab('Access',
|
$tabAccess = new Tab('Access',
|
||||||
@ -1496,10 +1533,9 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function getClassDropdown() {
|
protected function getClassDropdown() {
|
||||||
$classes = ClassInfo::getValidSubClasses('SiteTree');
|
$classes = self::page_type_classes();
|
||||||
array_shift($classes);
|
|
||||||
|
|
||||||
$currentClass = null;
|
$currentClass = null;
|
||||||
|
$result = array();
|
||||||
|
|
||||||
$result = array();
|
$result = array();
|
||||||
foreach($classes as $class) {
|
foreach($classes as $class) {
|
||||||
|
@ -617,6 +617,27 @@ class Versioned extends DataObjectDecorator {
|
|||||||
return $version;
|
return $version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-populate the cache for Versioned::get_versionnumber_by_stage() for a list of record IDs,
|
||||||
|
* for more efficient database querying. If $idList is null, then every page will be pre-cached.
|
||||||
|
*/
|
||||||
|
static function prepopulate_versionnumber_cache($class, $stage, $idList = null) {
|
||||||
|
$filter = "";
|
||||||
|
if($idList) {
|
||||||
|
// Validate the ID list
|
||||||
|
foreach($idList as $id) if(!is_numeric($id)) user_error("Bad ID passed to Versioned::prepopulate_versionnumber_cache() in \$idList: " . $id, E_USER_ERROR);
|
||||||
|
$filter = "WHERE ID IN(" .implode(", ", $idList) . ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
$baseClass = ClassInfo::baseDataClass($class);
|
||||||
|
$stageTable = ($stage == 'Stage') ? $baseClass : "{$baseClass}_{$stage}";
|
||||||
|
|
||||||
|
$versions = DB::query("SELECT ID, Version FROM `$stageTable` $filter")->map();
|
||||||
|
foreach($versions as $id => $version) {
|
||||||
|
self::$cache_versionnumber[$baseClass][$stage][$id] = $version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a set of class instances by the given stage.
|
* Get a set of class instances by the given stage.
|
||||||
*
|
*
|
||||||
|
@ -64,7 +64,8 @@ abstract class DBField extends ViewableData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of this field
|
* Returns the name of this field.
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
function getName() {
|
function getName() {
|
||||||
return $this->name;
|
return $this->name;
|
||||||
|
@ -43,6 +43,10 @@ class Decimal extends DBField {
|
|||||||
return new NumericField($this->name, $title);
|
return new NumericField($this->name, $title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function nullValue() {
|
||||||
|
return "0.00";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an encoding of the given value suitable for inclusion in a SQL statement.
|
* Return an encoding of the given value suitable for inclusion in a SQL statement.
|
||||||
* If necessary, this should include quotes.
|
* If necessary, this should include quotes.
|
||||||
|
@ -6,6 +6,10 @@
|
|||||||
*/
|
*/
|
||||||
class SSDatetime extends Date {
|
class SSDatetime extends Date {
|
||||||
function setValue($value) {
|
function setValue($value) {
|
||||||
|
// Default to NZ date format - strtotime expects a US date
|
||||||
|
if(ereg('^([0-9]+)/([0-9]+)/([0-9]+)$', $value, $parts))
|
||||||
|
$value = "$parts[2]/$parts[1]/$parts[3]";
|
||||||
|
|
||||||
if($value) $this->value = date('Y-m-d H:i:s', strtotime($value));
|
if($value) $this->value = date('Y-m-d H:i:s', strtotime($value));
|
||||||
else $value = null;
|
else $value = null;
|
||||||
}
|
}
|
||||||
|
@ -50,10 +50,6 @@ class Varchar extends DBField {
|
|||||||
return str_replace("\n", '\par ', $this->value);
|
return str_replace("\n", '\par ', $this->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*function forTemplate() {
|
|
||||||
return $this->raw2HTML();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
function LimitCharacters($limit = 20, $add = "...") {
|
function LimitCharacters($limit = 20, $add = "...") {
|
||||||
$value = trim($this->value);
|
$value = trim($this->value);
|
||||||
return (strlen($value) > $limit) ? substr($value, 0, $limit) . $add : $value;
|
return (strlen($value) > $limit) ? substr($value, 0, $limit) . $add : $value;
|
||||||
|
@ -9,6 +9,10 @@
|
|||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#SiteTreeFilterDate {
|
||||||
|
width: 68px;
|
||||||
|
}
|
||||||
|
|
||||||
.calendardate img {
|
.calendardate img {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
@ -17,11 +21,16 @@
|
|||||||
|
|
||||||
.calendarpopup {
|
.calendarpopup {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 13.6em;
|
left: 9em;
|
||||||
|
_left: 1.3em;
|
||||||
top: -0.15em;
|
top: -0.15em;
|
||||||
|
_top: 4em;
|
||||||
display: none;
|
display: none;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.calendarpopup.focused {
|
.calendarpopup.focused {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
html,body {
|
|
||||||
overflow:auto !important;
|
|
||||||
background: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ComplexTableField_popup {
|
.ComplexTableField_popup {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
overflow-y: auto !important;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
#ComplexTableField_Popup_DetailForm input.loading {
|
#ComplexTableField_Popup_DetailForm input.loading {
|
||||||
background: #fff url(../../cms/images/network-save.gif) left center no-repeat;
|
background: #fff url(../../cms/images/network-save.gif) left center no-repeat;
|
||||||
padding-left:16px;
|
padding-left: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.PageControls {
|
.PageControls {
|
||||||
|
20
css/Form.css
20
css/Form.css
@ -138,3 +138,23 @@ form .message {
|
|||||||
width:240px;
|
width:240px;
|
||||||
border-color: #FF4040;
|
border-color: #FF4040;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** LOGIN FORM **/
|
||||||
|
|
||||||
|
#Remember {
|
||||||
|
margin: 0.5em 0 0.5em 11em !important;
|
||||||
|
}
|
||||||
|
p#Remember label {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
#Remember input {
|
||||||
|
float: left;
|
||||||
|
margin: 0 5px 0 0;
|
||||||
|
}
|
||||||
|
#MemberLoginForm_LoginForm .Actions {
|
||||||
|
padding-left: 12em;
|
||||||
|
}
|
||||||
|
#ForgotPassword {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
@ -1,8 +1,3 @@
|
|||||||
/* HACK Doesn't work in an iframe-popup at the moment, so we disable it */
|
|
||||||
#Avatar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#i18nStatus {
|
#i18nStatus {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
@ -4,24 +4,25 @@
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-top: 3px solid #d4d0c8;
|
border-top: 2px solid #d4d0c8;
|
||||||
background-color:#81858d;
|
background-color:#81858d;
|
||||||
height: 18px;
|
height: 22px;
|
||||||
overflow:hidden;
|
overflow:hidden;
|
||||||
background-image:url(../../cms/images/textures/bottom.png);
|
background: #4d4e5a url(../../cms/images/textures/footerBg.gif) repeat-x left top;
|
||||||
|
}
|
||||||
|
|
||||||
|
#SilverStripeNavigator * {
|
||||||
|
font-family: Arial,Helvetica,sans-serif;
|
||||||
|
font-size: 10px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#SilverStripeNavigator .holder {
|
#SilverStripeNavigator .holder {
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top : 3px;
|
padding-top : 4px;
|
||||||
padding-left : 3px;
|
padding-left : 3px;
|
||||||
padding-right : 6px;
|
padding-right : 6px;
|
||||||
font-size: 10px;
|
|
||||||
color: white;
|
color: white;
|
||||||
border-top: 1px solid #555555;
|
border-top: 1px solid #555555;
|
||||||
|
|
||||||
}
|
}
|
||||||
#SilverStripeNavigator #logInStatus {
|
#SilverStripeNavigator #logInStatus {
|
||||||
float: right;
|
float: right;
|
||||||
@ -32,72 +33,52 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#SilverStripeNavigator a {
|
#SilverStripeNavigator a {
|
||||||
color: #333;
|
color: #fff;
|
||||||
background-color: transparent;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
#SilverStripeNavigator a:hover {
|
|
||||||
color: #333;
|
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
#SilverStripeNavigator a:hover {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
#SilverStripeNavigator .bottomTabs a {
|
#SilverStripeNavigator .bottomTabs a {
|
||||||
width: auto;
|
margin-right: 8px;
|
||||||
display: block;
|
text-decoration: underline;
|
||||||
float : left;
|
|
||||||
height : 13px;
|
|
||||||
padding-left : 12px;
|
|
||||||
padding-right : 12px;
|
|
||||||
position:relative;
|
|
||||||
top : -3px;
|
|
||||||
border : 1px solid #65686e;
|
|
||||||
border-top : none;
|
|
||||||
cursor:pointer;
|
|
||||||
background-color: #cdc9c1;
|
|
||||||
color : #333333;
|
|
||||||
background-image: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#SilverStripeNavigator .bottomTabs div.blank {
|
#SilverStripeNavigator .bottomTabs div.blank {
|
||||||
display: block;
|
display: block;
|
||||||
float : left;
|
float : left;
|
||||||
height : 13px;
|
height : 13px;
|
||||||
padding-left : 12px;
|
|
||||||
padding-right : 12px;
|
|
||||||
position:relative;
|
position:relative;
|
||||||
top : -3px;
|
top : -2px;
|
||||||
border : 1px solid #65686e;
|
cursor: pointer;
|
||||||
border-top : none;
|
|
||||||
cursor:pointer;
|
|
||||||
background-color: #cdc9c1;
|
|
||||||
color : #333333;
|
|
||||||
|
|
||||||
border : none;
|
border : none;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
padding-right: 2px;
|
padding: 2px 4px 2px 2px;
|
||||||
padding-left: 2px;
|
font-weight: bold;
|
||||||
padding-top : 2px;
|
|
||||||
color:#FFFFFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#SilverStripeNavigator .bottomTabs a.current {
|
#SilverStripeNavigator .bottomTabs a.current {
|
||||||
background-color : #d4d0c8;
|
|
||||||
padding-top : 1px;
|
|
||||||
top : -5px;
|
|
||||||
height : 15px;
|
|
||||||
font-weight:bold;
|
font-weight:bold;
|
||||||
font-size : 11px;
|
text-decoration: none;
|
||||||
border : 1px solid #555555;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#SilverStripeNavigatorMessage {
|
#SilverStripeNavigatorMessage {
|
||||||
|
font-family: 'Lucida Grande', Verdana, Arial, 'sans-serif';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 45%;
|
right: 20px;
|
||||||
top: 10px;
|
top: 40px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-color: #c99;
|
border-color: #c99;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: #c00;
|
background-color: #c00;
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#SilverStripeNavigator #logInStatus {
|
||||||
|
background:transparent url(../../cms/images/logout.gif) no-repeat scroll right top !important;
|
||||||
|
padding-bottom:4px;
|
||||||
|
padding-right:20px;
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ table.CMSList {
|
|||||||
width : 100%;
|
width : 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HACK Preventing IE6 from showing double borders */
|
/* Preventing IE6 from showing double borders */
|
||||||
body>div table.TableField,
|
body>div table.TableField,
|
||||||
body>div table.TableListField,
|
body>div table.TableListField,
|
||||||
body>div .TableListField table.data,
|
body>div .TableListField table.data,
|
||||||
@ -113,6 +113,7 @@ table.CMSList tbody td.checkbox {
|
|||||||
|
|
||||||
table.TableField tbody tr.over td,
|
table.TableField tbody tr.over td,
|
||||||
.TableListField table.data tbody tr.over td,
|
.TableListField table.data tbody tr.over td,
|
||||||
|
.TableListField table.data tbody tr.over td input,
|
||||||
table.CMSList tbody td.over td{
|
table.CMSList tbody td.over td{
|
||||||
background-color: #FFCC66;
|
background-color: #FFCC66;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,14 @@ abstract class BulkLoader extends ViewableData {
|
|||||||
* Specifies how to determine duplicates based on one or more provided fields
|
* Specifies how to determine duplicates based on one or more provided fields
|
||||||
* in the imported data, matching to properties on the used {@link DataObject} class.
|
* in the imported data, matching to properties on the used {@link DataObject} class.
|
||||||
* Alternatively the array values can contain a callback method (see example for
|
* Alternatively the array values can contain a callback method (see example for
|
||||||
* implementation details).
|
* implementation details). The callback method should be defined on the source class.
|
||||||
|
*
|
||||||
|
* NOTE: If you're trying to get a unique Member record by a particular field that
|
||||||
|
* isn't Email, you need to ensure that Member is correctly set to the unique field
|
||||||
|
* you want, as it will merge any duplicates during {@link Member::onBeforeWrite()}.
|
||||||
|
*
|
||||||
|
* {@see Member::set_unique_identifier_field()}.
|
||||||
|
*
|
||||||
* If multiple checks are specified, the first one "wins".
|
* If multiple checks are specified, the first one "wins".
|
||||||
*
|
*
|
||||||
* <code>
|
* <code>
|
||||||
@ -222,7 +229,7 @@ abstract class BulkLoader extends ViewableData {
|
|||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
protected function isNullValue($val, $fieldName = null) {
|
protected function isNullValue($val, $fieldName = null) {
|
||||||
return (empty($val));
|
return (empty($val) && $val !== '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -171,5 +171,4 @@ class ModelViewer_Relation extends ViewableData {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -262,6 +262,22 @@ class Email extends ViewableData {
|
|||||||
$this->body;
|
$this->body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set template name (without *.ss extension).
|
||||||
|
*
|
||||||
|
* @param string $template
|
||||||
|
*/
|
||||||
|
public function setTemplate($template) {
|
||||||
|
$this->ss_template = $template;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTemplate() {
|
||||||
|
return $this->ss_template;
|
||||||
|
}
|
||||||
|
|
||||||
protected function templateData() {
|
protected function templateData() {
|
||||||
if($this->template_data) {
|
if($this->template_data) {
|
||||||
return $this->template_data->customise(array(
|
return $this->template_data->customise(array(
|
||||||
@ -385,6 +401,8 @@ class Email extends ViewableData {
|
|||||||
$headers['Bcc'] .= self::$bcc_all_emails_to;
|
$headers['Bcc'] .= self::$bcc_all_emails_to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Requirements::restore();
|
||||||
|
|
||||||
return self::mailer()->sendPlain($to, $this->from, $subject, $this->body, $this->attachments, $headers);
|
return self::mailer()->sendPlain($to, $this->from, $subject, $this->body, $this->attachments, $headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,12 +561,19 @@ class Email extends ViewableData {
|
|||||||
*
|
*
|
||||||
* @param string $email Email-address
|
* @param string $email Email-address
|
||||||
* @param string $method Method for obfuscating/encoding the address
|
* @param string $method Method for obfuscating/encoding the address
|
||||||
|
* - 'direction': Reverse the text and then use CSS to put the text direction back to normal
|
||||||
* - 'visible': Simple string substitution ('@' to '[at]', '.' to '[dot], '-' to [dash])
|
* - 'visible': Simple string substitution ('@' to '[at]', '.' to '[dot], '-' to [dash])
|
||||||
* - 'hex': Hexadecimal URL-Encoding - useful for mailto: links
|
* - 'hex': Hexadecimal URL-Encoding - useful for mailto: links
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function obfuscate($email, $method = 'visible') {
|
public static function obfuscate($email, $method = 'visible') {
|
||||||
switch($method) {
|
switch($method) {
|
||||||
|
case 'direction' :
|
||||||
|
Requirements::customCSS(
|
||||||
|
'span.codedirection { unicode-bidi: bidi-override; direction: rtl; }',
|
||||||
|
'codedirectionCSS'
|
||||||
|
);
|
||||||
|
return '<span class="codedirection">' . strrev($email) . '</span>';
|
||||||
case 'visible' :
|
case 'visible' :
|
||||||
$obfuscated = array('@' => ' [at] ', '.' => ' [dot] ', '-' => ' [dash] ');
|
$obfuscated = array('@' => ' [at] ', '.' => ' [dot] ', '-' => ' [dash] ');
|
||||||
return strtr($email, $obfuscated);
|
return strtr($email, $obfuscated);
|
||||||
@ -714,38 +739,21 @@ class Email_BounceRecord extends DataObject {
|
|||||||
static $has_one = array(
|
static $has_one = array(
|
||||||
'Member' => 'Member'
|
'Member' => 'Member'
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
static $has_many = array();
|
||||||
* This class is responsible for ensuring that members who are on it receive NO email
|
|
||||||
* communication at all. any correspondance is caught before the email is sent.
|
|
||||||
* @package sapphire
|
|
||||||
* @subpackage email
|
|
||||||
*/
|
|
||||||
class Email_BlackList extends DataObject{
|
|
||||||
static $db = array(
|
|
||||||
'BlockedEmail' => 'Varchar',
|
|
||||||
);
|
|
||||||
static $has_one = array(
|
|
||||||
'Member' => 'Member'
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
static $many_many = array();
|
||||||
* Helper function to see if the email being
|
|
||||||
* sent has specifically been blocked.
|
static $defaults = array();
|
||||||
*/
|
|
||||||
static function isBlocked($email){
|
|
||||||
$blockedEmails = DataObject::get("Email_BlackList")->toDropDownMap("ID","BlockedEmail");
|
/**
|
||||||
if($blockedEmails){
|
* a record of Email_BounceRecord can't be created manually. Instead, it should be
|
||||||
if(in_array($email,$blockedEmails)){
|
* created though system.
|
||||||
return true;
|
*/
|
||||||
}else{
|
public function canCreate($member = null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}else{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
@ -17,7 +17,7 @@ class Mailer extends Object {
|
|||||||
* Send a plain-text email
|
* Send a plain-text email
|
||||||
*/
|
*/
|
||||||
function sendPlain($to, $from, $subject, $plainContent, $attachedFiles = false, $customheaders = false) {
|
function sendPlain($to, $from, $subject, $plainContent, $attachedFiles = false, $customheaders = false) {
|
||||||
return plaintextEmail($to, $from, $subject, $htmlContent, $attachedFiles, $customheaders);
|
return plaintextEmail($to, $from, $subject, $plainContent, $attachedFiles, $customheaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -428,4 +428,3 @@ function loadMimeTypes() {
|
|||||||
$global_mimetypes = $mimeData;
|
$global_mimetypes = $mimeData;
|
||||||
return $mimeData;
|
return $mimeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,12 @@ class QueuedEmail extends DataObject {
|
|||||||
'To' => 'Member'
|
'To' => 'Member'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static $has_many = array();
|
||||||
|
|
||||||
|
static $many_many = array();
|
||||||
|
|
||||||
|
static $defaults = array();
|
||||||
|
|
||||||
// overwrite this method to provide a check whether or not to send the email
|
// overwrite this method to provide a check whether or not to send the email
|
||||||
function canSendEmail() {
|
function canSendEmail() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -33,14 +33,21 @@ class File extends DataObject {
|
|||||||
"Owner" => "Member"
|
"Owner" => "Member"
|
||||||
);
|
);
|
||||||
|
|
||||||
static $extensions = array(
|
static $has_many = array();
|
||||||
"Hierarchy",
|
|
||||||
);
|
static $many_many = array();
|
||||||
|
|
||||||
static $belongs_many_many = array(
|
static $belongs_many_many = array(
|
||||||
"BackLinkTracking" => "SiteTree",
|
"BackLinkTracking" => "SiteTree",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static $defaults = array();
|
||||||
|
|
||||||
|
static $extensions = array(
|
||||||
|
"Hierarchy",
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cached result of a "SHOW FIELDS" call
|
* Cached result of a "SHOW FIELDS" call
|
||||||
* in instance_get() for performance reasons.
|
* in instance_get() for performance reasons.
|
||||||
|
@ -441,7 +441,7 @@ class Folder extends File {
|
|||||||
*/
|
*/
|
||||||
function getUploadIframe() {
|
function getUploadIframe() {
|
||||||
return <<<HTML
|
return <<<HTML
|
||||||
<iframe name="AssetAdmin_upload" src="admin/assets/uploadiframe/{$this->ID}" id="AssetAdmin_upload" border="0" style="border-style: none; width: 100%; height: 200px">
|
<iframe name="AssetAdmin_upload" src="admin/assets/uploadiframe/{$this->ID}" id="AssetAdmin_upload" border="0" style="border-style none !important; width: 97%; min-height: 300px; height: 100%; height: expression(document.body.clientHeight) !important;">
|
||||||
</iframe>
|
</iframe>
|
||||||
HTML;
|
HTML;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,15 @@
|
|||||||
*
|
*
|
||||||
* ASSUMPTION -> IF you pass your source as an array, you pass values as an array too.
|
* ASSUMPTION -> IF you pass your source as an array, you pass values as an array too.
|
||||||
* Likewise objects are handled the same.
|
* Likewise objects are handled the same.
|
||||||
|
*
|
||||||
|
* @todo Document the different source data that can be used
|
||||||
|
* with this form field - e.g ComponentSet, DataObjectSet,
|
||||||
|
* array. Is it also appropriate to accept so many different
|
||||||
|
* types of data when just using an array would be appropriate?
|
||||||
|
*
|
||||||
|
* @todo Make use of FormField->createTag() to generate the
|
||||||
|
* HTML tag(s) for this field.
|
||||||
|
*
|
||||||
* @package forms
|
* @package forms
|
||||||
* @subpackage fields-basic
|
* @subpackage fields-basic
|
||||||
*/
|
*/
|
||||||
@ -11,11 +20,12 @@ class CheckboxSetField extends OptionsetField {
|
|||||||
|
|
||||||
protected $disabled = false;
|
protected $disabled = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object handles arrays and dosets being passed by reference.
|
* @todo Explain different source data that can be used with this field,
|
||||||
*
|
* e.g. SQLMap, DataObjectSet or an array.
|
||||||
* @todo Should use CheckboxField FieldHolder rather than constructing own markup.
|
*
|
||||||
*/
|
* @todo Should use CheckboxField FieldHolder rather than constructing own markup.
|
||||||
|
*/
|
||||||
function Field() {
|
function Field() {
|
||||||
Requirements::css(SAPPHIRE_DIR . '/css/CheckboxSetField.css');
|
Requirements::css(SAPPHIRE_DIR . '/css/CheckboxSetField.css');
|
||||||
|
|
||||||
@ -86,10 +96,10 @@ class CheckboxSetField extends OptionsetField {
|
|||||||
$checked = '';
|
$checked = '';
|
||||||
|
|
||||||
if(isset($items)) {
|
if(isset($items)) {
|
||||||
in_array($key,$items) ? $checked = " checked=\"checked\"" : $checked = "";
|
$checked = (in_array($key, $items)) ? ' checked="checked"' : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->disabled ? $disabled = " disabled=\"disabled\"" : $disabled = "";
|
$disabled = ($this->disabled) ? $disabled = ' disabled="disabled"' : '';
|
||||||
$options .= "<li class=\"$extraClass\"><input id=\"$itemID\" name=\"$this->name[$key]\" type=\"checkbox\" value=\"$key\"$checked $disabled class=\"checkbox\" /> <label for=\"$itemID\">$value</label></li>\n";
|
$options .= "<li class=\"$extraClass\"><input id=\"$itemID\" name=\"$this->name[$key]\" type=\"checkbox\" value=\"$key\"$checked $disabled class=\"checkbox\" /> <label for=\"$itemID\">$value</label></li>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +118,7 @@ class CheckboxSetField extends OptionsetField {
|
|||||||
if(!$value && $obj && $obj instanceof DataObject && $obj->hasMethod($this->name)) {
|
if(!$value && $obj && $obj instanceof DataObject && $obj->hasMethod($this->name)) {
|
||||||
$funcName = $this->name;
|
$funcName = $this->name;
|
||||||
$selected = $obj->$funcName();
|
$selected = $obj->$funcName();
|
||||||
$value = $selected->toDropdownMap('ID','ID');
|
$value = $selected->toDropdownMap('ID', 'ID');
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::setValue($value, $obj);
|
parent::setValue($value, $obj);
|
||||||
@ -133,7 +143,7 @@ class CheckboxSetField extends OptionsetField {
|
|||||||
$record->$fieldname()->setByIDList($idList);
|
$record->$fieldname()->setByIDList($idList);
|
||||||
} elseif($fieldname && $record) {
|
} elseif($fieldname && $record) {
|
||||||
if($this->value) {
|
if($this->value) {
|
||||||
$this->value = str_replace(",", "{comma}", $this->value);
|
$this->value = str_replace(',', '{comma}', $this->value);
|
||||||
$record->$fieldname = implode(",", $this->value);
|
$record->$fieldname = implode(",", $this->value);
|
||||||
} else {
|
} else {
|
||||||
$record->$fieldname = '';
|
$record->$fieldname = '';
|
||||||
@ -142,79 +152,93 @@ class CheckboxSetField extends OptionsetField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the CheckboxSetField value, as an array of the selected item keys
|
* Return the CheckboxSetField value as an array
|
||||||
|
* selected item keys.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
function dataValue() {
|
function dataValue() {
|
||||||
if($this->value&&is_array($this->value)){
|
if($this->value && is_array($this->value)) {
|
||||||
// Filter items to those who aren't 0
|
|
||||||
$filtered = array();
|
$filtered = array();
|
||||||
foreach($this->value as $item) if($item) $filtered[] = str_replace(",", "{comma}", $item);
|
foreach($this->value as $item) {
|
||||||
return implode(",", $filtered);
|
if($item) {
|
||||||
} else {
|
$filtered[] = str_replace(",", "{comma}", $item);
|
||||||
return '';
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(',', $filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function performDisabledTransformation() {
|
function performDisabledTransformation() {
|
||||||
$clone = clone $this;
|
$clone = clone $this;
|
||||||
$clone->setDisabled(true);
|
$clone->setDisabled(true);
|
||||||
|
|
||||||
return $clone;
|
return $clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a pretty readonly field
|
* Transforms the source data for this CheckboxSetField
|
||||||
*/
|
* into a comma separated list of values.
|
||||||
|
*
|
||||||
|
* @return ReadonlyField
|
||||||
|
*/
|
||||||
function performReadonlyTransformation() {
|
function performReadonlyTransformation() {
|
||||||
$values = '';
|
$values = '';
|
||||||
|
$data = array();
|
||||||
|
|
||||||
$items = $this->value;
|
$items = $this->value;
|
||||||
foreach($this->source as $source) {
|
if($this->source) {
|
||||||
if(is_object($source)) {
|
foreach($this->source as $source) {
|
||||||
$sourceTitles[$source->ID] = $source->Title;
|
if(is_object($source)) {
|
||||||
|
$sourceTitles[$source->ID] = $source->Title;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($items){
|
if($items) {
|
||||||
// Items is a DO Set
|
// Items is a DO Set
|
||||||
if(is_a($items,'DataObjectSet')){
|
if(is_a($items, 'DataObjectSet')) {
|
||||||
|
foreach($items as $item) {
|
||||||
foreach($items as $item){
|
|
||||||
$data[] = $item->Title;
|
$data[] = $item->Title;
|
||||||
}
|
}
|
||||||
if($data) {
|
if($data) $values = implode(', ', $data);
|
||||||
$values = implode(", ",$data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Items is an array or single piece of string (including comma seperated string)
|
// Items is an array or single piece of string (including comma seperated string)
|
||||||
}else{
|
} else {
|
||||||
if(!is_array($items)) {
|
if(!is_array($items)) {
|
||||||
$items = split(" *, *", trim($items));
|
$items = split(' *, *', trim($items));
|
||||||
}
|
}
|
||||||
foreach($items as $item){
|
|
||||||
|
foreach($items as $item) {
|
||||||
if(is_array($item)) {
|
if(is_array($item)) {
|
||||||
$data[] = $item['Title'];
|
$data[] = $item['Title'];
|
||||||
} else if(is_array($this->source) && !empty($this->source[$item])) {
|
} elseif(is_array($this->source) && !empty($this->source[$item])) {
|
||||||
$data[] = $this->source[$item];
|
$data[] = $this->source[$item];
|
||||||
} else if(is_a($this->source, "ComponentSet")){
|
} elseif(is_a($this->source, 'ComponentSet')) {
|
||||||
//added for editable checkboxset.
|
|
||||||
$data[] = $sourceTitles[$item];
|
$data[] = $sourceTitles[$item];
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$data[] = $item;
|
$data[] = $item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$values = implode(", ",$data);
|
|
||||||
|
$values = implode(', ', $data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$field = new ReadonlyField($this->name,$this->title ? $this->title : "",$values);
|
$title = ($this->title) ? $this->title : '';
|
||||||
|
|
||||||
|
$field = new ReadonlyField($this->name, $title, $values);
|
||||||
$field->setForm($this->form);
|
$field->setForm($this->form);
|
||||||
|
|
||||||
return $field;
|
return $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ExtraOptions() {
|
function ExtraOptions() {
|
||||||
return FormField::ExtraOptions();
|
return FormField::ExtraOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
@ -472,7 +472,7 @@ JS;
|
|||||||
if(!$childData->ID && $this->getParentClass()) {
|
if(!$childData->ID && $this->getParentClass()) {
|
||||||
// make sure the relation-link is existing, even if we just add the sourceClass and didn't save it
|
// make sure the relation-link is existing, even if we just add the sourceClass and didn't save it
|
||||||
$parentIDName = $this->getParentIdName( $this->getParentClass(), $this->sourceClass() );
|
$parentIDName = $this->getParentIdName( $this->getParentClass(), $this->sourceClass() );
|
||||||
$childData->$parentIDName = $childData->ID;
|
$childData->$parentIDName = $this->sourceID();
|
||||||
}
|
}
|
||||||
|
|
||||||
$detailFields = $this->getCustomFieldsFor($childData);
|
$detailFields = $this->getCustomFieldsFor($childData);
|
||||||
@ -725,8 +725,10 @@ class ComplexTableField_ItemRequest extends RequestHandler {
|
|||||||
* @see Form::ReferencedField
|
* @see Form::ReferencedField
|
||||||
*/
|
*/
|
||||||
function saveComplexTableField($data, $form, $request) {
|
function saveComplexTableField($data, $form, $request) {
|
||||||
$form->saveInto($this->dataObj());
|
$dataObject = $this->dataObj();
|
||||||
$this->dataObj()->write();
|
|
||||||
|
$form->saveInto($dataObject);
|
||||||
|
$dataObject->write();
|
||||||
|
|
||||||
$closeLink = sprintf(
|
$closeLink = sprintf(
|
||||||
'<small><a href="' . $_SERVER['HTTP_REFERER'] . '" onclick="javascript:window.top.GB_hide(); return false;">(%s)</a></small>',
|
'<small><a href="' . $_SERVER['HTTP_REFERER'] . '" onclick="javascript:window.top.GB_hide(); return false;">(%s)</a></small>',
|
||||||
@ -734,8 +736,8 @@ class ComplexTableField_ItemRequest extends RequestHandler {
|
|||||||
);
|
);
|
||||||
$message = sprintf(
|
$message = sprintf(
|
||||||
_t('ComplexTableField.SUCCESSEDIT', 'Saved %s %s %s'),
|
_t('ComplexTableField.SUCCESSEDIT', 'Saved %s %s %s'),
|
||||||
$this->dataObj()->singular_name(),
|
$dataObject->singular_name(),
|
||||||
'<a href="' . $this->Link() . '">"' . $this->dataObj()->Title . '"</a>',
|
'<a href="' . $this->Link() . '">"' . $dataObject->Title . '"</a>',
|
||||||
$closeLink
|
$closeLink
|
||||||
);
|
);
|
||||||
$form->sessionMessage($message, 'good');
|
$form->sessionMessage($message, 'good');
|
||||||
@ -754,7 +756,8 @@ class ComplexTableField_ItemRequest extends RequestHandler {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$item = $this->unpagedSourceItems->First();
|
// We never use $item afterwards in the function, where we have it here? disable it!
|
||||||
|
//$item = $this->unpagedSourceItems->First();
|
||||||
$start = 0;
|
$start = 0;
|
||||||
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
|
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
|
||||||
}
|
}
|
||||||
@ -764,7 +767,8 @@ class ComplexTableField_ItemRequest extends RequestHandler {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$item = $this->unpagedSourceItems->Last();
|
// We never use $item afterwards in the function, where we have it here? disable it!
|
||||||
|
// $item = $this->unpagedSourceItems->Last();
|
||||||
$start = $this->totalCount - 1;
|
$start = $this->totalCount - 1;
|
||||||
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
|
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
|
||||||
}
|
}
|
||||||
@ -774,7 +778,8 @@ class ComplexTableField_ItemRequest extends RequestHandler {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$item = $this->unpagedSourceItems->getIterator()->getOffset($_REQUEST['ctf']['start'] + 1);
|
// We never use $item afterwards in the function, where we have it here? disable it!
|
||||||
|
//$item = $this->unpagedSourceItems->getIterator()->getOffset($_REQUEST['ctf']['start'] + 1);
|
||||||
|
|
||||||
$start = $_REQUEST['ctf']['start'] + 1;
|
$start = $_REQUEST['ctf']['start'] + 1;
|
||||||
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
|
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
|
||||||
@ -785,7 +790,8 @@ class ComplexTableField_ItemRequest extends RequestHandler {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$item = $this->unpagedSourceItems->getIterator()->getOffset($_REQUEST['ctf']['start'] - 1);
|
// We never use $item afterwards in the function, where we have it here? disable it!
|
||||||
|
//$item = $this->unpagedSourceItems->getIterator()->getOffset($_REQUEST['ctf']['start'] - 1);
|
||||||
|
|
||||||
$start = $_REQUEST['ctf']['start'] - 1;
|
$start = $_REQUEST['ctf']['start'] - 1;
|
||||||
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
|
return Controller::join_links($this->Link(), "$this->methodName?ctf[start]={$start}");
|
||||||
|
@ -112,15 +112,16 @@ class DateField_Disabled extends DateField {
|
|||||||
$df->setValue($this->dataValue());
|
$df->setValue($this->dataValue());
|
||||||
|
|
||||||
if(date('Y-m-d', time()) == $this->dataValue()) {
|
if(date('Y-m-d', time()) == $this->dataValue()) {
|
||||||
$val = Convert::raw2xml($this->value . ' ('._t('DateField.TODAY','today').')');
|
$val = Convert::raw2xml($this->value . ' ('._t('DateField.TODAY','today').')');
|
||||||
} else {
|
} else {
|
||||||
$val = Convert::raw2xml($this->value . ', ' . $df->Ago());
|
$val = Convert::raw2xml($this->value . ', ' . $df->Ago());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$val = '<i>('._t('DateField.NOTSET', 'not set').')</i>';
|
$val = '<i>('._t('DateField.NOTSET', 'not set').')</i>';
|
||||||
}
|
}
|
||||||
|
|
||||||
return "<span class=\"readonly\" id=\"" . $this->id() . "\">$val</span>";
|
return "<span class=\"readonly\" id=\"" . $this->id() . "\">$val</span>
|
||||||
|
<input type=\"hidden\" value=\"{$this->value}\" name=\"$this->name\" />";
|
||||||
}
|
}
|
||||||
|
|
||||||
function Type() {
|
function Type() {
|
||||||
|
@ -83,7 +83,22 @@ class FieldGroup extends CompositeField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function FieldHolder() {
|
function FieldHolder() {
|
||||||
return FormField::FieldHolder();
|
$Title = $this->XML_val('Title');
|
||||||
|
$Message = $this->XML_val('Message');
|
||||||
|
$MessageType = $this->XML_val('MessageType');
|
||||||
|
$RightTitle = $this->XML_val('RightTitle');
|
||||||
|
$Type = $this->XML_val('Type');
|
||||||
|
$extraClass = $this->XML_val('extraClass');
|
||||||
|
$Name = $this->XML_val('Name');
|
||||||
|
$Field = $this->XML_val('Field');
|
||||||
|
|
||||||
|
$titleBlock = (!empty($Title)) ? "<label class=\"left\">$Title</label>" : "";
|
||||||
|
$messageBlock = (!empty($Message)) ? "<span class=\"message $MessageType\">$Message</span>" : "";
|
||||||
|
$rightTitleBlock = (!empty($RightTitle)) ? "<label class=\"right\">$RightTitle</label>" : "";
|
||||||
|
|
||||||
|
return <<<HTML
|
||||||
|
<div id="$Name" class="field $Type $extraClass">$titleBlock<div class="middleColumn">$Field</div>$rightTitleBlock$messageBlock</div>
|
||||||
|
HTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Message() {
|
function Message() {
|
||||||
|
@ -201,7 +201,7 @@ class FileField extends FormField {
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getFolderName() {
|
public function getFolderName() {
|
||||||
return $folderName;
|
return $this->folderName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function validate($validator) {
|
public function validate($validator) {
|
||||||
|
@ -886,6 +886,8 @@ class Form extends RequestHandler {
|
|||||||
*/
|
*/
|
||||||
function getData() {
|
function getData() {
|
||||||
$dataFields = $this->fields->dataFields();
|
$dataFields = $this->fields->dataFields();
|
||||||
|
$data = array();
|
||||||
|
|
||||||
if($dataFields){
|
if($dataFields){
|
||||||
foreach($dataFields as $field) {
|
foreach($dataFields as $field) {
|
||||||
if($field->Name()) {
|
if($field->Name()) {
|
||||||
|
@ -69,6 +69,10 @@ class FormAction extends FormField {
|
|||||||
'type' => 'submit',
|
'type' => 'submit',
|
||||||
'name' => $this->action
|
'name' => $this->action
|
||||||
);
|
);
|
||||||
|
if($this->isReadonly()) {
|
||||||
|
$attributes['disabled'] = 'disabled';
|
||||||
|
$attributes['class'] = $attributes['class'] . ' disabled';
|
||||||
|
}
|
||||||
|
|
||||||
return $this->createTag('button', $attributes, $this->attrTitle());
|
return $this->createTag('button', $attributes, $this->attrTitle());
|
||||||
} else {
|
} else {
|
||||||
@ -79,7 +83,10 @@ class FormAction extends FormField {
|
|||||||
'name' => $this->action,
|
'name' => $this->action,
|
||||||
'value' => ($this->dontEscape) ? $this->Title() : $this->attrTitle()
|
'value' => ($this->dontEscape) ? $this->Title() : $this->attrTitle()
|
||||||
);
|
);
|
||||||
|
if($this->isReadonly()) {
|
||||||
|
$attributes['disabled'] = 'disabled';
|
||||||
|
$attributes['class'] = $attributes['class'] . ' disabled';
|
||||||
|
}
|
||||||
$attributes['title'] = ($this->description) ? $this->description : ($this->dontEscape) ? $this->Title() : $this->attrTitle();
|
$attributes['title'] = ($this->description) ? $this->description : ($this->dontEscape) ? $this->Title() : $this->attrTitle();
|
||||||
|
|
||||||
return $this->createTag('input', $attributes);
|
return $this->createTag('input', $attributes);
|
||||||
|
@ -481,7 +481,8 @@ HTML;
|
|||||||
*
|
*
|
||||||
* @todo shouldn't this be an abstract method?
|
* @todo shouldn't this be an abstract method?
|
||||||
*/
|
*/
|
||||||
function jsValidation() {}
|
function jsValidation() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validation Functions for each field type by default
|
* Validation Functions for each field type by default
|
||||||
@ -489,7 +490,9 @@ HTML;
|
|||||||
*
|
*
|
||||||
* @todo shouldn't this be an abstract method?
|
* @todo shouldn't this be an abstract method?
|
||||||
*/
|
*/
|
||||||
function validate(){return true;}
|
function validate() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe this field, provide help text for it.
|
* Describe this field, provide help text for it.
|
||||||
|
@ -47,52 +47,6 @@ class HasManyComplexTableField extends ComplexTableField {
|
|||||||
elseif($this->controller instanceof ContentController) return $this->controller->data()->class;
|
elseif($this->controller instanceof ContentController) return $this->controller->data()->class;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getQuery($limitClause = null) {
|
|
||||||
if($this->customQuery) {
|
|
||||||
$query = $this->customQuery;
|
|
||||||
$query->select[] = "{$this->sourceClass}.ID AS ID";
|
|
||||||
$query->select[] = "{$this->sourceClass}.ClassName AS ClassName";
|
|
||||||
$query->select[] = "{$this->sourceClass}.ClassName AS \"RecordClassName\"";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$query = singleton($this->sourceClass)->extendedSQL($this->sourceFilter, $this->sourceSort, $limitClause, $this->sourceJoin);
|
|
||||||
|
|
||||||
// Add more selected fields if they are from joined table.
|
|
||||||
|
|
||||||
$SNG = singleton($this->sourceClass);
|
|
||||||
foreach($this->FieldList() as $k => $title) {
|
|
||||||
if(! $SNG->hasField($k) && ! $SNG->hasMethod('get' . $k))
|
|
||||||
$query->select[] = $k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return clone $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sourceItems() {
|
|
||||||
if($this->sourceItems) return $this->sourceItems;
|
|
||||||
|
|
||||||
$limitClause = '';
|
|
||||||
if(isset($_REQUEST['ctf'][$this->Name()]['start']) && is_numeric($_REQUEST['ctf'][$this->Name()]['start'])) {
|
|
||||||
$limitClause = $_REQUEST[ 'ctf' ][ $this->Name() ][ 'start' ] . ", $this->pageSize";
|
|
||||||
} else {
|
|
||||||
$limitClause = "0, $this->pageSize";
|
|
||||||
}
|
|
||||||
|
|
||||||
$dataQuery = $this->getQuery($limitClause);
|
|
||||||
$records = $dataQuery->execute();
|
|
||||||
$items = new DataObjectSet();
|
|
||||||
|
|
||||||
$sourceClass = $this->sourceClass;
|
|
||||||
$dataobject = new $sourceClass();
|
|
||||||
$items = $dataobject->buildDataObjectSet($records, 'DataObjectSet');
|
|
||||||
|
|
||||||
$this->unpagedSourceItems = $dataobject->buildDataObjectSet($records, 'DataObjectSet');
|
|
||||||
|
|
||||||
$this->totalCount = ($this->unpagedSourceItems) ? $this->unpagedSourceItems->TotalItems() : null;
|
|
||||||
|
|
||||||
return $items;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getControllerID() {
|
function getControllerID() {
|
||||||
return $this->controller->ID;
|
return $this->controller->ID;
|
||||||
}
|
}
|
||||||
@ -123,15 +77,21 @@ class HasManyComplexTableField extends ComplexTableField {
|
|||||||
return $this->addTitle ? $this->addTitle : parent::Title();
|
return $this->addTitle ? $this->addTitle : parent::Title();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the IDs of the selected items, in a has_many or many_many relation
|
||||||
|
*/
|
||||||
|
function selectedItemIDs() {
|
||||||
|
$fieldName = $this->name;
|
||||||
|
$selectedItems = $this->form->getRecord()->$fieldName();
|
||||||
|
$itemIDs = array();
|
||||||
|
foreach($selectedItems as $item) $itemIDs[] = $item->ID;
|
||||||
|
return $itemIDs;
|
||||||
|
}
|
||||||
|
|
||||||
function ExtraData() {
|
function ExtraData() {
|
||||||
$items = array();
|
$items = array();
|
||||||
if($this->unpagedSourceItems) {
|
|
||||||
foreach($this->unpagedSourceItems as $item) {
|
$list = implode(',', $this->selectedItemIDs());
|
||||||
if($item->{$this->joinField} == $this->controller->ID)
|
|
||||||
$items[] = $item->ID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$list = implode(',', $items);
|
|
||||||
$inputId = $this->id() . '_' . $this->htmlListEndName;
|
$inputId = $this->id() . '_' . $this->htmlListEndName;
|
||||||
return <<<HTML
|
return <<<HTML
|
||||||
<input id="$inputId" name="{$this->name}[{$this->htmlListField}]" type="hidden" value="$list"/>
|
<input id="$inputId" name="{$this->name}[{$this->htmlListField}]" type="hidden" value="$list"/>
|
||||||
|
@ -15,7 +15,7 @@ class HtmlEditorField extends TextareaField {
|
|||||||
/**
|
/**
|
||||||
* Construct a new HtmlEditor field
|
* Construct a new HtmlEditor field
|
||||||
*/
|
*/
|
||||||
function __construct($name, $title = "", $rows = 20, $cols = 20, $value = "", $form = null) {
|
function __construct($name, $title = null, $rows = 20, $cols = 20, $value = "", $form = null) {
|
||||||
parent::__construct($name, $title, $rows, $cols, $value, $form);
|
parent::__construct($name, $title, $rows, $cols, $value, $form);
|
||||||
$this->extraClass = 'typography';
|
$this->extraClass = 'typography';
|
||||||
}
|
}
|
||||||
@ -100,10 +100,10 @@ class HtmlEditorField extends TextareaField {
|
|||||||
|
|
||||||
$content = preg_replace('/mce_real_src="[^"]+"/i', "", $content);
|
$content = preg_replace('/mce_real_src="[^"]+"/i', "", $content);
|
||||||
|
|
||||||
$content = eregi_replace('(<img[^>]* )width=([0-9]+)( [^>]*>|>)','\\1width="\\2"\\3',$content);
|
$content = eregi_replace('(<img[^>]* )width=([0-9]+)( [^>]*>|>)','\\1width="\\2"\\3', $content);
|
||||||
$content = eregi_replace('(<img[^>]* )height=([0-9]+)( [^>]*>|>)','\\1height="\\2"\\3',$content);
|
$content = eregi_replace('(<img[^>]* )height=([0-9]+)( [^>]*>|>)','\\1height="\\2"\\3', $content);
|
||||||
$content = eregi_replace('src="([^\?]*)\?r=[0-9]+"','src="\\1"',$content);
|
$content = eregi_replace('src="([^\?]*)\?r=[0-9]+"','src="\\1"', $content);
|
||||||
$content = eregi_replace('mce_src="([^\?]*)\?r=[0-9]+"','mce_src="\\1"',$content);
|
$content = eregi_replace('mce_src="([^\?]*)\?r=[0-9]+"','mce_src="\\1"', $content);
|
||||||
|
|
||||||
$content = preg_replace_callback('/(<img[^>]* )(width="|height="|src=")([^"]+)("[^>]* )(width="|height="|src=")([^"]+)("[^>]* )(width="|height="|src=")([^"]+)("[^>]*>)/i', "HtmlEditorField_dataValue_processImage", $content);
|
$content = preg_replace_callback('/(<img[^>]* )(width="|height="|src=")([^"]+)("[^>]* )(width="|height="|src=")([^"]+)("[^>]* )(width="|height="|src=")([^"]+)("[^>]*>)/i', "HtmlEditorField_dataValue_processImage", $content);
|
||||||
|
|
||||||
@ -111,11 +111,12 @@ class HtmlEditorField extends TextareaField {
|
|||||||
if(!ereg("^[ \t\r\n]*<", $content)) $content = "<p>$content</p>";
|
if(!ereg("^[ \t\r\n]*<", $content)) $content = "<p>$content</p>";
|
||||||
|
|
||||||
$links = HTTP::getLinksIn($content);
|
$links = HTTP::getLinksIn($content);
|
||||||
|
$linkedPages = array();
|
||||||
|
|
||||||
if($links) foreach($links as $link) {
|
if($links) foreach($links as $link) {
|
||||||
$link = Director::makeRelative($link);
|
$link = Director::makeRelative($link);
|
||||||
|
|
||||||
if(preg_match( '/^([A-Za-z0-9_-]+)\/?(#.*)?$/', $link, $parts ) ) {
|
if(preg_match('/^([A-Za-z0-9_-]+)\/?(#.*)?$/', $link, $parts)) {
|
||||||
$candidatePage = DataObject::get_one("SiteTree", "\"URLSegment\" = '" . urldecode( $parts[1] ). "'", false);
|
$candidatePage = DataObject::get_one("SiteTree", "\"URLSegment\" = '" . urldecode( $parts[1] ). "'", false);
|
||||||
if($candidatePage) {
|
if($candidatePage) {
|
||||||
$linkedPages[] = $candidatePage->ID;
|
$linkedPages[] = $candidatePage->ID;
|
||||||
@ -135,10 +136,8 @@ class HtmlEditorField extends TextareaField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$images = HTTP::getImagesIn($content);
|
$images = HTTP::getImagesIn($content);
|
||||||
|
if($images) {
|
||||||
if($images){
|
|
||||||
foreach($images as $image) {
|
foreach($images as $image) {
|
||||||
|
|
||||||
$image = Director::makeRelative($image);
|
$image = Director::makeRelative($image);
|
||||||
if(substr($image,0,7) == 'assets/') {
|
if(substr($image,0,7) == 'assets/') {
|
||||||
$candidateImage = DataObject::get_one("File", "\"Filename\" = '$image'");
|
$candidateImage = DataObject::get_one("File", "\"Filename\" = '$image'");
|
||||||
@ -150,7 +149,7 @@ class HtmlEditorField extends TextareaField {
|
|||||||
|
|
||||||
$fieldName = $this->name;
|
$fieldName = $this->name;
|
||||||
if($record->ID && $record->hasMethod('LinkTracking') && $linkTracking = $record->LinkTracking()) {
|
if($record->ID && $record->hasMethod('LinkTracking') && $linkTracking = $record->LinkTracking()) {
|
||||||
$linkTracking->removeByFilter("\"FieldName\" = '$fieldName'");
|
$linkTracking->removeByFilter("\"FieldName\" = '$fieldName' AND \"SiteTreeID\" = $record->ID");
|
||||||
|
|
||||||
if(isset($linkedPages)) foreach($linkedPages as $item) {
|
if(isset($linkedPages)) foreach($linkedPages as $item) {
|
||||||
$linkTracking->add($item, array("FieldName" => $fieldName));
|
$linkTracking->add($item, array("FieldName" => $fieldName));
|
||||||
@ -410,14 +409,14 @@ class HtmlEditorField_Toolbar extends RequestHandler {
|
|||||||
new TreeDropdownField('FolderID', _t('HtmlEditorField.FOLDER', 'Folder'), 'Folder'),
|
new TreeDropdownField('FolderID', _t('HtmlEditorField.FOLDER', 'Folder'), 'Folder'),
|
||||||
new LiteralField('AddFolderOrUpload',
|
new LiteralField('AddFolderOrUpload',
|
||||||
'<div style="clear:both;"></div><div id="AddFolderGroup" style="display:inline">
|
'<div style="clear:both;"></div><div id="AddFolderGroup" style="display:inline">
|
||||||
<a style="" href="#" id="AddFolder" class="link">' . _t('HtmlEditorField.CREATEFOLDER','create folder') . '</a>
|
<a style="" href="#" id="AddFolder" class="link">' . _t('HtmlEditorField.CREATEFOLDER','Create Folder') . '</a>
|
||||||
<input style="display: none; margin-left: 2px; width: 94px;" id="NewFolderName" class="addFolder" type="text">
|
<input style="display: none; margin-left: 2px; width: 94px;" id="NewFolderName" class="addFolder" type="text">
|
||||||
<a style="display: none;" href="#" id="FolderOk" class="link addFolder">' . _t('HtmlEditorField.OK','ok') . '</a>
|
<a style="display: none;" href="#" id="FolderOk" class="link addFolder">' . _t('HtmlEditorField.OK','Ok') . '</a>
|
||||||
<a style="display: none;" href="#" id="FolderCancel" class="link addFolder">' . _t('HtmlEditorField.FOLDERCANCEL','cancel') . '</a>
|
<a style="display: none;" href="#" id="FolderCancel" class="link addFolder">' . _t('HtmlEditorField.FOLDERCANCEL','Cancel') . '</a>
|
||||||
</div>
|
</div>
|
||||||
<div id="PipeSeparator" style="display:inline">|</div>
|
<div id="PipeSeparator" style="display:inline">|</div>
|
||||||
<div id="UploadGroup" class="group" style="display: inline; margin-top: 2px;">
|
<div id="UploadGroup" class="group" style="display: inline; margin-top: 2px;">
|
||||||
<a href="#" id="UploadFiles" class="link">' . _t('HtmlEditorField.UPLOAD','upload') . '</a>
|
<a href="#" id="UploadFiles" class="link">' . _t('HtmlEditorField.UPLOAD','Upload') . '</a>
|
||||||
</div>'
|
</div>'
|
||||||
),
|
),
|
||||||
new TextField('getimagesSearch', _t('HtmlEditorField.SEARCHFILENAME', 'Search by file name')),
|
new TextField('getimagesSearch', _t('HtmlEditorField.SEARCHFILENAME', 'Search by file name')),
|
||||||
|
@ -59,5 +59,4 @@ class ImageField extends FileField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -42,45 +42,15 @@ class ManyManyComplexTableField extends HasManyComplexTableField {
|
|||||||
$this->joinField = 'Checked';
|
$this->joinField = 'Checked';
|
||||||
}
|
}
|
||||||
|
|
||||||
function getQuery($limitClause = null) {
|
function getQuery() {
|
||||||
if($this->customQuery) {
|
$query = parent::getQuery();
|
||||||
$query = $this->customQuery;
|
$query->select[] = "IF(`{$this->manyManyParentClass}ID` IS NULL, '0', '1') AS Checked";
|
||||||
$query->select[] = "{$this->sourceClass}.ID AS ID";
|
return $query;
|
||||||
$query->select[] = "{$this->sourceClass}.ClassName AS ClassName";
|
|
||||||
$query->select[] = "{$this->sourceClass}.ClassName AS \"RecordClassName\"";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$query = singleton($this->sourceClass)->extendedSQL($this->sourceFilter, $this->sourceSort, $limitClause, $this->sourceJoin);
|
|
||||||
|
|
||||||
// Add more selected fields if they are from joined table.
|
|
||||||
|
|
||||||
$SNG = singleton($this->sourceClass);
|
|
||||||
foreach($this->FieldList() as $k => $title) {
|
|
||||||
if(! $SNG->hasField($k) && ! $SNG->hasMethod('get' . $k))
|
|
||||||
$query->select[] = $k;
|
|
||||||
}
|
|
||||||
$parent = $this->controllerClass();
|
|
||||||
$query->select[] = "IF(\"{$this->manyManyParentClass}ID\" IS NULL, '0', '1') AS Checked";
|
|
||||||
}
|
|
||||||
return clone $query;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getParentIdName($parentClass, $childClass) {
|
function getParentIdName($parentClass, $childClass) {
|
||||||
return $this->getParentIdNameRelation($parentClass, $childClass, 'many_many');
|
return $this->getParentIdNameRelation($parentClass, $childClass, 'many_many');
|
||||||
}
|
}
|
||||||
|
|
||||||
function ExtraData() {
|
|
||||||
$items = array();
|
|
||||||
foreach($this->unpagedSourceItems as $item) {
|
|
||||||
if($item->{$this->joinField})
|
|
||||||
$items[] = $item->ID;
|
|
||||||
}
|
|
||||||
$list = implode(',', $items);
|
|
||||||
$inputId = $this->id() . '_' . $this->htmlListEndName;
|
|
||||||
return <<<HTML
|
|
||||||
<input id="$inputId" name="{$this->name}[{$this->htmlListField}]" type="hidden" value="$list"/>
|
|
||||||
HTML;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,6 +6,21 @@
|
|||||||
*/
|
*/
|
||||||
class PopupDateTimeField extends CalendarDateField {
|
class PopupDateTimeField extends CalendarDateField {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo js validation needs to be implemented.
|
||||||
|
* @see sapphire/forms/DateField#jsValidation()
|
||||||
|
*/
|
||||||
|
function jsValidation() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo php validation needs to be implemented.
|
||||||
|
* @see sapphire/forms/DateField#validate($validator)
|
||||||
|
*/
|
||||||
|
function validate() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function Field() {
|
function Field() {
|
||||||
|
|
||||||
Requirements::css( SAPPHIRE_DIR . '/css/PopupDateTimeField.css' );
|
Requirements::css( SAPPHIRE_DIR . '/css/PopupDateTimeField.css' );
|
||||||
|
@ -393,5 +393,4 @@ class ReportField_Controller extends Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -8,11 +8,36 @@
|
|||||||
class ResetFormAction extends FormAction {
|
class ResetFormAction extends FormAction {
|
||||||
|
|
||||||
function Field() {
|
function Field() {
|
||||||
$titleAttr = $this->description ? "title=\"" . Convert::raw2att($this->description) . "\"" : '';
|
|
||||||
if($this->useButtonTag) {
|
if($this->useButtonTag) {
|
||||||
return "<button class=\"action " . $this->extraClass() . "\" id=\"" . $this->id() . "\" type=\"reset\" name=\"$this->action\" $titleAttr />" . $this->attrTitle() . "</button>\n";
|
$attributes = array(
|
||||||
|
'class' => 'action' . ($this->extraClass() ? $this->extraClass() : ''),
|
||||||
|
'id' => $this->id(),
|
||||||
|
'type' => 'reset',
|
||||||
|
'name' => $this->action
|
||||||
|
);
|
||||||
|
|
||||||
|
if($this->isReadonly()) {
|
||||||
|
$attributes['disabled'] = 'disabled';
|
||||||
|
$attributes['class'] = $attributes['class'] . ' disabled';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->createTag('button', $attributes, $this->attrTitle());
|
||||||
} else {
|
} else {
|
||||||
return "<input class=\"action " . $this->extraClass() . "\" id=\"" . $this->id() . "\" type=\"reset\" name=\"$this->action\" value=\"" . $this->attrTitle() . "\" $titleAttr />\n";
|
$attributes = array(
|
||||||
|
'class' => 'action' . ($this->extraClass() ? $this->extraClass() : ''),
|
||||||
|
'id' => $this->id(),
|
||||||
|
'type' => 'reset',
|
||||||
|
'name' => $this->action,
|
||||||
|
);
|
||||||
|
|
||||||
|
if($this->isReadonly()) {
|
||||||
|
$attributes['disabled'] = 'disabled';
|
||||||
|
$attributes['class'] = $attributes['class'] . ' disabled';
|
||||||
|
}
|
||||||
|
|
||||||
|
$attributes['title'] = ($this->description) ? $this->description : ($this->dontEscape) ? $this->Title() : $this->attrTitle();
|
||||||
|
|
||||||
|
return $this->createTag('input', $attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,4 @@ class Tab extends CompositeField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -223,7 +223,7 @@ class TableField extends TableListField {
|
|||||||
|
|
||||||
function SubmittedFieldSet(&$sourceItems){
|
function SubmittedFieldSet(&$sourceItems){
|
||||||
$fields = array ();
|
$fields = array ();
|
||||||
if($rows = $_POST[$this->name]){
|
if(isset($_POST[$this->name])&&$rows = $_POST[$this->name]){
|
||||||
if(count($rows)){
|
if(count($rows)){
|
||||||
foreach($rows as $idx => $row){
|
foreach($rows as $idx => $row){
|
||||||
if($idx == 'new'){
|
if($idx == 'new'){
|
||||||
|
@ -801,6 +801,7 @@ JS
|
|||||||
}
|
}
|
||||||
|
|
||||||
function FirstItem() {
|
function FirstItem() {
|
||||||
|
if ($this->TotalCount() < 1) return 0;
|
||||||
return isset($_REQUEST['ctf'][$this->Name()]['start']) ? $_REQUEST['ctf'][$this->Name()]['start'] + 1 : 1;
|
return isset($_REQUEST['ctf'][$this->Name()]['start']) ? $_REQUEST['ctf'][$this->Name()]['start'] + 1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -894,6 +895,8 @@ JS
|
|||||||
/**
|
/**
|
||||||
* Exports a given set of comma-separated IDs (from a previous search-query, stored in a HiddenField).
|
* Exports a given set of comma-separated IDs (from a previous search-query, stored in a HiddenField).
|
||||||
* Uses {$csv_columns} if present, and falls back to {$result_columns}.
|
* Uses {$csv_columns} if present, and falls back to {$result_columns}.
|
||||||
|
* We move the most filedata generation code to the function {@link generateExportFileData()} so that a child class
|
||||||
|
* could reuse the filedata generation code while overwrite export function.
|
||||||
*
|
*
|
||||||
* @todo Make relation-syntax available (at the moment you'll have to use custom sql)
|
* @todo Make relation-syntax available (at the moment you'll have to use custom sql)
|
||||||
*/
|
*/
|
||||||
@ -901,19 +904,28 @@ JS
|
|||||||
$now = Date("d-m-Y-H-i");
|
$now = Date("d-m-Y-H-i");
|
||||||
$fileName = "export-$now.csv";
|
$fileName = "export-$now.csv";
|
||||||
|
|
||||||
|
if($fileData = $this->generateExportFileData($numColumns, $numRows)){
|
||||||
|
return HTTPRequest::send_file($fileData, $fileName);
|
||||||
|
}else{
|
||||||
|
user_error("No records found", E_USER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateExportFileData(&$numColumns, &$numRows) {
|
||||||
$separator = $this->csvSeparator;
|
$separator = $this->csvSeparator;
|
||||||
$csvColumns = ($this->fieldListCsv) ? $this->fieldListCsv : $this->fieldList;
|
$csvColumns = ($this->fieldListCsv) ? $this->fieldListCsv : $this->fieldList;
|
||||||
$fileData = "";
|
$fileData = '';
|
||||||
|
$columnData = array();
|
||||||
|
$fieldItems = new DataObjectSet();
|
||||||
|
|
||||||
if($this->csvHasHeader) {
|
if($this->csvHasHeader) {
|
||||||
$fileData .= "\"" . implode("\"{$separator}\"",array_values($csvColumns)) . "\"";
|
$fileData .= "\"" . implode("\"{$separator}\"", array_values($csvColumns)) . "\"";
|
||||||
$fileData .= "\n";
|
$fileData .= "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// get data
|
if(isset($this->customSourceItems)) {
|
||||||
if(isset($this->customSourceItems)){
|
|
||||||
$items = $this->customSourceItems;
|
$items = $this->customSourceItems;
|
||||||
}else{
|
} else {
|
||||||
$dataQuery = $this->getCsvQuery();
|
$dataQuery = $this->getCsvQuery();
|
||||||
$records = $dataQuery->execute();
|
$records = $dataQuery->execute();
|
||||||
$sourceClass = $this->sourceClass;
|
$sourceClass = $this->sourceClass;
|
||||||
@ -921,7 +933,6 @@ JS
|
|||||||
$items = $dataobject->buildDataObjectSet($records, 'DataObjectSet');
|
$items = $dataobject->buildDataObjectSet($records, 'DataObjectSet');
|
||||||
}
|
}
|
||||||
|
|
||||||
$fieldItems = new DataObjectSet();
|
|
||||||
if($items && $items->count()) foreach($items as $item) {
|
if($items && $items->count()) foreach($items as $item) {
|
||||||
// create a TableListField_Item to support resolving of
|
// create a TableListField_Item to support resolving of
|
||||||
// relation-fields in dot notation via TableListField_Item->Fields()
|
// relation-fields in dot notation via TableListField_Item->Fields()
|
||||||
@ -934,15 +945,14 @@ JS
|
|||||||
|
|
||||||
if($fieldItems) {
|
if($fieldItems) {
|
||||||
foreach($fieldItems as $fieldItem) {
|
foreach($fieldItems as $fieldItem) {
|
||||||
$columnData = array();
|
|
||||||
$fields = $fieldItem->Fields();
|
$fields = $fieldItem->Fields();
|
||||||
foreach($fields as $field) {
|
$columnData = array();
|
||||||
|
if($fields) foreach($fields as $field) {
|
||||||
$value = $field->Value;
|
$value = $field->Value;
|
||||||
|
|
||||||
// TODO This should be replaced with casting
|
// TODO This should be replaced with casting
|
||||||
if(array_key_exists($field->Name, $this->csvFieldFormatting)) {
|
if(array_key_exists($field->Name, $this->csvFieldFormatting)) {
|
||||||
$format = str_replace('$value', "__VAL__", $this->csvFieldFormatting[$columnName]);
|
$format = str_replace('$value', "__VAL__", $this->csvFieldFormatting[$field->Name]);
|
||||||
$format = preg_replace('/\$([A-Za-z0-9-_]+)/','$item->$1', $format);
|
$format = preg_replace('/\$([A-Za-z0-9-_]+)/','$item->$1', $format);
|
||||||
$format = str_replace('__VAL__', '$value', $format);
|
$format = str_replace('__VAL__', '$value', $format);
|
||||||
eval('$value = "' . $format . '";');
|
eval('$value = "' . $format . '";');
|
||||||
@ -955,9 +965,12 @@ JS
|
|||||||
$fileData .= implode($separator, $columnData);
|
$fileData .= implode($separator, $columnData);
|
||||||
$fileData .= "\n";
|
$fileData .= "\n";
|
||||||
}
|
}
|
||||||
return HTTPRequest::send_file($fileData, $fileName);
|
|
||||||
|
$numColumns = count($columnData);
|
||||||
|
$numRows = $fieldItems->count();
|
||||||
|
return $fileData;
|
||||||
} else {
|
} else {
|
||||||
user_error("No records found", E_USER_ERROR);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,127 +0,0 @@
|
|||||||
/**
|
|
||||||
* @author Tim Copeland
|
|
||||||
*/
|
|
||||||
// Browser detection
|
|
||||||
|
|
||||||
var BrowserDetect = {
|
|
||||||
init: function () {
|
|
||||||
this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
|
|
||||||
this.version = this.searchVersion(navigator.userAgent)
|
|
||||||
|| this.searchVersion(navigator.appVersion)
|
|
||||||
|| "an unknown version";
|
|
||||||
this.OS = this.searchString(this.dataOS) || "an unknown OS";
|
|
||||||
},
|
|
||||||
searchString: function (data) {
|
|
||||||
for (var i=0;i<data.length;i++) {
|
|
||||||
var dataString = data[i].string;
|
|
||||||
var dataProp = data[i].prop;
|
|
||||||
this.versionSearchString = data[i].versionSearch || data[i].identity;
|
|
||||||
if (dataString) {
|
|
||||||
if (dataString.indexOf(data[i].subString) != -1)
|
|
||||||
return data[i].identity;
|
|
||||||
}
|
|
||||||
else if (dataProp)
|
|
||||||
return data[i].identity;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
searchVersion: function (dataString) {
|
|
||||||
var index = dataString.indexOf(this.versionSearchString);
|
|
||||||
if (index == -1) return;
|
|
||||||
return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
|
|
||||||
},
|
|
||||||
dataBrowser: [
|
|
||||||
{
|
|
||||||
string: navigator.vendor,
|
|
||||||
subString: "Apple",
|
|
||||||
identity: "Safari"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
prop: window.opera,
|
|
||||||
identity: "Opera"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
string: navigator.vendor,
|
|
||||||
subString: "iCab",
|
|
||||||
identity: "iCab"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
string: navigator.vendor,
|
|
||||||
subString: "KDE",
|
|
||||||
identity: "Konqueror"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
string: navigator.userAgent,
|
|
||||||
subString: "Firefox",
|
|
||||||
identity: "Firefox"
|
|
||||||
},
|
|
||||||
{ // for newer Netscapes (6+)
|
|
||||||
string: navigator.userAgent,
|
|
||||||
subString: "Netscape",
|
|
||||||
identity: "Netscape"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
string: navigator.userAgent,
|
|
||||||
subString: "MSIE",
|
|
||||||
identity: "Explorer",
|
|
||||||
versionSearch: "MSIE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
string: navigator.userAgent,
|
|
||||||
subString: "Gecko",
|
|
||||||
identity: "Mozilla",
|
|
||||||
versionSearch: "rv"
|
|
||||||
},
|
|
||||||
{ // for older Netscapes (4-)
|
|
||||||
string: navigator.userAgent,
|
|
||||||
subString: "Mozilla",
|
|
||||||
identity: "Netscape",
|
|
||||||
versionSearch: "Mozilla"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
dataOS : [
|
|
||||||
{
|
|
||||||
string: navigator.platform,
|
|
||||||
subString: "Win",
|
|
||||||
identity: "Windows"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
string: navigator.platform,
|
|
||||||
subString: "Mac",
|
|
||||||
identity: "Mac"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
string: navigator.platform,
|
|
||||||
subString: "Linux",
|
|
||||||
identity: "Linux"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
};
|
|
||||||
BrowserDetect.init();
|
|
||||||
|
|
||||||
Behaviour.register({
|
|
||||||
'#all' : {
|
|
||||||
initialise: function() {
|
|
||||||
if( BrowserDetect.browser == "Firefox" /*&& BrowserDetect.version >= 1.5*/ ||
|
|
||||||
(BrowserDetect.browser == "Explorer" && BrowserDetect.version >= 6) ||
|
|
||||||
(BrowserDetect.browser == "Mozilla" && BrowserDetect.version >= 1.2)
|
|
||||||
) {
|
|
||||||
|
|
||||||
$("noSupport").style.display = "none"
|
|
||||||
$("supported").style.display = "block"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//center the all holder
|
|
||||||
$("all").style.left = (document.body.offsetWidth /2) - ( $("all").offsetWidth /2) -2 + "px"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
'#LoginForm_LoginForm_action_login' : {
|
|
||||||
onclick: function() {
|
|
||||||
document.body.style.backgroundColor = "white";
|
|
||||||
// Effect.Puff("all");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
@ -136,8 +136,10 @@ TableListField.prototype = {
|
|||||||
{
|
{
|
||||||
postBody: 'update=1',
|
postBody: 'update=1',
|
||||||
onComplete: function(response) {
|
onComplete: function(response) {
|
||||||
Element.replace(this.id, response.responseText)
|
Element.replace(this.id, response.responseText);
|
||||||
Behaviour.apply($(this.id))
|
// reapply behaviour and reattach methods to TF container node
|
||||||
|
// e.g. <div class="TableListField">
|
||||||
|
Behaviour.apply($(this.id), true);
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -134,7 +134,7 @@ TreeDropdownField.prototype = {
|
|||||||
this.treeShown = false;
|
this.treeShown = false;
|
||||||
if(this.itemTree) {
|
if(this.itemTree) {
|
||||||
this.itemTree.style.display = 'none';
|
this.itemTree.style.display = 'none';
|
||||||
Event.stopObserving(document, 'click', this.bound_testForBlur);
|
if(this.bound_testForBlur) Event.stopObserving(document, 'click', this.bound_testForBlur);
|
||||||
// this.editLink.style.display = this.humanItems.style.display = 'block';
|
// this.editLink.style.display = this.humanItems.style.display = 'block';
|
||||||
this.unstretchIframeIfNeeded();
|
this.unstretchIframeIfNeeded();
|
||||||
}
|
}
|
||||||
|
5
main.php
5
main.php
@ -57,7 +57,7 @@ if($majorVersion < 5) {
|
|||||||
*/
|
*/
|
||||||
require_once("core/Core.php");
|
require_once("core/Core.php");
|
||||||
|
|
||||||
header("Content-type: text/html; charset=\"utf-8\"");
|
if(!headers_sent()) header("Content-type: text/html; charset=\"utf-8\"");
|
||||||
if (function_exists('mb_http_output')) {
|
if (function_exists('mb_http_output')) {
|
||||||
mb_http_output('UTF-8');
|
mb_http_output('UTF-8');
|
||||||
mb_internal_encoding('UTF-8');
|
mb_internal_encoding('UTF-8');
|
||||||
@ -86,8 +86,7 @@ if (isset($_GET['url'])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fix glitches in URL generation
|
// Fix glitches in URL generation
|
||||||
if (substr($url, 0, strlen(BASE_URL)) == BASE_URL) $url = substr($url, strlen(BASE_URL));
|
if (substr(strtolower($url), 0, strlen(BASE_URL)) == strtolower(BASE_URL)) $url = substr($url, strlen(BASE_URL));
|
||||||
|
|
||||||
|
|
||||||
if (isset($_GET['debug_profile'])) {
|
if (isset($_GET['debug_profile'])) {
|
||||||
Profiler::init();
|
Profiler::init();
|
||||||
|
@ -213,17 +213,20 @@ class SSHTMLBBCodeParser
|
|||||||
$filter = ucfirst($filter);
|
$filter = ucfirst($filter);
|
||||||
if (!array_key_exists($filter, $this->_filters)) {
|
if (!array_key_exists($filter, $this->_filters)) {
|
||||||
$class = 'SSHTMLBBCodeParser_Filter_'.$filter;
|
$class = 'SSHTMLBBCodeParser_Filter_'.$filter;
|
||||||
@include_once 'BBCodeParser/Filter/'.$filter.'.php';
|
if (fopen('BBCodeParser/Filter/'.$filter.'.php','r',true)) {
|
||||||
|
include_once 'BBCodeParser/Filter/'.$filter.'.php';
|
||||||
|
}
|
||||||
if (!class_exists($class)) {
|
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->_filters[$filter] = new $class;
|
||||||
$this->_definedTags = array_merge(
|
$this->_definedTags = array_merge(
|
||||||
$this->_definedTags,
|
$this->_definedTags,
|
||||||
$this->_filters[$filter]->_definedTags
|
$this->_filters[$filter]->_definedTags
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
9
sake
9
sake
@ -62,10 +62,17 @@ if [ "$1" = "-start" ]; then
|
|||||||
sake=`realpath $0`
|
sake=`realpath $0`
|
||||||
base=`realpath $base`
|
base=`realpath $base`
|
||||||
|
|
||||||
|
# if third argument is not explicitly given, copy from second argument
|
||||||
|
if [ "$3" = "" ]; then
|
||||||
|
url=$2
|
||||||
|
else
|
||||||
|
url=$3
|
||||||
|
fi
|
||||||
|
|
||||||
# TODO: Give a globally unique processname by including the projectname as well
|
# TODO: Give a globally unique processname by including the projectname as well
|
||||||
processname=$2
|
processname=$2
|
||||||
|
|
||||||
daemon -n $processname -r -D $base --pidfile=$pidfile --stdout=$outlog --stderr=$errlog $sake $2 $3
|
daemon -n $processname -r -D $base --pidfile=$pidfile --stdout=$outlog --stderr=$errlog $sake $url
|
||||||
else
|
else
|
||||||
echo "Service $2 seems to already be running"
|
echo "Service $2 seems to already be running"
|
||||||
fi
|
fi
|
||||||
|
@ -134,5 +134,4 @@ class AdvancedSearchForm extends SearchForm {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -31,6 +31,11 @@ class SearchForm extends Form {
|
|||||||
*/
|
*/
|
||||||
protected $pageLength = 10;
|
protected $pageLength = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classes to search
|
||||||
|
*/
|
||||||
|
protected $classesToSearch = array("SiteTree", "File");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param Controller $controller
|
* @param Controller $controller
|
||||||
@ -73,6 +78,19 @@ class SearchForm extends Form {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the classes to search.
|
||||||
|
* Currently you can only choose from "SiteTree" and "File", but a future version might improve this.
|
||||||
|
*/
|
||||||
|
function classesToSearch($classes) {
|
||||||
|
$illegalClasses = array_diff($classes, array('SiteTree', 'File'));
|
||||||
|
if($illegalClasses) {
|
||||||
|
user_error("SearchForm::classesToSearch() passed illegal classes '" . implode("', '", $illegalClasses) . "'. At this stage, only File and SiteTree are allowed", E_USER_WARNING);
|
||||||
|
}
|
||||||
|
$legalClasses = array_intersect($classes, array('SiteTree', 'File'));
|
||||||
|
$this->classesToSearch = $legalClasses;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return dataObjectSet of the results using $_REQUEST to get info from form.
|
* Return dataObjectSet of the results using $_REQUEST to get info from form.
|
||||||
* Wraps around {@link searchEngine()}.
|
* Wraps around {@link searchEngine()}.
|
||||||
@ -150,66 +168,71 @@ class SearchForm extends Form {
|
|||||||
public function searchEngine($keywords, $pageLength = null, $sortBy = "Relevance DESC", $extraFilter = "", $booleanSearch = false, $alternativeFileFilter = "", $invertedMatch = false) {
|
public function searchEngine($keywords, $pageLength = null, $sortBy = "Relevance DESC", $extraFilter = "", $booleanSearch = false, $alternativeFileFilter = "", $invertedMatch = false) {
|
||||||
if(!$pageLength) $pageLength = $this->pageLength;
|
if(!$pageLength) $pageLength = $this->pageLength;
|
||||||
$fileFilter = '';
|
$fileFilter = '';
|
||||||
|
|
||||||
$keywords = Convert::raw2sql($keywords);
|
$keywords = Convert::raw2sql($keywords);
|
||||||
$htmlEntityKeywords = htmlentities($keywords);
|
$htmlEntityKeywords = htmlentities($keywords);
|
||||||
|
|
||||||
|
$extraFilters = array('SiteTree' => '', 'File' => '');
|
||||||
|
|
||||||
if($booleanSearch) $boolean = "IN BOOLEAN MODE";
|
if($booleanSearch) $boolean = "IN BOOLEAN MODE";
|
||||||
|
|
||||||
if($extraFilter) {
|
if($extraFilter) {
|
||||||
$extraFilter = " AND $extraFilter";
|
$extraFilters['SiteTree'] = " AND $extraFilter";
|
||||||
$fileFilter = ($alternativeFileFilter) ? " AND $alternativeFileFilter" : $extraFilter;
|
|
||||||
|
if($alternativeFileFilter) $extraFilters['File'] = " AND $alternativeFileFilter";
|
||||||
|
else $extraFilters['File'] = $extraFilters['SiteTree'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->showInSearchTurnOn) $extraFilter .= " AND showInSearch <> 0";
|
if($this->showInSearchTurnOn) $extraFilters['SiteTree'] .= " AND showInSearch <> 0";
|
||||||
|
|
||||||
$start = isset($_GET['start']) ? (int)$_GET['start'] : 0;
|
$start = isset($_GET['start']) ? (int)$_GET['start'] : 0;
|
||||||
$limit = $start . ", " . (int) $pageLength;
|
$limit = $start . ", " . (int) $pageLength;
|
||||||
|
|
||||||
$notMatch = $invertedMatch ? "NOT " : "";
|
$notMatch = $invertedMatch ? "NOT " : "";
|
||||||
if($keywords) {
|
if($keywords) {
|
||||||
$matchContent = "
|
$match['SiteTree'] = "MATCH (Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords) AGAINST ('$keywords' $boolean)";
|
||||||
MATCH (Title, MenuTitle, MetaTitle, MetaDescription, MetaKeywords) AGAINST ('$keywords' $boolean)
|
$match['File'] = "MATCH (Filename, Title, Content) AGAINST ('$keywords' $boolean) AND ClassName = 'File'";
|
||||||
+ MATCH (Content) AGAINST ('$htmlEntityKeywords' $boolean)
|
|
||||||
";
|
|
||||||
$matchFile = "MATCH (Filename, Title, Content) AGAINST ('$keywords' $boolean) AND ClassName = 'File'";
|
|
||||||
|
|
||||||
// We make the relevance search by converting a boolean mode search into a normal one
|
// We make the relevance search by converting a boolean mode search into a normal one
|
||||||
$relevanceKeywords = str_replace(array('*','+','-'),'',$keywords);
|
$relevanceKeywords = str_replace(array('*','+','-'),'',$keywords);
|
||||||
$htmlEntityRelevanceKeywords = str_replace(array('*','+','-'),'',$htmlEntityKeywords);
|
$htmlEntityRelevanceKeywords = str_replace(array('*','+','-'),'',$htmlEntityKeywords);
|
||||||
$relevanceContent = "
|
$relevance['SiteTree'] = "MATCH (Title) AGAINST ('$relevanceKeywords') + MATCH(Content) AGAINST ('$htmlEntityRelevanceKeywords') + MATCH (Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords) AGAINST ('$relevanceKeywords')";
|
||||||
MATCH (Title) AGAINST ('$relevanceKeywords')
|
$relevance['File'] = "MATCH (Filename, Title, Content) AGAINST ('$relevanceKeywords')";
|
||||||
+ MATCH(Content) AGAINST ('$htmlEntityRelevanceKeywords')
|
|
||||||
+ MATCH (Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords) AGAINST ('$relevanceKeywords')
|
|
||||||
";
|
|
||||||
$relevanceFile = "MATCH (Filename, Title, Content) AGAINST ('$relevanceKeywords')";
|
|
||||||
} else {
|
} else {
|
||||||
$relevanceContent = $relevanceFile = 1;
|
$relevance['SiteTree'] = $relevance['File'] = 1;
|
||||||
$matchContent = $matchFile = "1 = 1";
|
$match['SiteTree'] = $match['File'] = "1 = 1";
|
||||||
}
|
}
|
||||||
|
|
||||||
$queryContent = singleton('SiteTree')->extendedSQL($notMatch . $matchContent . $extraFilter, "");
|
// Generate initial queries and base table names
|
||||||
|
$baseClasses = array('SiteTree' => '', 'File' => '');
|
||||||
|
foreach($this->classesToSearch as $class) {
|
||||||
|
$queries[$class] = singleton($class)->extendedSQL($notMatch . $match[$class] . $extraFilters[$class], "");
|
||||||
|
$baseClasses[$class] = reset($queries[$class]->from);
|
||||||
|
}
|
||||||
|
|
||||||
$baseClass = reset($queryContent->from);
|
// Make column selection lists
|
||||||
// There's no need to do all that joining
|
$select = array(
|
||||||
$queryContent->from = array(str_replace(array('`','"'),'',$baseClass) => $baseClass);
|
'SiteTree' => array("ClassName","$baseClasses[SiteTree].ID","ParentID","Title","URLSegment","Content","LastEdited","Created","_utf8'' AS Filename", "_utf8'' AS Name", "$relevance[SiteTree] AS Relevance", "CanViewType"),
|
||||||
$queryContent->select = array("\"ClassName\"","$baseClass.\"ID\"","\"ParentID\"","\"Title\"",
|
'File' => array("ClassName","$baseClasses[File].ID","_utf8'' AS ParentID","Title","_utf8'' AS URLSegment","Content","LastEdited","Created","Filename","Name","$relevance[File] AS Relevance","NULL AS CanViewType"),
|
||||||
"\"URLSegment\"","\"Content\"","\"LastEdited\"","\"Created\"","'' AS \"Filename\"",
|
);
|
||||||
"'' AS \"Name\"", "$relevanceContent AS \"Relevance\"", "\"CanViewType\"");
|
|
||||||
$queryContent->orderby = null;
|
|
||||||
|
|
||||||
$queryFiles = singleton('File')->extendedSQL($notMatch . $matchFile . $fileFilter, "");
|
// Process queries
|
||||||
$baseClass = reset($queryFiles->from);
|
foreach($this->classesToSearch as $class) {
|
||||||
// There's no need to do all that joining
|
// There's no need to do all that joining
|
||||||
$queryFiles->from = array(str_replace(array('`','"'),'',$baseClass) => $baseClass);
|
$queries[$class]->from = array(str_replace('`','',$baseClasses[$class]) => $baseClasses[$class]);
|
||||||
$queryFiles->select = array("\"ClassName\"","$baseClass.\"ID\"","'' AS \"ParentID\"","\"Title\"",
|
$queries[$class]->select = $select[$class];
|
||||||
"'' AS \"URLSegment\"","\"Content\"","\"LastEdited\"","\"Created\"","\"Filename\"","\"Name\"",
|
$queries[$class]->orderby = null;
|
||||||
"$relevanceFile AS \"Relevance\"","NULL AS \"CanViewType\"");
|
}
|
||||||
$queryFiles->orderby = null;
|
|
||||||
|
|
||||||
$fullQuery = $queryContent->sql() . " UNION " . $queryFiles->sql() . " ORDER BY $sortBy LIMIT $limit";
|
// Combine queries
|
||||||
$totalCount = $queryContent->unlimitedRowCount() + $queryFiles->unlimitedRowCount();
|
$querySQLs = array();
|
||||||
|
$totalCount = 0;
|
||||||
|
foreach($queries as $query) {
|
||||||
|
$querySQLs[] = $query->sql();
|
||||||
|
$totalCount += $query->unlimitedRowCount();
|
||||||
|
}
|
||||||
|
$fullQuery = implode(" UNION ", $querySQLs) . " ORDER BY $sortBy LIMIT $limit";
|
||||||
|
|
||||||
|
// Get records
|
||||||
$records = DB::query($fullQuery);
|
$records = DB::query($fullQuery);
|
||||||
|
|
||||||
foreach($records as $record)
|
foreach($records as $record)
|
||||||
|
@ -186,5 +186,4 @@ abstract class Authenticator extends Object {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -100,5 +100,4 @@ class ChangePasswordForm extends Form {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -279,6 +279,14 @@ class Group extends DataObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function canView() {
|
||||||
|
if($this->hasMethod('alternateCanView')) return $this->alternateCanView();
|
||||||
|
else {
|
||||||
|
return Permission::check("ADMIN")
|
||||||
|
|| (Member::currentUserID() && !DataObject::get("Permission", "GroupID = $this->ID AND Code = 'ADMIN'"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all of the children for the CMS Tree.
|
* Returns all of the children for the CMS Tree.
|
||||||
* Filters to only those groups that the current user can edit
|
* Filters to only those groups that the current user can edit
|
||||||
|
@ -27,6 +27,12 @@ class LoginAttempt extends DataObject {
|
|||||||
'Member' => 'Member', // only linked if the member actually exists
|
'Member' => 'Member', // only linked if the member actually exists
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static $has_many = array();
|
||||||
|
|
||||||
|
static $many_many = array();
|
||||||
|
|
||||||
|
static $belongs_many_many = array();
|
||||||
|
|
||||||
function fieldLabels() {
|
function fieldLabels() {
|
||||||
$labels = parent::fieldLabels();
|
$labels = parent::fieldLabels();
|
||||||
$labels['Email'] = _t('LoginAttempt.Email', 'Email Address');
|
$labels['Email'] = _t('LoginAttempt.Email', 'Email Address');
|
||||||
|
@ -7,17 +7,16 @@
|
|||||||
class Member extends DataObject {
|
class Member extends DataObject {
|
||||||
|
|
||||||
static $db = array(
|
static $db = array(
|
||||||
'FirstName' => "Varchar",
|
'FirstName' => 'Varchar',
|
||||||
'Surname' => "Varchar",
|
'Surname' => 'Varchar',
|
||||||
'Email' => "Varchar",
|
'Email' => 'Varchar',
|
||||||
'Password' => "Varchar(64)", // support for up to SHA256!
|
'Password' => 'Varchar(64)', // support for up to SHA256!
|
||||||
'RememberLoginToken' => "Varchar(50)",
|
'RememberLoginToken' => 'Varchar(50)',
|
||||||
'NumVisit' => "Int",
|
'NumVisit' => 'Int',
|
||||||
'LastVisited' => 'SSDatetime',
|
'LastVisited' => 'SSDatetime',
|
||||||
'Bounced' => 'Boolean', // Note: This does not seem to be used anywhere.
|
'Bounced' => 'Boolean', // Note: This does not seem to be used anywhere.
|
||||||
'AutoLoginHash' => 'Varchar(30)',
|
'AutoLoginHash' => 'Varchar(30)',
|
||||||
'AutoLoginExpired' => 'SSDatetime',
|
'AutoLoginExpired' => 'SSDatetime',
|
||||||
'BlacklistedEmail' => 'Boolean',
|
|
||||||
'PasswordEncryption' => "Enum('none', 'none')",
|
'PasswordEncryption' => "Enum('none', 'none')",
|
||||||
'Salt' => 'Varchar(50)',
|
'Salt' => 'Varchar(50)',
|
||||||
'PasswordExpiry' => 'Date',
|
'PasswordExpiry' => 'Date',
|
||||||
@ -26,11 +25,13 @@ class Member extends DataObject {
|
|||||||
);
|
);
|
||||||
|
|
||||||
static $belongs_many_many = array(
|
static $belongs_many_many = array(
|
||||||
"Groups" => "Group",
|
'Groups' => 'Group',
|
||||||
);
|
);
|
||||||
|
|
||||||
static $has_one = array();
|
static $has_one = array();
|
||||||
|
|
||||||
static $has_many = array();
|
static $has_many = array();
|
||||||
|
|
||||||
static $many_many = array();
|
static $many_many = array();
|
||||||
|
|
||||||
static $many_many_extraFields = array();
|
static $many_many_extraFields = array();
|
||||||
@ -68,6 +69,15 @@ class Member extends DataObject {
|
|||||||
'Email',
|
'Email',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The unique field used to identify this member.
|
||||||
|
* By default, it's "Email", but another common
|
||||||
|
* field could be Username.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected static $unique_identifier_field = 'Email';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link PasswordValidator} object for validating user's password
|
* {@link PasswordValidator} object for validating user's password
|
||||||
*/
|
*/
|
||||||
@ -130,8 +140,30 @@ class Member extends DataObject {
|
|||||||
// This can be called via CLI during testing.
|
// This can be called via CLI during testing.
|
||||||
if(Director::is_cli()) return;
|
if(Director::is_cli()) return;
|
||||||
|
|
||||||
$file = ""; $line = "";
|
$file = '';
|
||||||
if (!headers_sent($file, $line)) session_regenerate_id(true);
|
$line = '';
|
||||||
|
|
||||||
|
if(!headers_sent($file, $line)) session_regenerate_id(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the field used for uniquely identifying a member
|
||||||
|
* in the database. {@see Member::$unique_identifier_field}
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
static function get_unique_identifier_field() {
|
||||||
|
return self::$unique_identifier_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the field used for uniquely identifying a member
|
||||||
|
* in the database. {@see Member::$unique_identifier_field}
|
||||||
|
*
|
||||||
|
* @param $field The field name to set as the unique field
|
||||||
|
*/
|
||||||
|
static function set_unique_identifier_field($field) {
|
||||||
|
self::$unique_identifier_field = $field;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -198,7 +230,10 @@ class Member extends DataObject {
|
|||||||
Session::set('Member.FailedLogins', $failedLogins);
|
Session::set('Member.FailedLogins', $failedLogins);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->LockedOutUntil = null;
|
// Don't set column if its not built yet (the login might be precursor to a /dev/build...)
|
||||||
|
if(array_key_exists('LockedOutUntil', DB::fieldList('Member'))) {
|
||||||
|
$this->LockedOutUntil = null;
|
||||||
|
}
|
||||||
|
|
||||||
$this->write();
|
$this->write();
|
||||||
|
|
||||||
@ -388,30 +423,6 @@ class Member extends DataObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the members email address to the blacklist
|
|
||||||
*
|
|
||||||
* With this method the blacklisted email table is updated to ensure that
|
|
||||||
* no promotional material is sent to the member (newsletters).
|
|
||||||
* Standard system messages are still sent such as receipts.
|
|
||||||
*
|
|
||||||
* @param bool $val Set to TRUE if the address should be added to the
|
|
||||||
* blacklist, otherwise to FALSE.
|
|
||||||
*/
|
|
||||||
function setBlacklistedEmail($val) {
|
|
||||||
if($val && $this->Email) {
|
|
||||||
$blacklisting = new Email_BlackList();
|
|
||||||
$blacklisting->BlockedEmail = $this->Email;
|
|
||||||
$blacklisting->MemberID = $this->ID;
|
|
||||||
$blacklisting->write();
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->setField("BlacklistedEmail", $val);
|
|
||||||
// Save the BlacklistedEmail field to the Member table
|
|
||||||
$this->write();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate a random password, with randomiser to kick in if there's no words file on the
|
* Generate a random password, with randomiser to kick in if there's no words file on the
|
||||||
* filesystem.
|
* filesystem.
|
||||||
@ -437,29 +448,18 @@ class Member extends DataObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler called before writing to the database
|
* Event handler called before writing to the database.
|
||||||
*
|
|
||||||
* If an email's filled out look for a record with the same email and if
|
|
||||||
* found update this record to merge with that member.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function onBeforeWrite() {
|
function onBeforeWrite() {
|
||||||
if($this->SetPassword) $this->Password = $this->SetPassword;
|
if($this->SetPassword) $this->Password = $this->SetPassword;
|
||||||
|
|
||||||
if($this->Email) {
|
$identifierField = self::$unique_identifier_field;
|
||||||
if($this->ID) {
|
if($this->$identifierField) {
|
||||||
$idClause = "AND \"Member\".\"ID\" <> $this->ID";
|
$idClause = ($this->ID) ? " AND \"Member\".\"ID\" <> $this->ID" : '';
|
||||||
} else {
|
$SQL_identifierField = Convert::raw2sql($this->$identifierField);
|
||||||
$idClause = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
$existingRecord = DataObject::get_one(
|
|
||||||
"Member", "\"Email\" = '" . addslashes($this->Email) . "' $idClause");
|
|
||||||
|
|
||||||
// Debug::message("Found an existing member for email $this->Email");
|
|
||||||
|
|
||||||
|
$existingRecord = DataObject::get_one('Member', "\"$identifierField\" = '{$SQL_identifierField}'{$idClause}");
|
||||||
if($existingRecord) {
|
if($existingRecord) {
|
||||||
$newID = $existingRecord->ID;
|
$newID = $existingRecord->ID;
|
||||||
if($this->ID) {
|
if($this->ID) {
|
||||||
@ -761,15 +761,13 @@ class Member extends DataObject {
|
|||||||
$groupIDList = array();
|
$groupIDList = array();
|
||||||
|
|
||||||
if(is_a($groups, 'DataObjectSet')) {
|
if(is_a($groups, 'DataObjectSet')) {
|
||||||
foreach($groups as $group)
|
foreach($groups as $group) {
|
||||||
$groupIDList[] = $group->ID;
|
$groupIDList[] = $group->ID;
|
||||||
|
}
|
||||||
} elseif(is_array($groups)) {
|
} elseif(is_array($groups)) {
|
||||||
$groupIDList = $groups;
|
$groupIDList = $groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if( empty( $groupIDList ) )
|
|
||||||
return Member::map(); */
|
|
||||||
|
|
||||||
$filterClause = ($groupIDList)
|
$filterClause = ($groupIDList)
|
||||||
? "\"GroupID\" IN (" . implode( ',', $groupIDList ) . ")"
|
? "\"GroupID\" IN (" . implode( ',', $groupIDList ) . ")"
|
||||||
: "";
|
: "";
|
||||||
@ -792,8 +790,7 @@ class Member extends DataObject {
|
|||||||
* @return array Groups in which the member is NOT in.
|
* @return array Groups in which the member is NOT in.
|
||||||
*/
|
*/
|
||||||
public function memberNotInGroups($groupList, $memberGroups = null){
|
public function memberNotInGroups($groupList, $memberGroups = null){
|
||||||
if(!$memberGroups)
|
if(!$memberGroups) $memberGroups = $this->Groups();
|
||||||
$memberGroups = $this->Groups();
|
|
||||||
|
|
||||||
foreach($memberGroups as $group) {
|
foreach($memberGroups as $group) {
|
||||||
if(in_array($group->Code, $groupList)) {
|
if(in_array($group->Code, $groupList)) {
|
||||||
@ -801,6 +798,7 @@ class Member extends DataObject {
|
|||||||
unset($groupList[$index]);
|
unset($groupList[$index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $groupList;
|
return $groupList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -846,11 +844,6 @@ class Member extends DataObject {
|
|||||||
$locale
|
$locale
|
||||||
));
|
));
|
||||||
|
|
||||||
$mainFields->insertAfter(
|
|
||||||
new TreeMultiselectField("Groups", _t("Member.SECURITYGROUPS", "Security groups")),
|
|
||||||
'Locale'
|
|
||||||
);
|
|
||||||
|
|
||||||
$mainFields->removeByName('Bounced');
|
$mainFields->removeByName('Bounced');
|
||||||
$mainFields->removeByName('RememberLoginToken');
|
$mainFields->removeByName('RememberLoginToken');
|
||||||
$mainFields->removeByName('AutoLoginHash');
|
$mainFields->removeByName('AutoLoginHash');
|
||||||
@ -861,14 +854,14 @@ class Member extends DataObject {
|
|||||||
$mainFields->removeByName('Salt');
|
$mainFields->removeByName('Salt');
|
||||||
$mainFields->removeByName('NumVisit');
|
$mainFields->removeByName('NumVisit');
|
||||||
$mainFields->removeByName('LastVisited');
|
$mainFields->removeByName('LastVisited');
|
||||||
$mainFields->removeByName('BlacklistedEmail');
|
|
||||||
|
|
||||||
$fields->removeByName('Subscriptions');
|
$fields->removeByName('Subscriptions');
|
||||||
$fields->removeByName('UnsubscribedRecords');
|
|
||||||
// Groups relation will get us into logical conflicts because
|
// Groups relation will get us into logical conflicts because
|
||||||
// Members are displayed within group edit form in SecurityAdmin
|
// Members are displayed within group edit form in SecurityAdmin
|
||||||
$fields->removeByName('Groups');
|
$fields->removeByName('Groups');
|
||||||
|
|
||||||
|
$this->extend('updateCMSFields', $fields);
|
||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -935,10 +928,6 @@ class Member extends DataObject {
|
|||||||
if($valid->valid()) {
|
if($valid->valid()) {
|
||||||
$this->AutoLoginHash = null;
|
$this->AutoLoginHash = null;
|
||||||
$this->write();
|
$this->write();
|
||||||
|
|
||||||
// Emails will be sent by Member::onBeforeWrite().
|
|
||||||
|
|
||||||
//$this->sendinfo('changePassword', array('CleartextPassword' => $password));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $valid;
|
return $valid;
|
||||||
@ -1372,26 +1361,35 @@ class Member_Validator extends RequiredFields {
|
|||||||
function php($data) {
|
function php($data) {
|
||||||
$valid = parent::php($data);
|
$valid = parent::php($data);
|
||||||
|
|
||||||
$member = DataObject::get_one('Member',
|
$identifierField = Member::get_unique_identifier_field();
|
||||||
"\"Email\" = '". Convert::raw2sql($data['Email']) ."'");
|
|
||||||
|
|
||||||
// if we are in a complex table field popup, use ctf[childID], else use
|
$SQL_identifierField = Convert::raw2sql($data[$identifierField]);
|
||||||
// ID
|
$member = DataObject::get_one('Member', "\"$identifierField\" = '{$SQL_identifierField}'");
|
||||||
if(isset($_REQUEST['ctf']['childID']))
|
|
||||||
|
// if we are in a complex table field popup, use ctf[childID], else use ID
|
||||||
|
if(isset($_REQUEST['ctf']['childID'])) {
|
||||||
$id = $_REQUEST['ctf']['childID'];
|
$id = $_REQUEST['ctf']['childID'];
|
||||||
elseif(isset($_REQUEST['ID']))
|
} elseif(isset($_REQUEST['ID'])) {
|
||||||
$id = $_REQUEST['ID'];
|
$id = $_REQUEST['ID'];
|
||||||
else
|
} else {
|
||||||
$id = null;
|
$id = null;
|
||||||
|
|
||||||
if($id && is_object($member) && $member->ID != $id) {
|
|
||||||
$emailField = $this->form->dataFieldByName('Email');
|
|
||||||
$this->validationError($emailField->id(),
|
|
||||||
_t('Member.VALIDATIONMEMBEREXISTS', "There already exists a member with this email"),
|
|
||||||
"required");
|
|
||||||
$valid = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($id && is_object($member) && $member->ID != $id) {
|
||||||
|
$uniqueField = $this->form->dataFieldByName($identifierField);
|
||||||
|
$this->validationError(
|
||||||
|
$uniqueField->id(),
|
||||||
|
sprintf(
|
||||||
|
_t(
|
||||||
|
'Member.VALIDATIONMEMBEREXISTS',
|
||||||
|
'A member already exists with the same %s'
|
||||||
|
),
|
||||||
|
strtolower($identifierField)
|
||||||
|
),
|
||||||
|
'required'
|
||||||
|
);
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Execute the validators on the extensions
|
// Execute the validators on the extensions
|
||||||
if($this->extension_instances) {
|
if($this->extension_instances) {
|
||||||
@ -1402,7 +1400,6 @@ class Member_Validator extends RequiredFields {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return $valid;
|
return $valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1429,9 +1426,7 @@ class Member_Validator extends RequiredFields {
|
|||||||
return $js;
|
return $js;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the static DB variables to add the supported encryption
|
// Initialize the static DB variables to add the supported encryption
|
||||||
// algorithms to the PasswordEncryption Enum field
|
// algorithms to the PasswordEncryption Enum field
|
||||||
Member::init_db_fields();
|
Member::init_db_fields();
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
@ -114,5 +114,4 @@ class MemberAuthenticator extends Authenticator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -37,6 +37,15 @@ class MemberLoginForm extends LoginForm {
|
|||||||
Requirements::css($customCSS);
|
Requirements::css($customCSS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Focus on the email input when the page is loaded
|
||||||
|
Requirements::customScript("
|
||||||
|
(function($){
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#Email input').focus();
|
||||||
|
});
|
||||||
|
})(jQuery);
|
||||||
|
");
|
||||||
|
|
||||||
if(isset($_REQUEST['BackURL'])) {
|
if(isset($_REQUEST['BackURL'])) {
|
||||||
$backURL = $_REQUEST['BackURL'];
|
$backURL = $_REQUEST['BackURL'];
|
||||||
} else {
|
} else {
|
||||||
@ -50,8 +59,8 @@ class MemberLoginForm extends LoginForm {
|
|||||||
if(!$fields) {
|
if(!$fields) {
|
||||||
$fields = new FieldSet(
|
$fields = new FieldSet(
|
||||||
new HiddenField("AuthenticationMethod", null, $this->authenticator_class, $this),
|
new HiddenField("AuthenticationMethod", null, $this->authenticator_class, $this),
|
||||||
new TextField("Email", _t('Member.EMAIL'), Session::get('SessionForms.MemberLoginForm.Email'), null, $this),
|
new TextField("Email", _t('Member.EMAIL', 'Email'), Session::get('SessionForms.MemberLoginForm.Email'), null, $this),
|
||||||
new PasswordField("Password", _t('Member.PASSWORD'), null, $this)
|
new PasswordField("Password", _t('Member.PASSWORD', 'Password'))
|
||||||
);
|
);
|
||||||
if(Security::$autologin_enabled) {
|
if(Security::$autologin_enabled) {
|
||||||
$fields->push(new CheckboxField(
|
$fields->push(new CheckboxField(
|
||||||
@ -231,6 +240,4 @@ class MemberLoginForm extends LoginForm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -12,9 +12,15 @@ class MemberPassword extends DataObject {
|
|||||||
);
|
);
|
||||||
|
|
||||||
static $has_one = array(
|
static $has_one = array(
|
||||||
'Member' => 'Member',
|
'Member' => 'Member'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static $has_many = array();
|
||||||
|
|
||||||
|
static $many_many = array();
|
||||||
|
|
||||||
|
static $belongs_many_many = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log a password change from the given member.
|
* Log a password change from the given member.
|
||||||
* Call MemberPassword::log($this) from within Member whenever the password is changed.
|
* Call MemberPassword::log($this) from within Member whenever the password is changed.
|
||||||
|
@ -22,6 +22,11 @@ class Permission extends DataObject {
|
|||||||
static $defaults = array(
|
static $defaults = array(
|
||||||
"Type" => 1
|
"Type" => 1
|
||||||
);
|
);
|
||||||
|
static $has_many = array();
|
||||||
|
|
||||||
|
static $many_many = array();
|
||||||
|
|
||||||
|
static $belongs_many_many = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the value to use for the "Type" field if a permission should be
|
* This is the value to use for the "Type" field if a permission should be
|
||||||
@ -106,6 +111,16 @@ class Permission extends DataObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static $cache_permissions = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush the permission cache, for example if you have edited group membership or a permission record.
|
||||||
|
* @todo Call this whenever Group_Members is added to or removed from
|
||||||
|
*/
|
||||||
|
public static function flush_permission_cache() {
|
||||||
|
self::$cache_permissions = array();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that the given member has the given permission
|
* Check that the given member has the given permission
|
||||||
* @param int|Member memberID The ID of the member to check. Leave blank for the current member.
|
* @param int|Member memberID The ID of the member to check. Leave blank for the current member.
|
||||||
@ -124,6 +139,12 @@ class Permission extends DataObject {
|
|||||||
$perms_list = self::get_declared_permissions_list();
|
$perms_list = self::get_declared_permissions_list();
|
||||||
$memberID = (is_object($member)) ? $member->ID : $member;
|
$memberID = (is_object($member)) ? $member->ID : $member;
|
||||||
|
|
||||||
|
// Simple cache. This could be improved a lot by actually downloading all of the given user's permissions in one hit
|
||||||
|
$codeStr = is_array($code) ? implode(',',$code) : $code;
|
||||||
|
if($arg == 'any' && isset(self::$cache_permissions[$memberID][$codeStr])) {
|
||||||
|
return self::$cache_permissions[$memberID][$codeStr];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if(self::$declared_permissions && is_array($perms_list) && !in_array($code, $perms_list)) {
|
if(self::$declared_permissions && is_array($perms_list) && !in_array($code, $perms_list)) {
|
||||||
user_error(
|
user_error(
|
||||||
@ -134,6 +155,8 @@ class Permission extends DataObject {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$groupList = self::groupList($memberID);
|
$groupList = self::groupList($memberID);
|
||||||
if(!$groupList) return false;
|
if(!$groupList) return false;
|
||||||
|
|
||||||
@ -177,8 +200,10 @@ class Permission extends DataObject {
|
|||||||
)
|
)
|
||||||
")->value();
|
")->value();
|
||||||
|
|
||||||
if($permission)
|
if($permission) {
|
||||||
|
self::$cache_permissions[$memberID][$codeStr] = $permission;
|
||||||
return $permission;
|
return $permission;
|
||||||
|
}
|
||||||
|
|
||||||
// Strict checking disabled?
|
// Strict checking disabled?
|
||||||
if(!self::$strict_checking || !$strict) {
|
if(!self::$strict_checking || !$strict) {
|
||||||
@ -190,11 +215,14 @@ class Permission extends DataObject {
|
|||||||
AND (\"Type\" = " . self::GRANT_PERMISSION . ")
|
AND (\"Type\" = " . self::GRANT_PERMISSION . ")
|
||||||
)
|
)
|
||||||
")->value();
|
")->value();
|
||||||
|
|
||||||
if(!$hasPermission) {
|
if(!$hasPermission) {
|
||||||
|
self::$cache_permissions[$memberID][$codeStr] = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self::$cache_permissions[$memberID][$codeStr] = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,6 +572,13 @@ class Permission extends DataObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function onBeforeWrite() {
|
||||||
|
parent::onBeforeWrite();
|
||||||
|
|
||||||
|
// Just in case we've altered someone's permissions
|
||||||
|
Permission::flush_permission_cache();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -612,5 +647,4 @@ class Permission_Group {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
@ -174,20 +174,12 @@ class Security extends Controller {
|
|||||||
|
|
||||||
// Work out the right message to show
|
// Work out the right message to show
|
||||||
if(Member::currentUserID()) {
|
if(Member::currentUserID()) {
|
||||||
// user_error( 'PermFailure with member', E_USER_ERROR );
|
$message = isset($messageSet['alreadyLoggedIn']) ? $messageSet['alreadyLoggedIn'] : $messageSet['default'];
|
||||||
|
if($member = Member::currentUser()) {
|
||||||
$message = isset($messageSet['alreadyLoggedIn'])
|
$member->logOut();
|
||||||
? $messageSet['alreadyLoggedIn']
|
}
|
||||||
: $messageSet['default'];
|
|
||||||
|
|
||||||
if($member = Member::currentUser())
|
|
||||||
$member->logout();
|
|
||||||
|
|
||||||
} else if(substr(Director::history(),0,15) == 'Security/logout') {
|
} else if(substr(Director::history(),0,15) == 'Security/logout') {
|
||||||
$message = $messageSet['logInAgain']
|
$message = $messageSet['logInAgain'] ? $messageSet['logInAgain'] : $messageSet['default'];
|
||||||
? $messageSet['logInAgain']
|
|
||||||
: $messageSet['default'];
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$message = $messageSet['default'];
|
$message = $messageSet['default'];
|
||||||
}
|
}
|
||||||
@ -356,11 +348,7 @@ class Security extends Controller {
|
|||||||
Session::clear('Security.Message');
|
Session::clear('Security.Message');
|
||||||
|
|
||||||
// custom processing
|
// custom processing
|
||||||
if(SSViewer::hasTemplate("Security_login")) {
|
return $customisedController->renderWith(array('Security_login', 'Security', $this->stat('template_main')));
|
||||||
return $customisedController->renderWith(array("Security_login", $this->stat('template_main')));
|
|
||||||
} else {
|
|
||||||
return $customisedController->renderWith($this->stat('template_main'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function basicauthlogin() {
|
function basicauthlogin() {
|
||||||
@ -398,7 +386,7 @@ class Security extends Controller {
|
|||||||
));
|
));
|
||||||
|
|
||||||
//Controller::$currentController = $controller;
|
//Controller::$currentController = $controller;
|
||||||
return $customisedController->renderWith($this->stat('template_main'));
|
return $customisedController->renderWith(array('Security_lostpassword', 'Security', $this->stat('template_main')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -412,7 +400,7 @@ class Security extends Controller {
|
|||||||
$this,
|
$this,
|
||||||
'LostPasswordForm',
|
'LostPasswordForm',
|
||||||
new FieldSet(
|
new FieldSet(
|
||||||
new EmailField('Email', _t('Member.EMAIL'))
|
new EmailField('Email', _t('Member.EMAIL', 'Email'))
|
||||||
),
|
),
|
||||||
new FieldSet(
|
new FieldSet(
|
||||||
new FormAction(
|
new FormAction(
|
||||||
@ -456,7 +444,7 @@ class Security extends Controller {
|
|||||||
));
|
));
|
||||||
|
|
||||||
//Controller::$currentController = $controller;
|
//Controller::$currentController = $controller;
|
||||||
return $customisedController->renderWith($this->stat('template_main'));
|
return $customisedController->renderWith(array('Security_passwordsent', 'Security', $this->stat('template_main')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -525,7 +513,7 @@ class Security extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Controller::$currentController = $controller;
|
//Controller::$currentController = $controller;
|
||||||
return $customisedController->renderWith($this->stat('template_main'));
|
return $customisedController->renderWith(array('Security_changepassword', 'Security', $this->stat('template_main')));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -982,5 +970,4 @@ class Security extends Controller {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
@ -64,7 +64,7 @@
|
|||||||
<% end_control %>
|
<% end_control %>
|
||||||
<% control Actions %>
|
<% control Actions %>
|
||||||
<td width="16" class="action<% if Default %> default<% end_if %>"><a class="$Class" href="$Link"><% if Icon %><img src="$Icon" alt="$Label" /><% else %>$Label<% end_if %></a></td>
|
<td width="16" class="action<% if Default %> default<% end_if %>"><a class="$Class" href="$Link"><% if Icon %><img src="$Icon" alt="$Label" /><% else %>$Label<% end_if %></a></td>
|
||||||
<% end_if %>
|
<% end_control %>
|
||||||
</tr>
|
</tr>
|
||||||
<% end_control %>
|
<% end_control %>
|
||||||
<% else %>
|
<% else %>
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
||||||
<% control Items %>
|
|
||||||
<url>
|
|
||||||
<loc>$AbsoluteLink</loc>
|
|
||||||
<lastmod>$LastEdited.Format(c)</lastmod>
|
|
||||||
<% if ChangeFreq %><changefreq>$ChangeFreq</changefreq><% end_if %>
|
|
||||||
<% if Priority %><priority>$Priority</priority><% end_if %>
|
|
||||||
</url>
|
|
||||||
<% end_control %>
|
|
||||||
</urlset>
|
|
@ -1,4 +1,4 @@
|
|||||||
<div id="$id" class="$CSSClasses">
|
<div id="$id" class="$CSSClasses" href="$CurrentLink">
|
||||||
<% include TableListField_PageControls %>
|
<% include TableListField_PageControls %>
|
||||||
<table class="data">
|
<table class="data">
|
||||||
<thead>
|
<thead>
|
||||||
|
33
tests/ClassInfoTest.php
Normal file
33
tests/ClassInfoTest.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package sapphire
|
||||||
|
* @subpackage tests
|
||||||
|
*/
|
||||||
|
class ClassInfoTest extends SapphireTest {
|
||||||
|
|
||||||
|
function testSubclassesFor() {
|
||||||
|
$this->assertEquals(
|
||||||
|
ClassInfo::subclassesFor('ClassInfoTest_BaseClass'),
|
||||||
|
array(
|
||||||
|
0 => 'ClassInfoTest_BaseClass',
|
||||||
|
'ClassInfoTest_ChildClass' => 'ClassInfoTest_ChildClass',
|
||||||
|
'ClassInfoTest_GrandChildClass' => 'ClassInfoTest_GrandChildClass'
|
||||||
|
),
|
||||||
|
'ClassInfo::subclassesFor() returns only direct subclasses and doesnt include base class'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassInfoTest_BaseClass {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassInfoTest_ChildClass extends ClassInfoTest_BaseClass {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassInfoTest_GrandChildClass extends ClassInfoTest_ChildClass {
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
@ -7,6 +7,21 @@
|
|||||||
*/
|
*/
|
||||||
class HTTPTest extends SapphireTest {
|
class HTTPTest extends SapphireTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests {@link HTTP::getLinksIn()}
|
||||||
|
*/
|
||||||
|
public function testGetLinksIn() {
|
||||||
|
$content = '
|
||||||
|
<h2>My page</h2>
|
||||||
|
<p>A boy went <a href="home/">home</a> to see his <span><a href="mother/">mother</a></span>.</p>
|
||||||
|
';
|
||||||
|
|
||||||
|
$links = HTTP::getLinksIn($content);
|
||||||
|
|
||||||
|
$this->assertTrue(is_array($links));
|
||||||
|
$this->assertTrue(count($links) == 2);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link HTTP::setGetVar()}
|
* Tests {@link HTTP::setGetVar()}
|
||||||
*/
|
*/
|
||||||
|
@ -57,6 +57,7 @@ class RestfulServiceTest extends SapphireTest {
|
|||||||
class RestfulServiceTest_Controller extends Controller {
|
class RestfulServiceTest_Controller extends Controller {
|
||||||
public function index() {
|
public function index() {
|
||||||
ContentNegotiator::disable();
|
ContentNegotiator::disable();
|
||||||
|
BasicAuth::disable();
|
||||||
$request_count = count($_REQUEST);
|
$request_count = count($_REQUEST);
|
||||||
$get_count = count($_GET);
|
$get_count = count($_GET);
|
||||||
$post_count = count($_POST);
|
$post_count = count($_POST);
|
||||||
|
@ -23,10 +23,11 @@ class CsvBulkLoaderTest extends SapphireTest {
|
|||||||
$this->assertEquals(4, $results->Count(), 'Test correct count of imported data');
|
$this->assertEquals(4, $results->Count(), 'Test correct count of imported data');
|
||||||
|
|
||||||
// Test that columns were correctly imported
|
// Test that columns were correctly imported
|
||||||
$obj = Dataobject::get_one("CsvBulkLoaderTest_Player", "\"FirstName\" = 'John'");
|
$obj = DataObject::get_one("CsvBulkLoaderTest_Player", "\"FirstName\" = 'John'");
|
||||||
$this->assertNotNull($obj);
|
$this->assertNotNull($obj);
|
||||||
$this->assertEquals("He's a good guy", $obj->Biography);
|
$this->assertEquals("He's a good guy", $obj->Biography);
|
||||||
$this->assertEquals("1988-01-31", $obj->Birthday);
|
$this->assertEquals("1988-01-31", $obj->Birthday);
|
||||||
|
$this->assertEquals("1", $obj->IsRegistered);
|
||||||
|
|
||||||
fclose($file);
|
fclose($file);
|
||||||
}
|
}
|
||||||
@ -44,7 +45,8 @@ class CsvBulkLoaderTest extends SapphireTest {
|
|||||||
'FirstName',
|
'FirstName',
|
||||||
'Biography',
|
'Biography',
|
||||||
null, // ignored column
|
null, // ignored column
|
||||||
'Birthday'
|
'Birthday',
|
||||||
|
'IsRegistered'
|
||||||
);
|
);
|
||||||
$loader->hasHeaderRow = false;
|
$loader->hasHeaderRow = false;
|
||||||
$results = $loader->load($filepath);
|
$results = $loader->load($filepath);
|
||||||
@ -53,10 +55,15 @@ class CsvBulkLoaderTest extends SapphireTest {
|
|||||||
$this->assertEquals(4, $results->Count(), 'Test correct count of imported data');
|
$this->assertEquals(4, $results->Count(), 'Test correct count of imported data');
|
||||||
|
|
||||||
// Test that columns were correctly imported
|
// Test that columns were correctly imported
|
||||||
$obj = Dataobject::get_one("CsvBulkLoaderTest_Player", "\"FirstName\" = 'John'");
|
$obj = DataObject::get_one("CsvBulkLoaderTest_Player", "\"FirstName\" = 'John'");
|
||||||
$this->assertNotNull($obj);
|
$this->assertNotNull($obj);
|
||||||
$this->assertEquals("He's a good guy", $obj->Biography);
|
$this->assertEquals("He's a good guy", $obj->Biography);
|
||||||
$this->assertEquals("1988-01-31", $obj->Birthday);
|
$this->assertEquals("1988-01-31", $obj->Birthday);
|
||||||
|
$this->assertEquals("1", $obj->IsRegistered);
|
||||||
|
|
||||||
|
$obj2 = DataObject::get_one('CsvBulkLoaderTest_Player', "FirstName = 'Jane'");
|
||||||
|
$this->assertNotNull($obj2);
|
||||||
|
$this->assertEquals('0', $obj2->IsRegistered);
|
||||||
|
|
||||||
fclose($file);
|
fclose($file);
|
||||||
}
|
}
|
||||||
@ -133,7 +140,6 @@ class CsvBulkLoaderTest extends SapphireTest {
|
|||||||
$player = DataObject::get_by_id('CsvBulkLoaderTest_Player', 1);
|
$player = DataObject::get_by_id('CsvBulkLoaderTest_Player', 1);
|
||||||
$this->assertEquals($player->FirstName, 'JohnUpdated', 'Test updating of existing records works');
|
$this->assertEquals($player->FirstName, 'JohnUpdated', 'Test updating of existing records works');
|
||||||
$this->assertEquals($player->Biography, 'He\'s a good guy', 'Test retaining of previous information on duplicate when overwriting with blank field');
|
$this->assertEquals($player->Biography, 'He\'s a good guy', 'Test retaining of previous information on duplicate when overwriting with blank field');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testLoadWithCustomImportMethods() {
|
function testLoadWithCustomImportMethods() {
|
||||||
@ -142,12 +148,14 @@ class CsvBulkLoaderTest extends SapphireTest {
|
|||||||
$loader->columnMap = array(
|
$loader->columnMap = array(
|
||||||
'FirstName' => '->importFirstName',
|
'FirstName' => '->importFirstName',
|
||||||
'Biography' => 'Biography',
|
'Biography' => 'Biography',
|
||||||
'Birthday' => 'Birthday'
|
'Birthday' => 'Birthday',
|
||||||
|
'IsRegistered' => 'IsRegistered'
|
||||||
);
|
);
|
||||||
$results = $loader->load($filepath);
|
$results = $loader->load($filepath);
|
||||||
$player = DataObject::get_by_id('CsvBulkLoaderTest_Player', 1);
|
$player = DataObject::get_by_id('CsvBulkLoaderTest_Player', 1);
|
||||||
$this->assertEquals($player->FirstName, 'Customized John');
|
$this->assertEquals($player->FirstName, 'Customized John');
|
||||||
$this->assertEquals($player->Biography, "He's a good guy");
|
$this->assertEquals($player->Biography, "He's a good guy");
|
||||||
|
$this->assertEquals($player->IsRegistered, "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getLineCount(&$file) {
|
protected function getLineCount(&$file) {
|
||||||
@ -185,6 +193,7 @@ class CsvBulkLoaderTest_Player extends DataObject implements TestOnly {
|
|||||||
'Biography' => 'HTMLText',
|
'Biography' => 'HTMLText',
|
||||||
'Birthday' => 'Date',
|
'Birthday' => 'Date',
|
||||||
'ExternalIdentifier' => 'Varchar(255)', // used for uniqueness checks on passed property
|
'ExternalIdentifier' => 'Varchar(255)', // used for uniqueness checks on passed property
|
||||||
|
'IsRegistered' => 'Boolean'
|
||||||
);
|
);
|
||||||
|
|
||||||
static $has_one = array(
|
static $has_one = array(
|
||||||
|
@ -1,4 +1 @@
|
|||||||
"John","He's a good guy","ignored","31/01/1988"
|
John,He's a good guy,ignored,31/01/88,1
Jane,"She is awesome.\nSo awesome that she gets multiple rows and \escaped\"" strings in her biography""",ignored,31/01/82,0
Jamie,"Pretty old\, with an escaped comma",ignored,31/01/1882,1
Järg,Unicode FTW,ignored,31/06/1982,1
|
||||||
"Jane","She is awesome.\nSo awesome that she gets multiple rows and \"escaped\" strings in her biography","ignored","31/01/1982"
|
|
||||||
"Jamie","Pretty old\, with an escaped comma","ignored","31/01/1882"
|
|
||||||
"Järg","Unicode FTW","ignored","31/06/1982"
|
|
Can't render this file because it contains an unexpected character in line 2 and column 70.
|
@ -1,6 +1,2 @@
|
|||||||
"FirstName","Biography","Birthday"
|
FirstName,Biography,Birthday,IsRegistered
John,He's a good guy,31/01/88,1
Jane,"She is awesome.
|
||||||
"John","He's a good guy","31/01/1988"
|
So awesome that she gets multiple rows and \escaped\"" strings in her biography""",31/01/82,0
Jamie,"Pretty old\, with an escaped comma",31/01/1882,1
Järg,Unicode FTW,31/06/1982,1
|
||||||
"Jane","She is awesome.
|
|
||||||
So awesome that she gets multiple rows and \"escaped\" strings in her biography","31/01/1982"
|
|
||||||
"Jamie","Pretty old\, with an escaped comma","31/01/1882"
|
|
||||||
"Järg","Unicode FTW","31/06/1982"
|
|
Can't render this file because it contains an unexpected character in line 4 and column 45.
|
44
tests/fieldtypes/DateTest.php
Normal file
44
tests/fieldtypes/DateTest.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package sapphire
|
||||||
|
* @subpackage tests
|
||||||
|
*/
|
||||||
|
class DateTest extends SapphireTest {
|
||||||
|
|
||||||
|
function testNiceDate() {
|
||||||
|
/* Test the DD/MM/YYYY formatting of Date::Nice() */
|
||||||
|
$cases = array(
|
||||||
|
'4/3/03' => '04/03/2003',
|
||||||
|
'04/03/03' => '04/03/2003',
|
||||||
|
'4/3/03' => '04/03/2003',
|
||||||
|
'4/03/03' => '04/03/2003',
|
||||||
|
'4/3/2003' => '04/03/2003',
|
||||||
|
'4-3-2003' => '04/03/2003',
|
||||||
|
'2003-03-04' => '04/03/2003',
|
||||||
|
'04/03/2003' => '04/03/2003',
|
||||||
|
'04-03-2003' => '04/03/2003'
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach($cases as $original => $expected) {
|
||||||
|
$date = new Date();
|
||||||
|
$date->setValue($original);
|
||||||
|
$this->assertEquals($expected, $date->Nice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testLongDate() {
|
||||||
|
/* "24 May 2006" style formatting of Date::Long() */
|
||||||
|
$cases = array(
|
||||||
|
'2003-4-3' => '3 April 2003',
|
||||||
|
'3/4/2003' => '3 April 2003',
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach($cases as $original => $expected) {
|
||||||
|
$date = new Date();
|
||||||
|
$date->setValue($original);
|
||||||
|
$this->assertEquals($expected, $date->Long());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
39
tests/forms/DateFieldTest.php
Normal file
39
tests/forms/DateFieldTest.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package sapphire
|
||||||
|
* @subpackage tests
|
||||||
|
*/
|
||||||
|
class DateFieldTest extends SapphireTest {
|
||||||
|
|
||||||
|
function testDMYFormat() {
|
||||||
|
/* We get YYYY-MM-DD format as the data value for DD/MM/YYYY input value */
|
||||||
|
$dateField = new DateField('Date', 'Date', '04/03/2003');
|
||||||
|
$this->assertEquals($dateField->dataValue(), '2003-03-04');
|
||||||
|
|
||||||
|
/* Even if value hasn't got leading 0's in it we still get the correct data value */
|
||||||
|
$dateField2 = new DateField('Date', 'Date', '4/3/03');
|
||||||
|
$this->assertEquals($dateField2->dataValue(), '03-3-4');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testYMDFormat() {
|
||||||
|
/* We get YYYY-MM-DD format as the data value for YYYY-MM-DD input value */
|
||||||
|
$dateField = new DateField('Date', 'Date', '2003/03/04');
|
||||||
|
$this->assertEquals($dateField->dataValue(), '2003-03-04');
|
||||||
|
|
||||||
|
/* Even if input value hasn't got leading 0's in it we still get the correct data value */
|
||||||
|
$dateField2 = new DateField('Date', 'Date', '2003/3/4');
|
||||||
|
$this->assertEquals($dateField2->dataValue(), '2003-03-04');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testMDYFormat() {
|
||||||
|
/* We get MM-DD-YYYY format as the data value for YYYY-MM-DD input value */
|
||||||
|
$dateField = new DateField('Date', 'Date', '03/04/2003');
|
||||||
|
$this->assertEquals($dateField->dataValue(), '2003-04-03');
|
||||||
|
|
||||||
|
/* Even if input value hasn't got leading 0's in it we still get the correct data value */
|
||||||
|
$dateField2 = new DateField('Date', 'Date', '3/4/03');
|
||||||
|
$this->assertEquals($dateField2->dataValue(), '03-4-3');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
@ -14,6 +14,11 @@ class Widget extends DataObject {
|
|||||||
"Parent" => "WidgetArea",
|
"Parent" => "WidgetArea",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static $has_many = array();
|
||||||
|
static $many_many = array();
|
||||||
|
static $belongs_many_many = array();
|
||||||
|
static $defaults = array();
|
||||||
|
|
||||||
static $default_sort = "Sort";
|
static $default_sort = "Sort";
|
||||||
|
|
||||||
static $title = "Widget Title";
|
static $title = "Widget Title";
|
||||||
|
@ -5,12 +5,19 @@
|
|||||||
* @subpackage widgets
|
* @subpackage widgets
|
||||||
*/
|
*/
|
||||||
class WidgetArea extends DataObject {
|
class WidgetArea extends DataObject {
|
||||||
|
|
||||||
static $db = array();
|
static $db = array();
|
||||||
|
|
||||||
|
static $has_one = array();
|
||||||
|
|
||||||
static $has_many = array(
|
static $has_many = array(
|
||||||
"Widgets" => "Widget"
|
"Widgets" => "Widget"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static $many_many = array();
|
||||||
|
|
||||||
|
static $belongs_many_many = array();
|
||||||
|
|
||||||
function forTemplate() {
|
function forTemplate() {
|
||||||
return $this->renderWith($this->class);
|
return $this->renderWith($this->class);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user