Merge remote-tracking branch 'origin/3.2' into 3

Conflicts:
	admin/css/screen.css
This commit is contained in:
Dan Hensby 2015-07-20 14:08:36 +00:00
commit 64ceba133c
57 changed files with 1728 additions and 968 deletions

View File

@ -1,5 +1,16 @@
language: php
sudo: false
addons:
apt:
packages:
- tidy
cache:
directories:
- $HOME/.composer/cache
php:
- 5.4
@ -38,9 +49,6 @@ matrix:
env: DB=MYSQL
- php: hhvm
env: DB=MYSQL
before_install:
- sudo apt-get update -qq
- sudo apt-get install -y tidy
before_script:
- composer self-update || true

View File

@ -13,3 +13,8 @@ Name: defaulti18n
i18n:
module_priority:
- other_modules
---
Name: textcollector
---
Injector:
i18nTextCollector_Writer: 'i18nTextCollector_Writer_RailsYaml'

View File

@ -1,22 +1,22 @@
<?php
/**
* The object manages the main CMS menu. See {@link LeftAndMain::init()} for
* The object manages the main CMS menu. See {@link LeftAndMain::init()} for
* example usage.
*
* The menu will be automatically populated with menu items for subclasses of
* {@link LeftAndMain}. That is, for each class in the CMS that creates an
* administration panel, a CMS menu item will be created. The default
* configuration will also include a 'help' link to the SilverStripe user
*
* The menu will be automatically populated with menu items for subclasses of
* {@link LeftAndMain}. That is, for each class in the CMS that creates an
* administration panel, a CMS menu item will be created. The default
* configuration will also include a 'help' link to the SilverStripe user
* documentation.
*
* Additional CMSMenu items can be added through {@link LeftAndMainExtension::init()}
* extensions added to {@link LeftAndMain}.
*
*
* @package framework
* @subpackage admin
*/
class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
/**
* An array of changes to be made to the menu items, in the order that the changes should be
* applied. Each item is a map in one of the two forms:
@ -24,7 +24,7 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
* - array('type' => 'remove', 'code' => 'codename' )
*/
protected static $menu_item_changes = array();
/**
* Set to true if clear_menu() is called, to indicate that the default menu shouldn't be
* included
@ -32,7 +32,7 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
protected static $menu_is_cleared = false;
/**
* Generate CMS main menu items by collecting valid
* Generate CMS main menu items by collecting valid
* subclasses of {@link LeftAndMain}
*/
public static function populate_menu() {
@ -46,13 +46,13 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
* @return The result of the operation
* @todo A director rule is added when a controller link is added, but it won't be removed
* when the item is removed. Functionality needed in {@link Director}.
*/
*/
public static function add_controller($controllerClass) {
if($menuItem = self::menuitem_for_controller($controllerClass)) {
self::add_menu_item_obj($controllerClass, $menuItem);
}
}
/**
* Return a CMSMenuItem to add the given controller to the CMSMenu
*/
@ -60,7 +60,7 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
$urlBase = Config::inst()->get($controllerClass, 'url_base', Config::FIRST_SET);
$urlSegment = Config::inst()->get($controllerClass, 'url_segment', Config::FIRST_SET);
$menuPriority = Config::inst()->get($controllerClass, 'menu_priority', Config::FIRST_SET);
// Don't add menu items defined the old way
if($urlSegment === null && $controllerClass != "CMSMain") return;
@ -75,7 +75,7 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
return new CMSMenuItem($menuTitle, $link, $controllerClass, $menuPriority);
}
/**
* Add an arbitrary URL to the CMS menu.
*
@ -91,7 +91,7 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
public static function add_link($code, $menuTitle, $url, $priority = -1, $attributes = null) {
return self::add_menu_item($code, $menuTitle, $url, null, $priority, $attributes);
}
/**
* Add a navigation item to the main administration menu showing in the top bar.
*
@ -99,10 +99,10 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
*
* @param string $code Unique identifier for this menu item (e.g. used by {@link replace_menu_item()} and
* {@link remove_menu_item}. Also used as a CSS-class for icon customization.
* @param string $menuTitle Localized title showing in the menu bar
* @param string $menuTitle Localized title showing in the menu bar
* @param string $url A relative URL that will be linked in the menu bar.
* @param string $controllerClass The controller class for this menu, used to check permisssions.
* If blank, it's assumed that this is public, and always shown to users who
* @param string $controllerClass The controller class for this menu, used to check permisssions.
* If blank, it's assumed that this is public, and always shown to users who
* have the rights to access some other part of the admin area.
* @param array $attributes an array of attributes to include on the link.
*
@ -114,10 +114,10 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
if($controllerClass) {
$code = $controllerClass;
}
return self::replace_menu_item($code, $menuTitle, $url, $controllerClass, $priority, $attributes);
}
/**
* Get a single menu item by its code value.
*
@ -126,9 +126,9 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
*/
public static function get_menu_item($code) {
$menuItems = self::get_menu_items();
return (isset($menuItems[$code])) ? $menuItems[$code] : false;
return (isset($menuItems[$code])) ? $menuItems[$code] : false;
}
/**
* Get all menu entries.
*
@ -142,26 +142,26 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
$cmsClasses = self::get_cms_classes();
foreach($cmsClasses as $cmsClass) {
$menuItem = self::menuitem_for_controller($cmsClass);
if($menuItem) $menuItems[$cmsClass] = $menuItem;
if($menuItem) $menuItems[Convert::raw2htmlname(str_replace('\\', '-', $cmsClass))] = $menuItem;
}
}
// Apply changes
foreach(self::$menu_item_changes as $change) {
switch($change['type']) {
case 'add':
$menuItems[$change['code']] = $change['item'];
break;
case 'remove':
unset($menuItems[$change['code']]);
break;
default:
user_error("Bad menu item change type {$change[type]}", E_USER_WARNING);
}
}
// Sort menu items according to priority, then title asc
$menuPriority = array();
$menuTitle = array();
@ -170,14 +170,14 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
$menuTitle[$key] = $menuItem->title;
}
array_multisort($menuPriority, SORT_DESC, $menuTitle, SORT_ASC, $menuItems);
return $menuItems;
}
/**
* Get all menu items that the passed member can view.
* Defaults to {@link Member::currentUser()}.
*
*
* @param Member $member
* @return array
*/
@ -185,7 +185,7 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
if(!$member && $member !== FALSE) {
$member = Member::currentUser();
}
$viewableMenuItems = array();
$allMenuItems = self::get_menu_items();
if($allMenuItems) foreach($allMenuItems as $code => $menuItem) {
@ -200,13 +200,13 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
if(!$controllerObj->canView($member)) continue;
}
}
$viewableMenuItems[$code] = $menuItem;
}
return $viewableMenuItems;
}
/**
* Removes an existing item from the menu.
*
@ -215,7 +215,7 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
public static function remove_menu_item($code) {
self::$menu_item_changes[] = array('type' => 'remove', 'code' => $code);
}
/**
* Clears the entire menu
*/
@ -229,11 +229,11 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
*
* @param string $code Unique identifier for this menu item (e.g. used by {@link replace_menu_item()} and
* {@link remove_menu_item}. Also used as a CSS-class for icon customization.
* @param string $menuTitle Localized title showing in the menu bar
* @param string $menuTitle Localized title showing in the menu bar
* @param string $url A relative URL that will be linked in the menu bar.
* Make sure to add a matching route via {@link Director::$rules} to this url.
* @param string $controllerClass The controller class for this menu, used to check permisssions.
* If blank, it's assumed that this is public, and always shown to users who
* @param string $controllerClass The controller class for this menu, used to check permisssions.
* If blank, it's assumed that this is public, and always shown to users who
* have the rights to access some other part of the admin area.
* @param array $attributes an array of attributes to include on the link.
*
@ -253,7 +253,7 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
'item' => $item,
);
}
/**
* Add a previously built menu item object to the menu
*/
@ -292,10 +292,10 @@ class CMSMenu extends Object implements IteratorAggregate, i18nEntityProvider {
if(!$classReflection->isInstantiable()) unset($subClasses[$key]);
}
}
return $subClasses;
}
/**
* IteratorAggregate Interface Method. Iterates over the menu items.
*/

View File

@ -555,7 +555,7 @@ class LeftAndMain extends Controller implements PermissionProvider {
public static function menu_icon_for_class($class) {
$icon = Config::inst()->get($class, 'menu_icon', Config::FIRST_SET);
if (!empty($icon)) {
$class = strtolower($class);
$class = strtolower(Convert::raw2htmlname(str_replace('\\', '-', $class)));
return ".icon.icon-16.icon-{$class} { background: url('{$icon}'); } ";
}
return '';
@ -1962,8 +1962,9 @@ class LeftAndMain_TreeNode extends ViewableData {
$obj = $this->obj;
return "<li id=\"record-$obj->ID\" data-id=\"$obj->ID\" data-pagetype=\"$obj->ClassName\" class=\""
. $this->getClasses() . "\">" . "<ins class=\"jstree-icon\">&nbsp;</ins>"
. "<a href=\"" . $this->getLink() . "\" title=\"" . _t('LeftAndMain.PAGETYPE','Page type: ')
. "$obj->class\" ><ins class=\"jstree-icon\">&nbsp;</ins><span class=\"text\">" . ($obj->TreeTitle)
. "<a href=\"" . $this->getLink() . "\" title=\"("
. trim(_t('LeftAndMain.PAGETYPE','Page type'), " :") // account for inconsistencies in translations
. ": " . $obj->i18n_singular_name() . ") $obj->Title\" ><ins class=\"jstree-icon\">&nbsp;</ins><span class=\"text\">" . ($obj->TreeTitle)
. "</span></a>";
}

View File

@ -256,7 +256,7 @@ form.small .field input.text, form.small .field textarea, form.small .field sele
.cms .ss-ui-button.ui-state-hover, .cms .ss-ui-button:hover { text-decoration: none; background-color: white; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2U2ZTZlNiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #e6e6e6)); background: -moz-linear-gradient(#ffffff, #e6e6e6); background: -webkit-linear-gradient(#ffffff, #e6e6e6); background: linear-gradient(#ffffff, #e6e6e6); -moz-box-shadow: 0 0 5px #b3b3b3; -webkit-box-shadow: 0 0 5px #b3b3b3; box-shadow: 0 0 5px #b3b3b3; }
.cms .ss-ui-button:active, .cms .ss-ui-button:focus, .cms .ss-ui-button.ui-state-active, .cms .ss-ui-button.ui-state-focus { border: 1px solid #b3b3b3; background-color: white; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2U2ZTZlNiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #e6e6e6)); background: -moz-linear-gradient(#ffffff, #e6e6e6); background: -webkit-linear-gradient(#ffffff, #e6e6e6); background: linear-gradient(#ffffff, #e6e6e6); -moz-box-shadow: 0 0 5px #b3b3b3 inset; -webkit-box-shadow: 0 0 5px #b3b3b3 inset; box-shadow: 0 0 5px #b3b3b3 inset; }
.cms .ss-ui-button.ss-ui-action-minor span { padding-left: 0; padding-right: 0; }
.cms .ss-ui-button.ss-ui-action-constructive { text-shadow: none; font-weight: bold; color: white; border-color: #1F9433; border-bottom-color: #166a24; background-color: #1F9433; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzk0YmU0MiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzFmOTQzMyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #94be42), color-stop(100%, #1f9433)); background: -moz-linear-gradient(#94be42, #1f9433); background: -webkit-linear-gradient(#94be42, #1f9433); background: linear-gradient(#94be42, #1f9433); text-shadow: #1c872f 0 -1px -1px; }
.cms .ss-ui-button.ss-ui-action-constructive { text-shadow: none; font-weight: bold; color: white; border-color: #1F9433; border-bottom-color: #166a24; background-color: #1F9433; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzkzYmU0MiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzFmOTQzMyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #93be42), color-stop(100%, #1f9433)); background: -moz-linear-gradient(#93be42, #1f9433); background: -webkit-linear-gradient(#93be42, #1f9433); background: linear-gradient(#93be42, #1f9433); text-shadow: #1c872f 0 -1px -1px; }
.cms .ss-ui-button.ss-ui-action-constructive.ui-state-hover, .cms .ss-ui-button.ss-ui-action-constructive:hover { border-color: #166a24; background-color: #1F9433; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2E0Y2EzYSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzIzYTkzYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #a4ca3a), color-stop(100%, #23a93a)); background: -moz-linear-gradient(#a4ca3a, #23a93a); background: -webkit-linear-gradient(#a4ca3a, #23a93a); background: linear-gradient(#a4ca3a, #23a93a); }
.cms .ss-ui-button.ss-ui-action-constructive:active, .cms .ss-ui-button.ss-ui-action-constructive:focus, .cms .ss-ui-button.ss-ui-action-constructive.ui-state-active, .cms .ss-ui-button.ss-ui-action-constructive.ui-state-focus { background-color: #1d8c30; -moz-box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); -webkit-box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); box-shadow: inset 0 1px 3px #17181a, 0 1px 0 rgba(255, 255, 255, 0.6); }
.cms .ss-ui-button.ss-ui-action-destructive { color: #f00; background-color: #e6e6e6; }
@ -882,7 +882,8 @@ form.import-form label.left { width: 250px; }
.cms .jstree a, .TreeDropdownField .treedropdownfield-panel .jstree a { display: inline-block; line-height: 16px; height: 16px; color: black; white-space: nowrap; text-decoration: none; padding: 1px 2px; margin: 0; border: 1px solid #fff; }
.cms .jstree a:focus, .cms .jstree a:active, .cms .jstree a:hover, .TreeDropdownField .treedropdownfield-panel .jstree a:focus, .TreeDropdownField .treedropdownfield-panel .jstree a:active, .TreeDropdownField .treedropdownfield-panel .jstree a:hover { text-decoration: none; cursor: pointer; text-shadow: 1px 1px 1px white; }
.cms .jstree a ins, .TreeDropdownField .treedropdownfield-panel .jstree a ins { height: 16px; width: 12px; }
.cms .jstree a ins.jstree-checkbox, .TreeDropdownField .treedropdownfield-panel .jstree a ins.jstree-checkbox { height: 19px; width: 16px; }
.cms .jstree a ins.jstree-checkbox, .TreeDropdownField .treedropdownfield-panel .jstree a ins.jstree-checkbox { width: 16px; position: relative; }
.cms .jstree a ins.jstree-checkbox:before, .TreeDropdownField .treedropdownfield-panel .jstree a ins.jstree-checkbox:before { content: ''; display: block; position: absolute; z-index: 1; left: -3px; top: -3px; height: 22px; width: 25px; }
.cms .jstree .jstree-real-checkbox, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-real-checkbox { display: none; }
.cms .jstree .jstree-wholerow-real, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow-real { position: relative; z-index: 1; }
.cms .jstree .jstree-wholerow-real li, .TreeDropdownField .treedropdownfield-panel .jstree .jstree-wholerow-real li { cursor: pointer; }
@ -943,7 +944,7 @@ form.import-form label.left { width: 250px; }
.tree-holder.jstree li.Root strong, .cms-tree.jstree li.Root strong { font-weight: bold; padding-left: 1px; }
.tree-holder.jstree li.Root > a .jstree-icon, .cms-tree.jstree li.Root > a .jstree-icon { background-position: -56px -36px; }
.tree-holder.jstree li.status-deletedonlive > a .text, .tree-holder.jstree li.status-deletedonlive > a:link .text, .tree-holder.jstree li.status-archived > a .text, .tree-holder.jstree li.status-archived > a:link .text, .cms-tree.jstree li.status-deletedonlive > a .text, .cms-tree.jstree li.status-deletedonlive > a:link .text, .cms-tree.jstree li.status-archived > a .text, .cms-tree.jstree li.status-archived > a:link .text { text-decoration: line-through; }
.tree-holder.jstree li.jstree-checked > a, .tree-holder.jstree li.jstree-checked > a:link, .cms-tree.jstree li.jstree-checked > a, .cms-tree.jstree li.jstree-checked > a:link { background-color: #efe999; }
.tree-holder.jstree li.jstree-checked > a, .tree-holder.jstree li.jstree-checked > a:link, .cms-tree.jstree li.jstree-checked > a, .cms-tree.jstree li.jstree-checked > a:link { background-color: #fffcdc; }
.tree-holder.jstree li.disabled > a, .tree-holder.jstree li.disabled > a:link, .tree-holder.jstree li.edit-disabled > a, .tree-holder.jstree li.edit-disabled > a:link, .cms-tree.jstree li.disabled > a, .cms-tree.jstree li.disabled > a:link, .cms-tree.jstree li.edit-disabled > a, .cms-tree.jstree li.edit-disabled > a:link { color: #aaa; background-color: transparent; cursor: default; }
.tree-holder.jstree li.disabled > a > .jstree-checkbox, .tree-holder.jstree li.disabled > a:link > .jstree-checkbox, .tree-holder.jstree li.edit-disabled > a > .jstree-checkbox, .tree-holder.jstree li.edit-disabled > a:link > .jstree-checkbox, .cms-tree.jstree li.disabled > a > .jstree-checkbox, .cms-tree.jstree li.disabled > a:link > .jstree-checkbox, .cms-tree.jstree li.edit-disabled > a > .jstree-checkbox, .cms-tree.jstree li.edit-disabled > a:link > .jstree-checkbox { background-position: -57px -54px; }
.tree-holder.jstree li.readonly, .cms-tree.jstree li.readonly { color: #aaa; padding-left: 18px; }
@ -966,9 +967,17 @@ form.import-form label.left { width: 250px; }
.jstree-default a .jstree-icon, .jstree-default-rtl a .jstree-icon, .jstree-classic a .jstree-icon, .jstree-apple a .jstree-icon { background-position: -60px -19px; }
<<<<<<< HEAD
/** DEPRECATED: .cms-content-tools will be removed in 4.0 Use .cms-content-filters instead. Ensure status is visible in sidebar */
.cms-content-tools .cms-tree.jstree li { min-width: 159px; }
.cms-content-tools .cms-tree.jstree a { overflow: hidden; display: block; position: relative; }
=======
.jstree-apple a { border-radius: 3px; }
/* ensure status is visible in sidebar */
.cms-content-tools .cms-tree.jstree li { min-width: 187px; }
.cms-content-tools .cms-tree.jstree a { overflow: hidden; text-overflow: ellipsis; display: block; position: relative; }
>>>>>>> origin/3.2
.cms-content-tools .cms-tree.jstree span.badge { position: absolute; top: 0; right: 0; padding: 7px 9px 6px 5px; margin: 0; max-width: 40%; -moz-transition: max-width 0.75s linear; -o-transition: max-width 0.75s linear; -webkit-transition: max-width 0.75s linear; transition: max-width 0.75s linear; }
.cms-content-tools .cms-tree.jstree span.badge:hover { max-width: 150px; }
@ -978,45 +987,59 @@ li.class-RedirectorPage > a .jstree-pageicon { background-position: 0 -16px; }
li.class-VirtualPage > a .jstree-pageicon { background-position: 0 -32px; }
li.class-ErrorPage > a .jstree-pageicon { background-position: 0 -112px; }
/* tree status icons and labels */
.cms-tree.jstree .status-modified > a .jstree-pageicon:before, .cms-tree.jstree .status-addedtodraft > a .jstree-pageicon:before, .cms-tree.jstree .status-deletedonlive > a .jstree-pageicon:before, .cms-tree.jstree .status-archived > a .jstree-pageicon:before, .cms-tree.jstree .status-removedfromdraft > a .jstree-pageicon:before, .cms-tree.jstree .status-workflow-approval > a .jstree-pageicon:before { content: ""; display: block; width: 5px; height: 5px; position: absolute; bottom: 0; right: 0; background: #fce2d0; border: 1px solid #ff9344; border-radius: 100px; box-shadow: 0px 0px 0px 1px #fff; }
/* Tree status labels and dots */
.jstree-apple .jstree-clicked, .jstree-apple .jstree-hovered { background: #ebfbff; }
.jstree .status-modified > .jstree-hovered, .jstree .status-modified > .jstree-clicked, .cms-tree.jstree span.badge.status-modified, .cms-tree.jstree .status-modified > a .jstree-pageicon:before { background-color: #FFF4ED; border-color: #EE6214; }
.cms-tree.jstree .status-addedtodraft > a .jstree-pageicon:before, .cms-tree.jstree .status-modified > a .jstree-pageicon:before, .cms-tree.jstree .status-archived > a .jstree-pageicon:before, .cms-tree.jstree .status-deletedonlive > a .jstree-pageicon:before, .cms-tree.jstree .status-removedfromdraft > a .jstree-pageicon:before, .cms-tree.jstree .status-workflow-approval > a .jstree-pageicon:before { content: ""; display: block; width: 6px; height: 6px; position: absolute; bottom: 0; right: 0; background: #fce2d0; border: 1px solid #fff; border-radius: 100px; }
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-modified { box-shadow: 0px 0px 6px 2px #FFF4ED; }
.jstree .status-addedtodraft > .jstree-hovered, .jstree .status-addedtodraft > .jstree-clicked, .cms-tree.jstree span.badge.status-addedtodraft { background-color: #fff7f2; border-color: #F46B00; }
.cms-tree.jstree span.badge.status-modified { color: #EE6214; }
.cms-tree.jstree span.badge.status-addedtodraft { color: #F46B00; }
.jstree .status-addedtodraft > .jstree-hovered, .jstree .status-addedtodraft > .jstree-clicked, .cms-tree.jstree span.badge.status-addedtodraft, .cms-tree.jstree .status-addedtodraft > a .jstree-pageicon:before { background-color: #FFF4ED; border-color: #EE6214; }
.cms-tree.jstree .status-addedtodraft > a .jstree-pageicon:before { background-color: #ff7f22; -moz-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #F46B00; -webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #F46B00; box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #F46B00; }
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-addedtodraft { box-shadow: 0px 0px 6px 2px #FFF4ED; }
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-addedtodraft { -moz-box-shadow: 0px 0px 6px 2px #fff7f2; -webkit-box-shadow: 0px 0px 6px 2px #fff7f2; box-shadow: 0px 0px 6px 2px #fff7f2; }
.cms-tree.jstree span.badge.status-addedtodraft { color: #EE6214; }
.jstree .status-modified > .jstree-hovered, .jstree .status-modified > .jstree-clicked, .cms-tree.jstree span.badge.status-modified { background-color: #fff7f2; border-color: #F46B00; }
.jstree .status-deletedonlive > .jstree-hovered, .jstree .status-deletedonlive > .jstree-clicked, .cms-tree.jstree span.badge.status-deletedonlive, .cms-tree.jstree .status-deletedonlive > a .jstree-pageicon:before { background-color: #F5F5F5; border-color: #5F7688; }
.cms-tree.jstree span.badge.status-modified { color: #F46B00; }
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-deletedonlive { box-shadow: 0px 0px 6px 2px #F5F5F5; }
.cms-tree.jstree .status-modified > a .jstree-pageicon:before { background-color: #fff2e8; -moz-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #F46B00; -webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #F46B00; box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #F46B00; }
.cms-tree.jstree span.badge.status-deletedonlive { color: #5F7688; }
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-modified { -moz-box-shadow: 0px 0px 6px 2px #fff7f2; -webkit-box-shadow: 0px 0px 6px 2px #fff7f2; box-shadow: 0px 0px 6px 2px #fff7f2; }
.jstree .status-archived > .jstree-hovered, .jstree .status-archived > .jstree-clicked, .cms-tree.jstree span.badge.status-archived, .cms-tree.jstree .status-archived > a .jstree-pageicon:before { background-color: #F5F5F5; border-color: #5F7688; }
.jstree .status-archived > .jstree-hovered, .jstree .status-archived > .jstree-clicked, .cms-tree.jstree span.badge.status-archived { background-color: #f7f7f7; border-color: #455b6c; }
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-archived { box-shadow: 0px 0px 6px 2px #F5F5F5; }
.cms-tree.jstree span.badge.status-archived { color: #455b6c; }
.cms-tree.jstree span.badge.status-archived { color: #5F7688; }
.cms-tree.jstree .status-archived > a .jstree-pageicon:before { background-color: #5F7688; -moz-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #455b6c; -webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #455b6c; box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #455b6c; }
.jstree .status-removedfromdraft > .jstree-hovered, .jstree .status-removedfromdraft > .jstree-clicked, .cms-tree.jstree span.badge.status-removedfromdraft, .cms-tree.jstree .status-removedfromdraft > a .jstree-pageicon:before { background-color: #F5F5F5; border-color: #5F7688; }
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-archived { -moz-box-shadow: 0px 0px 6px 2px #f7f7f7; -webkit-box-shadow: 0px 0px 6px 2px #f7f7f7; box-shadow: 0px 0px 6px 2px #f7f7f7; }
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-removedfromdraft { box-shadow: 0px 0px 6px 2px #F5F5F5; }
.jstree .status-deletedonlive > .jstree-hovered, .jstree .status-deletedonlive > .jstree-clicked, .cms-tree.jstree span.badge.status-deletedonlive { background-color: #f7f7f7; border-color: #455b6c; }
.cms-tree.jstree span.badge.status-removedfromdraft { color: #5F7688; }
.cms-tree.jstree span.badge.status-deletedonlive { color: #455b6c; }
.jstree .status-workflow-approval > .jstree-hovered, .jstree .status-workflow-approval > .jstree-clicked, .cms-tree.jstree span.badge.status-workflow-approval, .cms-tree.jstree .status-workflow-approval > a .jstree-pageicon:before { background-color: #E8FAFF; border-color: #0070B4; }
.cms-tree.jstree .status-deletedonlive > a .jstree-pageicon:before { background-color: #f7f7f7; -moz-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #455b6c; -webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #455b6c; box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #455b6c; }
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-workflow-approval { box-shadow: 0px 0px 6px 2px #E8FAFF; }
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-deletedonlive { -moz-box-shadow: 0px 0px 6px 2px #f7f7f7; -webkit-box-shadow: 0px 0px 6px 2px #f7f7f7; box-shadow: 0px 0px 6px 2px #f7f7f7; }
.jstree .status-removedfromdraft > .jstree-hovered, .jstree .status-removedfromdraft > .jstree-clicked, .cms-tree.jstree span.badge.status-removedfromdraft { background-color: #f7f7f7; border-color: #455b6c; }
.cms-tree.jstree span.badge.status-removedfromdraft { color: #455b6c; }
.cms-tree.jstree .status-removedfromdraft > a .jstree-pageicon:before { background-color: #f7f7f7; -moz-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #455b6c; -webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #455b6c; box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #455b6c; }
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-removedfromdraft { -moz-box-shadow: 0px 0px 6px 2px #f7f7f7; -webkit-box-shadow: 0px 0px 6px 2px #f7f7f7; box-shadow: 0px 0px 6px 2px #f7f7f7; }
.jstree .status-workflow-approval > .jstree-hovered, .jstree .status-workflow-approval > .jstree-clicked, .cms-tree.jstree span.badge.status-workflow-approval { background-color: #E8FAFF; border-color: #0070B4; }
.cms-tree.jstree span.badge.status-workflow-approval { color: #0070B4; }
.cms-tree.jstree .status-workflow-approval > a .jstree-pageicon:before { background-color: #0070B4; -moz-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #0070B4; -webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #0070B4; box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px #0070B4; }
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-workflow-approval { -moz-box-shadow: 0px 0px 6px 2px #E8FAFF; -webkit-box-shadow: 0px 0px 6px 2px #E8FAFF; box-shadow: 0px 0px 6px 2px #E8FAFF; }
.cms-tree { visibility: hidden; }
.cms-tree.multiple li > a > .jstree-icon { display: none; }
.cms-tree.multiple li > a > .jstree-icon.jstree-checkbox { display: inline-block; }
@ -1335,7 +1358,7 @@ green tick icon as a background this is created using compass generated classes
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2 / 1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { /* Loading spinner */
.cms-content-loading-spinner { background-image: url(../images/spinner@2x.gif); background-size: 43px 43px; }
.ui-dialog .ui-dialog-content.loading { background-image: url(../images/spinner@2x.gif); background-size: 43px 43px; }
.ui-dialog.loading { background-image: url(../images/spinner@2x.gif); background-size: 43px 22px; }
.ui-dialog.loading { background-image: url(../images/spinner@2x.gif); background-size: 43px 43px; }
/* Default CMS logo */
.cms-logo a { background-image: url("../images/logo_small@2x.png"); background-size: 22px 22px; }
/* Logout button */

View File

@ -176,7 +176,7 @@
updateMenuFromResponse: function(xhr) {
var controller = xhr.getResponseHeader('X-Controller');
if(controller) {
var item = this.find('li#Menu-' + controller);
var item = this.find('li#Menu-' + controller.replace(/\\/g, '-').replace(/[^a-zA-Z0-9\-_:.]+/, ''));
if(!item.hasClass('current')) item.select();
}
this.updateItems();

View File

@ -71,7 +71,7 @@
&.loading {
background-image: url(../images/spinner@2x.gif);
background-size: 43px 22px;
background-size: 43px 43px;
}
}

View File

@ -64,8 +64,19 @@
height: 16px;
width: 12px;
&.jstree-checkbox {
height: 19px; //Larger to help avoid accidental page loads when trying to click checkboxes
width: 16px;
position: relative;
//Larger to help avoid accidental page loads when trying to click checkboxes
&:before {
content: '';
display: block;
position: absolute;
z-index: 1;
left: -3px;
top: -3px;
height: 22px;
width: 25px;
}
}
}
}
@ -592,6 +603,9 @@
.jstree-apple a .jstree-icon {
background-position:-60px -19px;
}
.jstree-apple a {
border-radius: 3px;
}
/**
* DEPRECATED:
@ -602,10 +616,11 @@
*/
.cms-content-tools .cms-tree.jstree {
li {
min-width: 159px;
min-width: 187px;
}
a {
overflow: hidden;
text-overflow: ellipsis;
display: block;
position: relative;
}
@ -641,44 +656,52 @@ a .jstree-pageicon {
}
}
/* tree status icons and labels */
/* Tree status labels and dots */
.jstree-apple .jstree-clicked,
.jstree-apple .jstree-hovered {
background: #ebfbff;
}
%tree-status-icon-before {
content:"";
display: block;
width:5px;
height: 5px;
width:6px;
height: 6px;
position: absolute;
bottom: 0;
right: 0;
background: #fce2d0;
border: 1px solid #ff9344;
border: 1px solid #fff;
border-radius: 100px;
box-shadow: 0px 0px 0px 1px #fff;
}
@mixin tree-status-icon($label, $color, $bgColor) {
@mixin tree-status-icon($label, $dotColor, $textColor, $bgColor) {
.cms-tree.jstree .status-#{$label} > a .jstree-pageicon:before {
@extend %tree-status-icon-before;
}
// Labels
.jstree .status-#{$label} > .jstree-hovered,
.jstree .status-#{$label} > .jstree-clicked,
.cms-tree.jstree span.badge.status-#{$label},
.cms-tree.jstree .status-#{$label} > a .jstree-pageicon:before {
.cms-tree.jstree span.badge.status-#{$label} {
background-color:$bgColor;
border-color:$color;
}
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-#{$label} {
box-shadow: 0px 0px 6px 2px $bgColor;
border-color:$textColor;
}
.cms-tree.jstree span.badge.status-#{$label} {
color: $color;
color: $textColor;
}
// Dots
.cms-tree.jstree .status-#{$label} > a .jstree-pageicon:before {
background-color:$dotColor;
@include box-shadow(0px 1px 1px rgba(0, 0, 0, 0.3), inset 0 0 0 1px $textColor);
}
#cms-content-tools-CMSMain .cms-tree.jstree span.badge.status-#{$label} {
@include box-shadow(0px 0px 6px 2px $bgColor);
}
}
@include tree-status-icon('modified', #EE6214, #FFF4ED);
@include tree-status-icon('addedtodraft', #EE6214, #FFF4ED);
@include tree-status-icon('deletedonlive', #5F7688, #F5F5F5);
@include tree-status-icon('archived', #5F7688, #F5F5F5);
@include tree-status-icon('removedfromdraft', #5F7688, #F5F5F5);
@include tree-status-icon('workflow-approval', #0070B4, #E8FAFF);
@include tree-status-icon('addedtodraft', #ff7f22, #F46B00, #fff7f2);
@include tree-status-icon('modified', #fff2e8, #F46B00, #fff7f2);
@include tree-status-icon('archived', #5F7688, #455b6c, #f7f7f7);
@include tree-status-icon('deletedonlive', #f7f7f7, #455b6c, #f7f7f7);
@include tree-status-icon('removedfromdraft', #f7f7f7, #455b6c, #f7f7f7);
@include tree-status-icon('workflow-approval', #0070B4, #0070B4, #E8FAFF);
.cms-tree {
visibility: hidden; // enabled by JS to avoid layout glitches

View File

@ -67,7 +67,7 @@ $color-good: #72c34b !default; // green
/*$color-optional: #a1d2eb !default; */ // orange
$color-cms-batchactions-menu-background: #f5f5f5 !default;
$color-cms-batchactions-menu-selected-background: #efe999 !default;
$color-cms-batchactions-menu-selected-background: #fffcdc !default;
/** -----------------------------------------------
* Textures

View File

@ -17,10 +17,10 @@
],
"require": {
"php": ">=5.3.3",
"composer/installers": "*"
"composer/installers": "~1.0"
},
"require-dev": {
"phpunit/PHPUnit": "~3.7@stable"
"phpunit/PHPUnit": "~3.7"
},
"extra": {
"branch-alias": {
@ -29,6 +29,5 @@
},
"autoload": {
"classmap": ["tests/behat/features/bootstrap"]
},
"minimum-stability": "dev"
}
}

View File

@ -272,7 +272,16 @@ class Injector {
* @return Injector Reference to restored active Injector instance
*/
public static function unnest() {
return self::set_inst(self::$instance->nestedFrom);
if (self::inst()->nestedFrom) {
self::set_inst(self::inst()->nestedFrom);
}
else {
user_error(
"Unable to unnest root Injector, please make sure you don't have mis-matched nest/unnest",
E_USER_WARNING
);
}
return self::inst();
}
/**

View File

@ -237,7 +237,16 @@ class Config {
* @return Config Reference to new active Config instance
*/
public static function unnest() {
return self::set_instance(self::$instance->nestedFrom);
if (self::inst()->nestedFrom) {
self::set_instance(self::inst()->nestedFrom);
}
else {
user_error(
"Unable to unnest root Config, please make sure you don't have mis-matched nest/unnest",
E_USER_WARNING
);
}
return self::inst();
}
/**

View File

@ -185,9 +185,10 @@ if(!isset($_SERVER['HTTP_HOST'])) {
}
}
if (defined('SS_ALLOWED_HOSTS')) {
// Filter by configured allowed hosts
if (defined('SS_ALLOWED_HOSTS') && php_sapi_name() !== "cli") {
$all_allowed_hosts = explode(',', SS_ALLOWED_HOSTS);
if (!in_array($_SERVER['HTTP_HOST'], $all_allowed_hosts)) {
if (!isset($_SERVER['HTTP_HOST']) || !in_array($_SERVER['HTTP_HOST'], $all_allowed_hosts)) {
header('HTTP/1.1 400 Invalid Host', true, 400);
die();
}

View File

@ -16,7 +16,7 @@ Used in side panels and action tabs
.backlink { padding-left: 12px; }
body.cms.ss-uploadfield-edit-iframe, .composite.ss-assetuploadfield .details fieldset { overflow: auto; background: #E2E2E2; }
body.cms.ss-uploadfield-edit-iframe span.readonly, .composite.ss-assetuploadfield .details fieldset span.readonly { font-style: italic; color: #777777; text-shadow: 0px 1px 0px #fff; }
body.cms.ss-uploadfield-edit-iframe span.readonly, .composite.ss-assetuploadfield .details fieldset span.readonly { font-style: italic; color: #9ba5ae; text-shadow: 0px 1px 0px #fff; }
body.cms.ss-uploadfield-edit-iframe .fieldholder-small label, .composite.ss-assetuploadfield .details fieldset .fieldholder-small label { margin-left: 0; }
.composite.ss-assetuploadfield .details fieldset { padding: 16px; }
@ -30,7 +30,7 @@ body.cms.ss-uploadfield-edit-iframe .fieldholder-small label, .composite.ss-asse
.ss-assetuploadfield .fileOverview .uploadStatus .state { float: left; font-size: 16px; font-weight: bold; line-height: 1.1em; }
.ss-assetuploadfield .fileOverview .uploadStatus .details { opacity: 0.9; float: right; }
.ss-assetuploadfield .ss-uploadfield-item-actions.edit-all { clear: both; position: relative; z-index: 9; }
.ss-assetuploadfield .ss-uploadfield-item-actions.edit-all .ss-uploadfield-item-edit-all { z-index: 8; position: absolute; top: -33px; padding: 0; background: none; border: 0; right: 0; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; color: #444; }
.ss-assetuploadfield .ss-uploadfield-item-actions.edit-all .ss-uploadfield-item-edit-all { z-index: 8; position: absolute; top: -33px; padding: 0; background: none; border: 0; right: 0; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; color: #66727d; }
.ss-assetuploadfield .ss-uploadfield-item-actions.edit-all .ss-uploadfield-item-edit-all:hover { color: #1e7cba; }
.ss-assetuploadfield .ss-uploadfield-files { margin: 0; padding: 0; clear: both; }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item { border: 1px solid #b3b3b3; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; -moz-background-clip: padding; -o-background-clip: padding-box; -webkit-background-clip: padding; background-clip: padding-box; margin: 0 0 5px; padding: 0; overflow: hidden; position: relative; }
@ -41,8 +41,8 @@ body.cms.ss-uploadfield-edit-iframe .fieldholder-small label, .composite.ss-asse
.ss-assetuploadfield .ss-uploadfield-files .ui-state-error .ss-uploadfield-item-info { background-color: #c11f1d; padding-right: 130px; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2MxMWYxZCIvPjxzdG9wIG9mZnNldD0iNCUiIHN0b3AtY29sb3I9IiNiZjFkMWIiLz48c3RvcCBvZmZzZXQ9IjglIiBzdG9wLWNvbG9yPSIjYjcxYjFjIi8+PHN0b3Agb2Zmc2V0PSIxNSUiIHN0b3AtY29sb3I9IiNiNjFlMWQiLz48c3RvcCBvZmZzZXQ9IjI3JSIgc3RvcC1jb2xvcj0iI2IxMWQxZCIvPjxzdG9wIG9mZnNldD0iMzElIiBzdG9wLWNvbG9yPSIjYWIxZDFjIi8+PHN0b3Agb2Zmc2V0PSI0MiUiIHN0b3AtY29sb3I9IiNhNTFiMWIiLz48c3RvcCBvZmZzZXQ9IjQ2JSIgc3RvcC1jb2xvcj0iIzlmMWIxOSIvPjxzdG9wIG9mZnNldD0iNTAlIiBzdG9wLWNvbG9yPSIjOWYxYjE5Ii8+PHN0b3Agb2Zmc2V0PSI1NCUiIHN0b3AtY29sb3I9IiM5OTFjMWEiLz48c3RvcCBvZmZzZXQ9IjU4JSIgc3RvcC1jb2xvcj0iIzk3MWExOCIvPjxzdG9wIG9mZnNldD0iNjIlIiBzdG9wLWNvbG9yPSIjOTExYjFiIi8+PHN0b3Agb2Zmc2V0PSI2NSUiIHN0b3AtY29sb3I9IiM5MTFiMWIiLz48c3RvcCBvZmZzZXQ9Ijg4JSIgc3RvcC1jb2xvcj0iIzdlMTgxNiIvPjxzdG9wIG9mZnNldD0iOTIlIiBzdG9wLWNvbG9yPSIjNzcxOTE5Ii8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjNzMxODE3Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g'); background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #c11f1d), color-stop(4%, #bf1d1b), color-stop(8%, #b71b1c), color-stop(15%, #b61e1d), color-stop(27%, #b11d1d), color-stop(31%, #ab1d1c), color-stop(42%, #a51b1b), color-stop(46%, #9f1b19), color-stop(50%, #9f1b19), color-stop(54%, #991c1a), color-stop(58%, #971a18), color-stop(62%, #911b1b), color-stop(65%, #911b1b), color-stop(88%, #7e1816), color-stop(92%, #771919), color-stop(100%, #731817)); background-image: -moz-linear-gradient(top, #c11f1d 0%, #bf1d1b 4%, #b71b1c 8%, #b61e1d 15%, #b11d1d 27%, #ab1d1c 31%, #a51b1b 42%, #9f1b19 46%, #9f1b19 50%, #991c1a 54%, #971a18 58%, #911b1b 62%, #911b1b 65%, #7e1816 88%, #771919 92%, #731817 100%); background-image: -webkit-linear-gradient(top, #c11f1d 0%, #bf1d1b 4%, #b71b1c 8%, #b61e1d 15%, #b11d1d 27%, #ab1d1c 31%, #a51b1b 42%, #9f1b19 46%, #9f1b19 50%, #991c1a 54%, #971a18 58%, #911b1b 62%, #911b1b 65%, #7e1816 88%, #771919 92%, #731817 100%); background-image: linear-gradient(to bottom, #c11f1d 0%, #bf1d1b 4%, #b71b1c 8%, #b61e1d 15%, #b11d1d 27%, #ab1d1c 31%, #a51b1b 42%, #9f1b19 46%, #9f1b19 50%, #991c1a 54%, #971a18 58%, #911b1b 62%, #911b1b 65%, #7e1816 88%, #771919 92%, #731817 100%); }
.ss-assetuploadfield .ss-uploadfield-files .ui-state-error .ss-uploadfield-item-info .ss-uploadfield-item-name { width: 100%; cursor: default; background: #bcb9b9; background: rgba(201, 198, 198, 0.9); }
.ss-assetuploadfield .ss-uploadfield-files .ui-state-error .ss-uploadfield-item-info .ss-uploadfield-item-name .name { text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.7); }
.ss-assetuploadfield .ss-uploadfield-files .ui-state-warning .ss-uploadfield-item-info { background-color: #E9D104; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2U1ZDMzYiIvPjxzdG9wIG9mZnNldD0iOCUiIHN0b3AtY29sb3I9IiNlMmNlMjQiLz48c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iI2QxYmUxYyIvPjxzdG9wIG9mZnNldD0iNTQlIiBzdG9wLWNvbG9yPSIjZDFiZDFjIi8+PHN0b3Agb2Zmc2V0PSI5NiUiIHN0b3AtY29sb3I9IiNkMDlhMWEiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNjZjg3MWEiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA='); background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e5d33b), color-stop(8%, #e2ce24), color-stop(50%, #d1be1c), color-stop(54%, #d1bd1c), color-stop(96%, #d09a1a), color-stop(100%, #cf871a)); background-image: -moz-linear-gradient(top, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bd1c 54%, #d09a1a 96%, #cf871a 100%); background-image: -webkit-linear-gradient(top, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bd1c 54%, #d09a1a 96%, #cf871a 100%); background-image: linear-gradient(to bottom, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bd1c 54%, #d09a1a 96%, #cf871a 100%); }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name { position: relative; z-index: 1; margin: 3px 0 3px 50px; width: 50%; color: #5e5e5e; background: #eeeded; background: rgba(255, 255, 255, 0.8); -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; line-height: 24px; height: 22px; padding: 0 5px; text-align: left; cursor: pointer; display: table; table-layout: fixed; }
.ss-assetuploadfield .ss-uploadfield-files .ui-state-warning .ss-uploadfield-item-info { background-color: #E9D104; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2U1ZDMzYiIvPjxzdG9wIG9mZnNldD0iOCUiIHN0b3AtY29sb3I9IiNlMmNlMjQiLz48c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iI2QxYmUxYyIvPjxzdG9wIG9mZnNldD0iNTQlIiBzdG9wLWNvbG9yPSIjZDFiYzFiIi8+PHN0b3Agb2Zmc2V0PSI5NiUiIHN0b3AtY29sb3I9IiNkMDlhMWEiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNjZTg3MTkiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA='); background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e5d33b), color-stop(8%, #e2ce24), color-stop(50%, #d1be1c), color-stop(54%, #d1bc1b), color-stop(96%, #d09a1a), color-stop(100%, #ce8719)); background-image: -moz-linear-gradient(top, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bc1b 54%, #d09a1a 96%, #ce8719 100%); background-image: -webkit-linear-gradient(top, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bc1b 54%, #d09a1a 96%, #ce8719 100%); background-image: linear-gradient(to bottom, #e5d33b 0%, #e2ce24 8%, #d1be1c 50%, #d1bc1b 54%, #d09a1a 96%, #ce8719 100%); }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name { position: relative; z-index: 1; margin: 3px 0 3px 50px; width: 50%; color: #7f8c97; background: #eeeded; background: rgba(255, 255, 255, 0.8); -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; line-height: 24px; height: 22px; padding: 0 5px; text-align: left; cursor: pointer; display: table; table-layout: fixed; }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name .name { text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5); display: inline; float: left; max-width: 50%; font-weight: normal; padding: 0 5px 0 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; -o-text-overflow: ellipsis; }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name .ss-uploadfield-item-status { position: relative; float: right; padding: 0 0 0 5px; max-width: 30%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; -o-text-overflow: ellipsis; text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5); }
.ss-assetuploadfield .ss-uploadfield-files .ss-uploadfield-item-name .ss-uploadfield-item-status.ui-state-error-text { text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.6); color: #cc0000; }
@ -78,7 +78,7 @@ body.cms.ss-uploadfield-edit-iframe .fieldholder-small label, .composite.ss-asse
.ss-insert-media .ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-item-uploador { font-size: 18px; margin-top: -5px; }
.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone { margin-top: 9px; padding: 8px 0; -moz-border-radius: 13px; -webkit-border-radius: 13px; border-radius: 13px; -moz-box-shadow: rgba(128, 128, 128, 0.4) 0 0 4px 0 inset, 0 1px 0 #FAFAFA; -webkit-box-shadow: rgba(128, 128, 128, 0.4) 0 0 4px 0 inset, 0 1px 0 #FAFAFA; box-shadow: rgba(128, 128, 128, 0.4) 0 0 4px 0 inset, 0 1px 0 #FAFAFA; border: 2px dashed #808080; background: #d4dbe0; display: none; height: 54px; min-width: 280px; float: left; text-align: center; }
.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone.active.hover { -moz-box-shadow: rgba(255, 255, 255, 0.6) 0 0 3px 2px inset; -webkit-box-shadow: rgba(255, 255, 255, 0.6) 0 0 3px 2px inset; box-shadow: rgba(255, 255, 255, 0.6) 0 0 3px 2px inset; }
.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone div { color: #5e5e5e; text-shadow: 0px 1px 0px #fff; background: url("../images/upload.png") 0 10px no-repeat; z-index: 1; padding: 6px 48px 0; line-height: 25px; font-size: 20px; font-weight: bold; display: inline-block; }
.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone div { color: #7f8c97; text-shadow: 0px 1px 0px #fff; background: url("../images/upload.png") 0 10px no-repeat; z-index: 1; padding: 6px 48px 0; line-height: 25px; font-size: 20px; font-weight: bold; display: inline-block; }
.ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone div span { display: block; font-size: 12px; z-index: -1; margin-top: -3px; }
.ss-insert-media .ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone { height: 54px; min-width: 250px; overflow: hidden; padding: 0; margin-top: 2px; }
.ss-insert-media .ss-assetuploadfield .ss-uploadfield-addfile .ss-uploadfield-dropzone div { background-position: 0 11px; padding-top: 21px; margin-left: 33px; }

View File

@ -1,7 +1,7 @@
{
"version": 3,
"mappings": "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",
"sources": ["../scss/AssetUploadField.scss","../admin/scss/themes/_default.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_box-shadow.scss","../admin/scss/_mixins.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_border-radius.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_background-clip.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_images.scss","../scss/_elementMixins.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_text-shadow.scss"],
"mappings": "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",
"sources": ["../scss/AssetUploadField.scss","../admin/scss/themes/_default.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_box-shadow.scss","../admin/scss/_mixins.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_border-radius.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_background-clip.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_images.scss","../scss/_elementMixins.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_text-shadow.scss"],
"names": [],
"file": "AssetUploadField.css"
}

View File

@ -1,7 +1,7 @@
{
"version": 3,
"mappings": "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",
"sources": ["../scss/GridField.scss","../admin/scss/themes/_default.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_text-shadow.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_inline-block.scss","../admin/scss/_mixins.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_border-radius.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_images.scss","../scss/_elementMixins.scss"],
"sources": ["../scss/GridField.scss","../admin/scss/themes/_default.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_text-shadow.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_inline-block.scss","../admin/scss/_mixins.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_border-radius.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_images.scss","../scss/_elementMixins.scss"],
"names": [],
"file": "GridField.css"
}

View File

@ -12,14 +12,14 @@ Used in side panels and action tabs
*/
.ss-uploadfield .clear { clear: both; }
.ss-uploadfield .description { margin-left: 0; }
.ss-uploadfield .middleColumn { min-width: 510px; max-width: 600px; width: 100%; margin-left: 0; clear: both; padding: 0; background: #fff; border: 1px solid #b3b3b3; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2VmZWZlZiIvPjxzdG9wIG9mZnNldD0iMTAlIiBzdG9wLWNvbG9yPSIjZmZmZmZmIi8+PHN0b3Agb2Zmc2V0PSI5MCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNlZmVmZWYiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA='); background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #efefef), color-stop(10%, #ffffff), color-stop(90%, #ffffff), color-stop(100%, #efefef)); background-image: -moz-linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); background-image: -webkit-linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); background-image: linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); }
.ss-uploadfield .middleColumn { min-width: 510px; max-width: 696px; width: 100%; margin-left: 0; clear: both; padding: 0; background: #fff; border: 1px solid #b3b3b3; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2VmZWZlZiIvPjxzdG9wIG9mZnNldD0iMTAlIiBzdG9wLWNvbG9yPSIjZmZmZmZmIi8+PHN0b3Agb2Zmc2V0PSI5MCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNlZmVmZWYiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA='); background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #efefef), color-stop(10%, #ffffff), color-stop(90%, #ffffff), color-stop(100%, #efefef)); background-image: -moz-linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); background-image: -webkit-linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); background-image: linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); }
.ss-uploadfield .ss-uploadfield-item { margin: 0; padding: 15px; overflow: auto; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-preview { height: 60px; line-height: 60px; width: 80px; text-align: center; font-weight: bold; float: left; overflow: hidden; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-preview.ss-uploadfield-dropzone { -moz-box-shadow: #808080 0 0 4px 0 inset; -webkit-box-shadow: #808080 0 0 4px 0 inset; box-shadow: #808080 0 0 4px 0 inset; border: 2px dashed #808080; background: #d0d3d5; display: none; margin-right: 15px; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-preview.ss-uploadfield-dropzone { -moz-box-shadow: #808080 0 0 4px 0 inset; -webkit-box-shadow: #808080 0 0 4px 0 inset; box-shadow: #808080 0 0 4px 0 inset; border: 2px dashed #808080; background: #D2D5D8; display: none; margin-right: 15px; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info { margin-left: 95px; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name { display: block; line-height: 13px; height: 26px; margin: 0; text-align: left; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name .name { max-width: 240px; font-weight: bold; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; -o-text-overflow: ellipsis; display: inline; float: left; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name .size { color: #848484; padding: 0 0 0 5px; display: inline; float: left; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name .size { color: #a9b2b9; padding: 0 0 0 5px; display: inline; float: left; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name .ss-uploadfield-item-status { float: right; padding: 0 0 0 5px; text-align: right; max-width: 75%; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name .ss-uploadfield-item-status.ui-state-error-text { color: #f00; font-weight: bold; width: 150px; }
.ss-uploadfield .ss-uploadfield-item .ss-uploadfield-item-info .ss-uploadfield-item-name .ss-uploadfield-item-status.ui-state-warning-text { color: #b7a403; }
@ -34,7 +34,7 @@ Used in side panels and action tabs
.ss-uploadfield .ss-ui-button { display: block; float: left; margin: 0 10px 6px 0; }
.ss-uploadfield .ss-ui-button.ss-uploadfield-fromcomputer { position: relative; overflow: hidden; }
.ss-uploadfield .ss-uploadfield-files { margin: 0; padding: 0; overflow: auto; position: relative; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item, .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item.ui-state-error { border: 0; border-bottom: 1px solid #b3b3b3; background: none; color: #444; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item, .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item.ui-state-error { border: 0; border-bottom: 1px solid #b3b3b3; background: none; color: #66727d; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item:last-child, .ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item.ui-state-error:last-child { border-bottom: 0; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-actions { min-height: 28px; overflow: hidden; margin: 6px 0 -6px 0; position: relative; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-progress { position: absolute; left: 0; right: 42px; width: auto; margin: 11px 0 0; height: 15px; }
@ -49,7 +49,7 @@ Used in side panels and action tabs
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform { /* don't use display none, for it will break jQuery('iframe').contents().height() */ height: 0; overflow: hidden; clear: both; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform.loading { width: 100%; height: 22px; margin: 15px 0 0; background: url(../admin/images/spinner.gif) no-repeat 50% 0; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform.loading iframe { /* Old IE needs this or it'll give the iframe a white background, covering the spinner */ padding-top: 0; margin-top: 22px; border: none; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform iframe { margin-top: 8px; padding-top: 8px; border-top: 1px solid #d0d3d5; width: 100%; }
.ss-uploadfield .ss-uploadfield-files .ss-uploadfield-item-editform iframe { margin-top: 8px; padding-top: 8px; border-top: 1px solid #D2D5D8; width: 100%; }
.ss-uploadfield .ss-uploadfield-addfile.borderTop { border-top: 1px solid #b3b3b3; }
.ss-upload .clear { clear: both; }

View File

@ -1,7 +1,7 @@
{
"version": 3,
"mappings": "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",
"sources": ["../scss/UploadField.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_border-radius.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_images.scss","../../../../lib/gems/1.9.1/gems/compass-core-1.0.3/stylesheets/compass/css3/_box-shadow.scss","../admin/scss/themes/_default.scss","../admin/scss/_mixins.scss"],
"mappings": "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",
"sources": ["../scss/UploadField.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/_support.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_border-radius.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_images.scss","../../../../usr/local/share/gems/gems/compass-core-1.0.3/stylesheets/compass/css3/_box-shadow.scss","../admin/scss/themes/_default.scss","../admin/scss/_mixins.scss"],
"names": [],
"file": "UploadField.css"
}

View File

@ -524,7 +524,8 @@ function exceptionHandler($exception) {
$file = $exception->getFile();
$line = $exception->getLine();
$context = $exception->getTrace();
return Debug::fatalHandler($errno, $message, $file, $line, $context);
Debug::fatalHandler($errno, $message, $file, $line, $context);
exit(1);
}
/**
@ -558,6 +559,7 @@ function errorHandler($errno, $errstr, $errfile, $errline) {
case E_CORE_ERROR:
case E_USER_ERROR:
default:
return Debug::fatalHandler($errno, $errstr, $errfile, $errline, debug_backtrace());
Debug::fatalHandler($errno, $errstr, $errfile, $errline, debug_backtrace());
exit(1);
}
}

View File

@ -9,8 +9,8 @@ lets you install and upgrade SilverStripe and its modules. Although installing
Other ways to get SilverStripe:
* If you just want to get the code as quickly as possible, you can [download SilverStripe from our website](http://silverstripe.org/download).
* If you already have an installed version of SilverStripe, and you haven't used Composer to get it, please see our [upgrading](upgrading) guide. Note that [Composer](composer) provides its own tools for upgrading.
* If you just want to get the code as quickly as possible, you can [download SilverStripe from our website](http://www.silverstripe.org/software/download/).
* If you already have an installed version of SilverStripe, and you haven't used Composer to get it, please see our [upgrading](/upgrading) guide. Note that [Composer](composer) provides its own tools for upgrading.
## Setting up a server
@ -18,25 +18,25 @@ Other ways to get SilverStripe:
To run SilverStripe on Linux/Unix, set up one of the following web servers:
* [Install using Apache](webserver) - our preferred platform
* [Install using Lighttpd](lighttpd) - fast, but a bit tricker to get going
* [Install using Nginx](nginx) - Super fast at serving static files. Great for large traffic sites.
* [Install using nginx and HHVM](nginx-hhvm) - nginx and [HHVM](http://hhvm.com/) as a faster alternative to PHP
* [Install using Apache](installation) - our preferred platform
* [Install using Lighttpd](installation/how_to/configure_lighttpd) - fast, but a bit trickier to get going
* [Install using Nginx](installation/how_to/configure_nginx) - Super fast at serving static files. Great for large traffic sites.
* [Install using nginx and HHVM](installation/how_to/setup_nginx_and_hhvm) - nginx and [HHVM](http://hhvm.com/) as a faster alternative to PHP.
### Windows
The most straightforward way to get SilverStripe running on Windows is with the [Microsoft Web Platform installer](windows-pi). You can skip the "getting the code" step.
The most straightforward way to get SilverStripe running on Windows is with the [Microsoft Web Platform installer](installation/other_installation_options/windows_platform_installer). You can skip the "getting the code" step.
For more flexibility, you can set up either of the following web servers, and use Composer to get the code:
* [Install using IIS](windows-manual-iis)
* [Install using Apache/WAMP](windows-wamp)
* [Install using IIS](installation/other_installation_options/windows_iis7)
* [Install using Apache/WAMP](installation/windows)
### Mac OS X
Mac OS X comes with a built-in webserver, but there are a number of other options:
* [Install using MAMP](mac-osx)
* [Install using MAMP](installation/mac_osx)
* [Install using Homebrew](installation/other_installation_options/mac_osx_homebrew)
### Virtual Machines through Vagrant
@ -61,10 +61,9 @@ ready for download or installation on a cloud platform.
## Troubleshooting
If you run into trouble, see [common-problems](common-problems) or post to the
[SilverStripe forums](http://silverstripe.com/silverstripe-forum/).
If you run into trouble, see [common-problems](installation/common_problems) or post to the
[SilverStripe forums](http://silverstripe.org/community/forums/).
## Related
* [Module installation](../topics/modules)
* [Suggested web hosts](http://doc.silverstripe.org/old/suggested-web-hosts)
* [Module installation](/developer_guides/extending/modules)

View File

@ -27,6 +27,7 @@ These include video screencasts, written tutorials and code examples to get you
* [Lesson 15: Building a Search Form](http://www.silverstripe.org/learn/lessons/building-a-search-form)
* [Lesson 16: Lists and Pagination](http://www.silverstripe.org/learn/lessons/lists-and-pagination)
* [Lesson 17: Ajax Behaviour and Viewable Data](http://www.silverstripe.org/learn/lessons/ajax-behaviour-and-viewabledata)
* [Lesson 18: Dealing with Arbitrary Template Data](http://www.silverstripe.org/learn/lessons/dealing-with-arbitrary-template-data)
## Help: If you get stuck

View File

@ -80,7 +80,7 @@ does, such as `ArrayData` or `ArrayList`.
'Name' => 'John',
'Role' => 'Head Coach',
'Experience' => $experience
))->renderWith("AjaxTemplate");
)))->renderWith("AjaxTemplate");
} else {
return $this->httpError(404);
}

View File

@ -56,7 +56,7 @@ First we need to define a callback for the shortcode.
'MyShortCodeMethod' => 'HTMLText'
);
public function MyShortCodeMethod($arguments, $content = null, $parser = null, $tagName) {
public static function MyShortCodeMethod($arguments, $content = null, $parser = null, $tagName) {
return "<em>" . $tagName . "</em> " . $content . "; " . count($arguments) . " arguments.";
}
}

View File

@ -117,14 +117,16 @@ To use this backend, you need a memcached daemon and the memcache PECL extension
'primary_memcached',
'Memcached',
array(
'host' => 'localhost',
'port' => 11211,
'persistent' => true,
'weight' => 1,
'timeout' => 5,
'retry_interval' => 15,
'status' => true,
'failure_callback' => ''
'servers' => array(
'host' => 'localhost',
'port' => 11211,
'persistent' => true,
'weight' => 1,
'timeout' => 5,
'retry_interval' => 15,
'status' => true,
'failure_callback' => ''
)
)
);
SS_Cache::pick_backend('primary_memcached', 'any', 10);

View File

@ -1,6 +1,6 @@
# How to customize the CMS Menu
## Adding a administration panel
## Adding an administration panel
Every time you add a new extension of the `[api:LeftAndMain]` class to the CMS,
SilverStripe will automatically create a new `[api:CMSMenuItem]` for it

View File

@ -40,7 +40,7 @@ Never update a website on the live server without trying it on a development cop
How easy will it be to update my project? It's a fair question, and sometimes a difficult one to answer.
* "Micro" releases (x.y.z) are explicitly backwards compatible, "minor" and "major" releases can deprecate features and change APIs (see our [/misc/release-process](release process) for details)
* "Micro" releases (x.y.z) are explicitly backwards compatible, "minor" and "major" releases can deprecate features and change APIs (see our [/misc/release-process](../contributing/release_process) for details)
* If you've made custom branches of SilverStripe core, or any thirdparty module, it's going to be harder to upgrade.
* The more custom features you have, the harder it will be to upgrade. You will have to re-test all of those features, and adapt to API changes in core.
* Customizations of a well defined type - such as custom page types or custom blog widgets - are going to be easier to upgrade than customisations that modify deep system internals like rewriting SQL queries.

View File

@ -49,7 +49,7 @@
Use `set*()` and `add*()` methods instead.
* Template `<% control $MyList %>` syntax removed. Use `<% loop $MyList %>` instead.
* Removed `Member.LastVisited` and `Member.NumVisits` properties, see
[Howto: Track Member Logins](/extending/how_tos/track_member_logins) to restore functionality as custom code
[Howto: Track Member Logins](/developer_guides/extending/how_tos/track_member_logins) to restore functionality as custom code
## New and changed API

View File

@ -1,6 +1,9 @@
title: Contributing Code
summary: Fix bugs and add new features to help make SilverStripe better.
# Contributing Code - Submiting Bugfixes and Enhancements
SilverStripe will never be finished, and we need your help to keep making it better. If you're a developer a great way to get involved is to contribute patches to our modules and core codebase, fixing bugs or adding feautres.
SilverStripe will never be finished, and we need your help to keep making it better. If you're a developer a great way to get involved is to contribute patches to our modules and core codebase, fixing bugs or adding features.
The SilverStripe core modules (`framework` and `cms`), as well as some of the more popular modules are in
git version control. SilverStripe hosts its modules on [github.com/silverstripe](http://github.com/silverstripe) and [github.com/silverstripe-labs](http://github.com/silverstripe-labs). After [installing git](http://help.github.com/git-installation-redirect) and creating a [free github.com account](https://github.com/signup/free), you can "fork" a module,
@ -16,7 +19,9 @@ We ask for this so that the ownership in the license is clear and unambiguous, a
## Step-by-step: From forking to sending the pull request
_**NOTE:** The commands on this page assume that you are targetting framework version 3.2
<div class="notice" markdown='1'>
**Note:** Please adjust the commands below to the version of SilverStripe that you're targeting.
</div>
1. Install the project through composer. The process is described in detail in "[Installation through Composer](../getting_started/composer#contributing)".
@ -50,18 +55,18 @@ _**NOTE:** The commands on this page assume that you are targetting framework ve
# [make sure all your changes are committed as necessary in branch]
git fetch upstream
git rebase upstream/3.1
git rebase upstream/3.2
6. When development is complete, [squash all commit related to a single issue into a single commit](code#squash-all-commits-related-to-a-single-issue-into-a-single-commit).
git fetch upstream
git rebase -i upstream/3.1
git rebase -i upstream/3.2
7. Push release candidate branch to GitHub
git push origin ###-description
8. Issue pull request on GitHub. Visit your forked respoistory on GitHub.com and click the "Create Pull Request" button nex tot the new branch.
8. Issue pull request on GitHub. Visit your forked repository on GitHub.com and click the "Create Pull Request" button next to the new branch.
The core team is then responsible for reviewing patches and deciding if they will make it into core. If
there are any problems they will follow up with you, so please ensure they have a way to contact you!
@ -79,11 +84,11 @@ A core committer will also "label" your PR using the labels defined in GitHub, t
The current GitHub labels are grouped into 5 sections:
1. Changes - These are designed to signal what kind of change they are and how they fit into the [Semantic Versioning](http://semver.org/) schema
2. Impact - What impact does this bug/issue/fix have, does it break a feature completely, is it just a side effect or is it trivial and not a bit problem (but a bit annoying)
3. Effort - How much effort is required to fix this issue?
4. Type - What aspect of the system the PR/issue covers
5. Feedback - Are we waiting on feedback, if so who from? Typically used for issues that are likely to take a while to have feedback given
1. *Changes* - These are designed to signal what kind of change they are and how they fit into the [Semantic Versioning](http://semver.org/) schema
2. *Impact* - What impact does this bug/issue/fix have, does it break a feature completely, is it just a side effect or is it trivial and not a bit problem (but a bit annoying)
3. *Effort* - How much effort is required to fix this issue?
4. *Type* - What aspect of the system the PR/issue covers
5. *Feedback* - Are we waiting on feedback, if so who from? Typically used for issues that are likely to take a while to have feedback given
| Label | Purpose |
| ----- | ------- |
@ -102,9 +107,9 @@ The current GitHub labels are grouped into 5 sections:
| feedback-required/core-team | Core team members need to give an in-depth consideration |
| feedback-required/author | This issue is awaiting feedback from the original author of the PR |
### Workflow Diagram ###
### Workflow Diagram
![Workflow diagram](http://www.silverstripe.org/assets/doc-silverstripe-org/collaboration-on-github.png)
[![Workflow diagram](http://www.silverstripe.org/assets/doc-silverstripe-org/collaboration-on-github.png)](http://www.silverstripe.org/assets/doc-silverstripe-org/collaboration-on-github.png)
### Quickfire Do's and Don't's
@ -112,18 +117,18 @@ If you aren't familiar with git and GitHub, try reading the ["GitHub bootcamp do
We also found the [free online git book](http://git-scm.com/book/) and the [git crash course](http://gitref.org/) useful.
If you're familiar with it, here's the short version of what you need to know. Once you fork and download the code:
* **Don't develop on the master branch.** Always create a development branch specific to "the issue" you're working on (on our [GitHub repository's issues](https://github.com/silverstripe/silverstripe-framework/issues)). Name it by issue number and description. For example, if you're working on Issue #100, a `DataObject::get_one()` bugfix, your development branch should be called 100-dataobject-get-one. If you decide to work on another issue mid-stream, create a new branch for that issue--don't work on both in one branch.
* **Don't develop on the master branch.** Always create a development branch specific to "the issue" you're working on (on our [GitHub repository's issues](https://github.com/silverstripe/silverstripe-framework/issues)). Name it by issue number and description. For example, if you're working on Issue #100, a `DataObject::get_one()` bugfix, your development branch should be called 100-dataobject-get-one. If you decide to work on another issue mid-stream, create a new branch for that issue--don't work on both in one branch.
* **Do not merge the upstream master** with your development branch; *rebase* your branch on top of the upstream master.
* **Do not merge the upstream master** with your development branch; *rebase* your branch on top of the upstream master.
* **A single development branch should represent changes related to a single issue.** If you decide to work on another issue, create another branch.
* **A single development branch should represent changes related to a single issue.** If you decide to work on another issue, create another branch.
* **Squash your commits, so that each commit addresses a single issue.** After you rebase your work on top of the upstream master, you can squash multiple commits into one. Say, for instance, you've got three commits in related to Issue #100. Squash all three into one with the message "Issue #100 Description of the issue here." We won't accept pull requests for multiple commits related to a single issue; it's up to you to squash and clean your commit tree. (Remember, if you squash commits you've already pushed to GitHub, you won't be able to push that same branch again. Create a new local branch, squash, and push the new squashed branch.)
* **Squash your commits, so that each commit addresses a single issue.** After you rebase your work on top of the upstream master, you can squash multiple commits into one. Say, for instance, you've got three commits in related to Issue #100. Squash all three into one with the message "Description of the issue here (fixes #100)" We won't accept pull requests for multiple commits related to a single issue; it's up to you to squash and clean your commit tree. (Remember, if you squash commits you've already pushed to GitHub, you won't be able to push that same branch again. Create a new local branch, squash, and push the new squashed branch.)
* **Choose the correct branch**: Assume the current release is 3.0.3, and 3.1.0 is in beta state.
Most pull requests should go against the `3.1.x-dev` *pre-release branch*, only critical bugfixes
against the `3.0.x-dev` *release branch*. If you're changing an API or introducing a major feature,
the pull request should go against `master` (read more about our [release process](release_process)). Branches are periodically merged "upwards" (3.0 into 3.1, 3.1 into master).
* **Choose the correct branch**: Assume the current release is 3.0.3, and 3.1.0 is in beta state.
Most pull requests should go against the `3.1.x-dev` *pre-release branch*, only critical bugfixes
against the `3.0.x-dev` *release branch*. If you're changing an API or introducing a major feature,
the pull request should go against `master` (read more about our [release process](release_process)). Branches are periodically merged "upwards" (3.0 into 3.1, 3.1 into master).
### Editing files directly on GitHub.com
@ -133,21 +138,20 @@ After you have edited the file, GitHub will offer to create a pull request for y
## Check List
* Adhere to our [coding conventions](/getting_started/coding_conventions)
* If your patch is extensive, discuss it first on the [silverstripe-dev google group](https://groups.google.com/group/silverstripe-dev) (ideally before doing any serious coding)
* When working on existing tickets, provide status updates through ticket comments
* Check your patches against the "master" branch, as well as the latest release branch
* Write [unit tests](../developer_guides/testing/unit_testing)
* Write [Behat integration tests](https://github.com/silverstripe-labs/silverstripe-behat-extension) for any interface changes
* Describe specifics on how to test the effects of the patch
* It's better to submit multiple patches with separate bits of functionality than a big patch containing lots of
changes
* Only submit a pull request for work you expect to be ready to merge. Work in progress is best discussed in an issue, or on your own repository fork.
* Document your code inline through [PHPDoc](http://en.wikipedia.org/wiki/PHPDoc) syntax. See our
* Adhere to our [coding conventions](/getting_started/coding_conventions)
* If your patch is extensive, discuss it first on the [silverstripe-dev google group](https://groups.google.com/group/silverstripe-dev) (ideally before doing any serious coding)
* When working on existing tickets, provide status updates through ticket comments
* Check your patches against the "master" branch, as well as the latest release branch
* Write [unit tests](../developer_guides/testing/unit_testing)
* Write [Behat integration tests](https://github.com/silverstripe-labs/silverstripe-behat-extension) for any interface changes
* Describe specifics on how to test the effects of the patch
* It's better to submit multiple patches with separate bits of functionality than a big patch containing lots of changes
* Only submit a pull request for work you expect to be ready to merge. Work in progress is best discussed in an issue, or on your own repository fork.
* Document your code inline through [PHPDoc](http://en.wikipedia.org/wiki/PHPDoc) syntax. See our
[API documentation](http://api.silverstripe.org/3.1/) for good examples.
* Check and update documentation on [docs.silverstripe.org](http://docs.silverstripe.org). Check for any references to functionality deprecated or extended through your patch. Documentation changes should be included in the patch.
* If you get stuck, please post to the [forum](http://silverstripe.org/forum) or for deeper core problems, to the [core mailinglist](https://groups.google.com/forum/#!forum/silverstripe-dev)
* When working with the CMS, please read the ["CMS Architecture Guide"](cms_architecture) first
* When working with the CMS, please read the ["CMS Architecture Guide"](/developer_guides/customising_the_admin_interface/cms_architecture/) first
## Commit Messages
@ -159,10 +163,9 @@ This ensures commits are easy to browse, and look nice on github.com
As we automatically generate [changelogs](http://doc.silverstripe.org/sapphire/en/trunk/changelogs/) from them, we need a way to categorize and filter.
Please prefix **noteworthy** commit messages with one of the following tags:
* `NEW`: New feature or major enhancement (both for users and developers)
* `API`: Addition of a new API, or modification/removal/deprecation of an existing API.
Includes any change developers should be aware of when upgrading.
* `BUG`: Bugfix or minor enhancement on something developers or users are likely to encounter.
* `NEW` New feature or major enhancement (both for users and developers)
* `API` Addition of a new API, or modification/removal/deprecation of an existing API. Includes any change developers should be aware of when upgrading.
* `BUG` Bugfix or minor enhancement on something developers or users are likely to encounter.
All other commits should not be tagged if they are so trivial that most developers
can ignore them during upgrades or when reviewing changes to the codebase.
@ -195,16 +198,14 @@ Example: Good commit message
### Branch for new issue and develop on issue branch
Before you start working on a new feature or bugfix, create a new branch dedicated to that one change named by issue number and description. If you're working on Issue #100, a retweet bugfix, create a new branch with the issue number and description, like this:
Before you start working on a new feature or bugfix, create a new branch dedicated to that one change named by issue number and description. If you're working on Issue #100, a `DataObject::get_one()` bugfix, create a new branch with the issue number and description, like this:
$ git status
$ git branch 100-dataobject-get-one
$ git checkout 100-dataobject-get-one
$ git checkout -b 100-dataobject-get-one
Edit and test the files on your development environment. When you've got something the way you want and established that it works, commit the changes to your branch on your local git repo.
$ git add <filename>
$ git commit -m 'Issue #100: Some kind of descriptive message'
$ git commit -m 'Some kind of descriptive message (fixes #100)'
You'll need to use git add for each file that you created or modified. There are ways to add multiple files, but I highly recommend a more deliberate approach unless you know what you're doing.
@ -220,13 +221,13 @@ To keep your development branch up to date, rebase your changes on top of the cu
If you've set up an upstream branch as detailed above, and a development branch called `100-dataobject-get-one`, you can update `upstream` and rebase your branch from it like so:
# [make sure all your changes are committed as necessary in branch]
# make sure all your changes are committed as necessary in branch
$ git fetch upstream
$ git rebase upstream/master
Note that the example doesn't keep your own master branch up to date. If you wanted to that, you might take the following approach instead:
# [make sure all your changes are committed as necessary in branch]
# make sure all your changes are committed as necessary in branch
$ git fetch upstream
$ git checkout master
$ git rebase upstream/master
@ -248,11 +249,15 @@ To squash four commits into one, do the following:
$ git rebase -i upstream/master
In the text editor that comes up, replace the words "pick" with "squash" next to the commits you want to squash into the commit before it. Save and close the editor, and git will combine the "squash"'ed commits with the one before it. Git will then give you the opportunity to change your commit message to something like, "BUGFIX Issue #100: Fixed DataObject::get_one() parameter order"
In the text editor that comes up, replace the words "pick" with "squash" or just "s" next to the commits you want to squash into the commit before it.
Save and close the editor, and git will combine the "squash"'ed commits with the one before it.
Git will then give you the opportunity to change your commit message to something like, `BUG DataObject::get_one() parameter order (fixes #100)`.
If you want to discard the commit messages from the commits you're squashing and just use the message from your "pick" commit(s) you can use "fixup" or "f" instead of "squash" to bypass the message editing and make the process a bit quicker.
Important: If you've already pushed commits to GitHub, and then squash them locally, you will have to force-push to your GitHub again. Add the `-f` argument to your git push command:
$ git push -f origin 100-dataobject-get-one
$ git push -f origin 100-dataobject-get-one
Helpful hint: You can always edit your last commit message by using:
@ -274,21 +279,23 @@ Sometimes, you might correct an issue which was reported in a different repo. In
$ git commit -m 'Issue silverstripe/silverstripe-cms#100: Some kind of descriptive message'
Sometimes, you might correct an issue which was reported in a different repo. In these cases, don't simply refer to the issue number as GitHub will infer that as correcting an issue in the current repo. See [Commit Messages](code#commit-messages) above for the correct way to reference these issues.
## What is git rebase?
Using `git rebase` helps create clean commit trees and makes keeping your code up-to-date with the current state of the upstream master easy. Here's how it works.
Let's say you're working on Issue #212 a new plugin in your own branch and you start with something like this:
1---2---3 #212-my-new-plugin
/
A---B #master
1---2---3 #212-my-new-plugin
/
A---B #master
You keep coding for a few days and then pull the latest upstream stuff and you end up like this:
1---2---3 #212-my-new-plugin
/
A---B--C--D--E--F #master
1---2---3 #212-my-new-plugin
/
A---B--C--D--E--F #master
So all these new things (C,D,..F) have happened since you started. Normally you would just keep going (let's say you're not finished with the plugin yet) and then deal with a merge later on, which becomes a commit, which get moved upstream and ends up grafted on the tree forever.
@ -298,9 +305,9 @@ git rebase master 212-my-new-plugin
git will rewrite your commits like this:
1---2---3 #212-my-new-plugin
/
A---B--C--D--E--F #master
1---2---3 #212-my-new-plugin
/
A---B--C--D--E--F #master
It's as if you had just started your branch. One immediate advantage you get is that you can test your branch now to see if C, D, E, or F had any impact on your code (you don't need to wait until you're finished with your plugin and merge to find this out). And, since you can keep doing this over and over again as you develop your plugin, at the end your merge will just be a fast-forward (in other words no merge at all).

View File

@ -3,30 +3,30 @@ summary: Writing guide for contributing to SilverStripe developer and CMS user h
# Contributing documentation
Documentation for a software project is a continued and collaborative effort. We encourage everybody to contribute in any way they can, from simply fixing spelling mistakes, to writing recipes, to reviewing existing documentation and translating it to another language.
Documentation for a software project is a continuing, collaborative effort. We encourage everybody to contribute in any way they can, from simply fixing spelling mistakes, to writing recipes, reviewing existing documentation and translation to other languages.
Modifying documentation requires basic [PHPDoc](http://en.wikipedia.org/wiki/PHPDoc) and
[Markdown](http://daringfireball.net/projects/markdown/) knowledge, and a GitHub user account.
Modifying documentation requires basic knowledge of [PHPDoc](http://en.wikipedia.org/wiki/PHPDoc) and
[Markdown](http://daringfireball.net/projects/markdown/) as well as a GitHub user account.
## Editing online
The easiest way of editing any documentation is by clicking the "Edit this page" link at the bottom of the
The easiest way of editing any documentation is by clicking the "Edit this page" button at the bottom of the
page you want to edit. Alternatively, locate the appropriate .md file in the
[github.com/silverstripe/silverstripe-framework](https://github.com/silverstripe/silverstripe-framework/tree/master/docs/) repository and press the "edit" button. **You will need a free GitHub account to do this**.
* After editing the documentation, describe your changes in the "commit summary" and "extended description" fields below then press "Commit Changes".
* After that you will see a form to submit a Pull Request: "[pull requests](http://help.github.com/pull-requests/)". You should be able to adjust the version your documentation changes apply to and then submit the form. Your changes will be sent to the core committers for approval.
* After committing you changes, you will see a form to submit a Pull Request: "[pull requests](http://help.github.com/pull-requests/)". You should be able to adjust the version to which your documentation changes apply before submitting the form. Any changes submitted in a pull request will be sent to the core committers for approval.
<div class="warning" markdown='1'>
You should make your changes in the lowest branch they apply to. For instance, if you fix a spelling issue that you found in the 3.1 documentation, submit your fix to that branch in Github and it'll be copied to the master (3.2) version of the documentation automatically. *Don't submit multiple pull requests*.
You should make your changes in the lowest branch they apply to. For instance, if you fix a spelling issue that you found in the 3.2 documentation, submit your fix to that branch in Github and it'll be copied to the master (4.0) version of the documentation automatically. *Don't submit multiple pull requests*.
</div>
## Editing on your computer
If you prefer to edit content on your local machine, you can "[fork](http://help.github.com/forking/)" the
[github.com/silverstripe/silverstripe-framework](http://github.com/silverstripe/silverstripe-framework) and
[github.com/silverstripe/silverstripe-cms](http://github.com/silverstripe/silverstripe-cms) repositories, and send us "[pull requests](http://help.github.com/pull-requests/)" to incorporate your changes. If you have previously downloaded SilverStripe or a module, chances are that you already have these repositories on your machine.
[github.com/silverstripe/silverstripe-cms](http://github.com/silverstripe/silverstripe-cms) repositories, make changes locally, and then send us a "[pull request](http://help.github.com/pull-requests/)" to incorporate your changes. If you have previously downloaded SilverStripe or a module, chances are that you already have these repositories on your machine.
The documentation is kept alongside the source code in the `docs/` subfolder of any SilverStripe module, framework or CMS folder.
@ -36,8 +36,8 @@ If you submit a new feature or an API change, we strongly recommend that your pa
## Repositories
* End-user: [userhelp.silverstripe.org](http://github.com/silverstripe/userhelp.silverstripe.org)
* Developer guides: [doc.silverstripe.org](http://github.com/silverstripe/doc.silverstripe.org)
* End-user help: [userhelp.silverstripe.org](http://github.com/silverstripe/userhelp.silverstripe.org)
* Developer guides: [docs.silverstripe.org](http://github.com/silverstripe/docs.silverstripe.org)
* Developer API documentation: [api.silverstripe.org](http://github.com/silverstripe/api.silverstripe.org)
## Source control
@ -51,7 +51,7 @@ for documenting open source software.
## Structure
* Keep documentation lines to 120 characters.
* Keep documentation lines shorter than 120 characters.
* Don't duplicate: Search for existing places to put your documentation. Do you really require a new page, or just a new paragraph of text somewhere?
* Use PHPDoc in source code: Leave low level technical documentation to code comments within PHP, in [PHPDoc](http://en.wikipedia.org/wiki/PHPDoc) format.
* API and developer guides are two forms of source code documentation that complement each other.
@ -64,7 +64,7 @@ as "related content" on other resource (e.g. `/tutorials/site_search` might link
* Write in second person plural form: Use "we" instead of "I". It gives the text an instructive and collaborative style.
* It's okay to address the reader: For example "First you'll install a webserver" is good style.
* Write in an active and direct voice.
* Mark up correctly: Use preformatted text. Emphasis and bold make technical writing more easily "scannable".
* Mark up correctly: The use of preformatted text, emphasis and bold make technical writing easier to scan.
* Avoid FAQs: FAQs are not a replacement for coherent, well explained documentation. If you've done a good job
documenting, there shouldn't be any "frequently asked questions" left.
* "SilverStripe" should always appear without a space with both "S"s capitalised.
@ -73,7 +73,7 @@ documenting, there shouldn't be any "frequently asked questions" left.
* We use sentence case for titles so only capitalise the first letter of the first word of a title. The only exceptions to this are when using brand names (e.g. SilverStripe), acronyms (e.g. PHP) and class names (e.g. ModelAdmin).
* Use gender neutral language throughout the document, unless referencing a specific person. Use them, they, their, instead of he and she, his or her.
* URLs: if the end of your sentence is a URL then you don't need to use a full stop.
* Bullet points: Sentence case your bullet points. If a bullet point is a full sentence then end with a full stop. If it is a short point or a list, full stops are not required.
* Bullet points: Sentence case your bullet points. If a bullet point is a full sentence then end with a full stop. If it is a sentence fragment or a comma separated list, full stops are not required.
## Highlighted blocks
@ -117,7 +117,7 @@ on placing HTML blocks inside Markdown.
Documentation is kept alongside the source code, typically in a module subdirectory like `framework/docs/en/`. Each language has its own subfolder, which can duplicate parts of or the entire body of documentation. German documentation would, for example, live in `framework/docs/de/`. The
[docsviewer](https://github.com/silverstripe/silverstripe-docsviewer) module that drives
[doc.silverstripe.org](http://doc.silverstripe.org) automatically resolves these subfolders into a language dropdown.
[docs.silverstripe.org](http://docs.silverstripe.org) automatically resolves these subfolders into a language dropdown.
## Further reading

View File

@ -10,39 +10,39 @@ Honour the code of conduct whenever you participate formally and informally in o
* Experiment with your code and share the results.
* Ask questions if you get stuck.
* If you can answer questions be responsive and help guide others towards solutions
* If you can answer questions, be responsive and help guide others towards solutions.
* Share code and knowledge that might help others.
* The community is first and foremost about people sharing their knowledge to build something great together.
## Be empathetic, friendly and considerate.
* Welcome and encourage participation from everyone that wishes to join our community.
* Remember growing the community socially is as important as code related matters.
* Welcome and encourage participation from everyone that wishes to join and contribute to our community.
* Remember, growing the community socially is just as important as code related matters.
* Be respectful and honour diversity in our community. Sexist, racist, and other exclusionary jokes can offend those around you and are not appropriate.
* Keep your actions lawful, non-discriminatory, and unthreatening towards others.
## Respect the readers time.
* Be concise and read over things before you post.
* Mind your words, you write something once that will be read by many - being abusive, mean spirited and swearing at others does nothing to help get points across and drive constructive contributions to open source.
* Be clear when responding who you are representing, are you speaking on behalf of another business or acting in your capacity as an individual community member? Either is fine and encouraged and you should aim to make it clear to the reader.
* Mind your words; you write a single time but what you write will be read by many. Being abusive, mean spirited and swearing at others do nothing to help get your points across nor do they drive constructive collaboration and hence stimulate contributions to open source.
* Be clear about who you are representing when responding; are you speaking on behalf of another business or acting in your capacity as an individual community member? Either is fine and both are encouraged. Just make it clear to the reader.
## Respect different levels of participation.
* Welcome newcomers, spend a little time helping orientate them in our community.
* Welcome newcomers. Spend some time helping them to get orientated in our community.
* All contributors and core committers, module maintainers and knowledge sharers are participating in the community in a voluntary nature. Have respect for them and their time when making requests. You may need to exercise some patience.
* Whenever possible reference your comments to others with example code or links to documentation. This helps people learn and become more experienced community members and developers.
* If you manage to solve your own problem, tell others how you solved it. This will help people in the future that find they have the same problem as you.
* If you are reducing your input and potentially stepping away from the community please remember others might rely on your contributions. Be prepared to ensure these are kept open and available, spend some time handing over to another community member or core contributor to help continuity of SilverStripe open source.
* Whenever possible, reference your comments to others with example code or links to documentation. This helps people learn and become more experienced community members and developers.
* If you manage to solve your own problem, tell others how you solved it. This will help people in the future who have to solve similar problems.
* If you are reducing your input, and potentially stepping away from the community, please remember that others might be relying on your contributions. Be prepared to ensure your contributions remain open and available to the community. Spend some time handing your contributions over to another community member or core contributor to help with the continuity of SilverStripe open source development.
## Resolve conflicts directly
* Conflict may eventuate from time to time, we should view it as a constructive process. Understanding others positions without descending into ad hominem attacks is valuable.
* Involve a 3rd party or if necessary inform a core committer if conflicts continue to escalate.
* Breaches of the code of conduct by community members may first result in a reminder about the code of conduct (we realise we're all human and sometimes we have bad days).
* Repeated and deliberate breaching after this will be referred to the core committers team and may result in members being asked to leave the community channels.
* Conflict may eventuate from time to time. We should all try to view it as a constructive process. Understanding others' positions, without descending into ad hominem attacks, is valuable and may lead to better solutions to problems.
* Involve a 3rd party. If necessary, inform a core committer if a conflict continues to escalate.
* Breaches of the code of conduct by a community member may result in a first reminder about the code of conduct (we realise we're all human and sometimes we have bad days).
* Repeated and deliberate breachings of the code of conduct following this first reminder will be referred on to the team of core committers and may result in the member being asked to leave the community channels.
* While we have a policy of not removing postings and comments from our digital channels, there may be times in which items are removed if deemed blatantly discriminatory towards individuals, groups or cultures.
* Call others on their behaviour within the community and remind them of this code where necessary.
* Refer to [these helpful guides on conflict resolution](http://www.crnhq.org/pages.php?pID=10) to aid you.
* If a member behaves inappropriately, politely bring this to their attention and gently remind them of the code of conduct when necessary.
* Refer to [these helpful guides on conflict resolution](http://www.crnhq.org/pages.php?pID=10) to aid you when dealing with a conflict.
## A living document
* This is a living document, as core committers we don't have all the answers and we attempt to make the community an innovative and valuable space for everyone that wishes to participate.
* This is a living document. As core committers, we know we don't have all the answers so we want to make the community an innovative and valuable space for everyone that wishes to contribute.
* If you would like to improve the wording, add additional items, or simply fix typos, each contribution to the code of conduct will be considered on it's merit and agreed upon unanimously by the core committers. Any changes will be included in future revisions of the SilverStripe code of conduct.

View File

@ -140,10 +140,10 @@ class File extends DataObject {
private static $app_categories = array(
'audio' => array(
"aif" ,"au" ,"mid" ,"midi" ,"mp3" ,"ra" ,"ram" ,"rm","mp3" ,"wav" ,"m4a" ,"snd" ,"aifc" ,"aiff" ,"wma",
"apl", "avr" ,"cda" ,"mp4" ,"ogg"
"apl", "avr" ,"cda" ,"ogg"
),
'mov' => array(
"mpeg" ,"mpg" ,"m1v" ,"mp2" ,"mpa" ,"mpe" ,"ifo" ,"vob","avi" ,"wmv" ,"asf" ,"m2v" ,"qt", "ogv", "webm"
"mpeg" ,"mpg" ,"mp4" ,"m1v" ,"mp2" ,"mpa" ,"mpe" ,"ifo" ,"vob","avi" ,"wmv" ,"asf" ,"m2v" ,"qt", "ogv", "webm"
),
'zip' => array(
"arc" ,"rar" ,"tar" ,"gz" ,"tgz" ,"bz2" ,"dmg" ,"jar","ace" ,"arj" ,"bz" ,"cab"

View File

@ -3,20 +3,22 @@
/**
* Represents a field in a form.
*
* A FieldList contains a number of FormField objects which make up the whole
* of a form. In addition to single fields, FormField objects can be
* "composite", for example, the {@link TabSet} field. Composite fields let us
* define complex forms without having to resort to custom HTML.
* A FieldList contains a number of FormField objects which make up the whole of a form.
*
* <b>Subclassing</b>
* In addition to single fields, FormField objects can be "composite", for example, the
* {@link TabSet} field. Composite fields let us define complex forms without having to resort to
* custom HTML.
*
* Define a {@link dataValue()} method that returns a value suitable for
* inserting into a single database field. For example, you might tidy up the
* format of a date or currency field. Define {@link saveInto()} to totally
* customise saving. For example, data might be saved to the filesystem instead
* of the data record, or saved to a component of the data record instead of
* the data record itself. Define {@link validate()} to validate the form field
* and ensure that the content provided is valid.
* To subclass:
*
* Define a {@link dataValue()} method that returns a value suitable for inserting into a single
* database field.
*
* For example, you might tidy up the format of a date or currency field. Define {@link saveInto()}
* to totally customise saving.
*
* For example, data might be saved to the filesystem instead of the data record, or saved to a
* component of the data record instead of the data record itself.
*
* @package forms
* @subpackage core
@ -28,16 +30,49 @@ class FormField extends RequestHandler {
*/
protected $form;
protected $name, $title, $value ,$message, $messageType, $extraClass;
/**
* @var string
*/
protected $name;
/**
* @var $description string Adds a "title"-attribute to the markup.
* @var null|string
*/
protected $title;
/**
* @var mixed
*/
protected $value;
/**
* @var string
*/
protected $message;
/**
* @var string
*/
protected $messageType;
/**
* @var string
*/
protected $extraClass;
/**
* Adds a title attribute to the markup.
*
* @var string
*
* @todo Implement in all subclasses
*/
protected $description;
/**
* @var $extraClasses array Extra CSS-classes for the formfield-container
* Extra CSS classes for the FormField container.
*
* @var array
*/
protected $extraClasses;
@ -47,85 +82,111 @@ class FormField extends RequestHandler {
*/
private static $default_classes = array();
/**
* @var bool
*/
public $dontEscape;
/**
* @var $rightTitle string Used in SmallFieldHolder to force a right-aligned label, or in FieldHolder
* to create contextual label.
* Right-aligned, contextual label for the field.
*
* @var string
*/
protected $rightTitle;
/**
* @var $leftTitle string Used in SmallFieldHolder() to force a left-aligned label with correct spacing.
* Please use $title for FormFields rendered with FieldHolder().
* Left-aligned, contextual label for the field.
*
* @var string
*/
protected $leftTitle;
/**
* Stores a reference to the FieldList that contains this object.
*
* @var FieldList
*/
protected $containerFieldList;
/**
* @var boolean
* @var bool
*/
protected $readonly = false;
/**
* @var boolean
* @var bool
*/
protected $disabled = false;
/**
* @var string custom validation message for the Field
*/
protected $customValidationMessage = "";
/**
* Name of the template used to render this form field. If not set, then
* will look up the class ancestry for the first matching template where
* the template name equals the class name.
*
* To explicitly use a custom template or one named other than the form
* field see {@link setTemplate()}, {@link setFieldHolderTemplate()}
* Custom validation message for the field.
*
* @var string
*/
protected
$template,
$fieldHolderTemplate,
$smallFieldHolderTemplate;
protected $customValidationMessage = '';
/**
* @var array All attributes on the form field (not the field holder).
* Partially determined based on other instance properties, please use {@link getAttributes()}.
* Name of the template used to render this form field. If not set, then will look up the class
* ancestry for the first matching template where the template name equals the class name.
*
* To explicitly use a custom template or one named other than the form field see
* {@link setTemplate()}.
*
* @var string
*/
protected $template;
/**
* Name of the template used to render this form field. If not set, then will look up the class
* ancestry for the first matching template where the template name equals the class name.
*
* To explicitly use a custom template or one named other than the form field see
* {@link setFieldHolderTemplate()}.
*
* @var string
*/
protected $fieldHolderTemplate;
/**
* @var string
*/
protected $smallFieldHolderTemplate;
/**
* All attributes on the form field (not the field holder).
*
* Partially determined based on other instance properties.
*
* @see getAttributes()
*
* @var array
*/
protected $attributes = array();
/**
* Takes a fieldname and converts camelcase to spaced
* words. Also resolves combined fieldnames with dot syntax
* to spaced words.
* Takes a field name and converts camelcase to spaced words. Also resolves combined field
* names with dot syntax to spaced words.
*
* Examples:
*
* - 'TotalAmount' will return 'Total Amount'
* - 'Organisation.ZipCode' will return 'Organisation Zip Code'
*
* @param string $fieldName
*
* @return string
*/
public static function name_to_label($fieldName) {
if(strpos($fieldName, '.') !== false) {
$parts = explode('.', $fieldName);
$label = $parts[count($parts)-2] . ' ' . $parts[count($parts)-1];
$label = $parts[count($parts) - 2] . ' ' . $parts[count($parts) - 1];
} else {
$label = $fieldName;
}
$label = preg_replace("/([a-z]+)([A-Z])/","$1 $2", $label);
return $label;
return preg_replace('/([a-z]+)([A-Z])/', '$1 $2', $label);
}
/**
@ -133,41 +194,51 @@ class FormField extends RequestHandler {
*
* @param string $tag
* @param array $attributes
* @param mixed $content
* @param null|string $content
*
* @return string
*/
public static function create_tag($tag, $attributes, $content = null) {
$preparedAttributes = '';
foreach($attributes as $k => $v) {
// Note: as indicated by the $k == value item here; the decisions over what to include in the attributes
// can sometimes get finicky
if(!empty($v) || $v === '0' || ($k == 'value' && $v !== null) ) {
$preparedAttributes .= " $k=\"" . Convert::raw2att($v) . "\"";
foreach($attributes as $attributeKey => $attributeValue) {
if(!empty($attributeValue) || $attributeValue === '0' || ($attributeKey == 'value' && $attributeValue !== null)) {
$preparedAttributes .= sprintf(
' %s="%s"', $attributeKey, Convert::raw2att($attributeValue)
);
}
}
if($content || $tag != 'input') {
return "<$tag$preparedAttributes>$content</$tag>";
}
else {
return "<$tag$preparedAttributes />";
return sprintf(
'<%s%s>%s</%s>', $tag, $preparedAttributes, $content, $tag
);
}
return sprintf(
'<%s%s />', $tag, $preparedAttributes
);
}
/**
* Creates a new field.
*
* @param string $name The internal field name, passed to forms.
* @param string $title The human-readable field label.
* @param null|string $title The human-readable field label.
* @param mixed $value The value of the field.
*/
public function __construct($name, $title = null, $value = null) {
$this->name = $name;
$this->title = ($title === null) ? self::name_to_label($name) : $title;
if($value !== NULL) $this->setValue($value);
if($title === null) {
$this->title = self::name_to_label($name);
} else {
$this->title = $title;
}
if($value !== null) {
$this->setValue($value);
}
parent::__construct();
@ -175,7 +246,7 @@ class FormField extends RequestHandler {
}
/**
* set up the default classes for the form. This is done on construct so that the default classes can be removed
* Set up the default classes for the form. This is done on construct so that the default classes can be removed
* after instantiation
*/
protected function setupDefaultClasses() {
@ -199,10 +270,10 @@ class FormField extends RequestHandler {
}
/**
* Returns the HTML ID of the field - used in the template by label tags.
* Returns the HTML ID of the field.
*
* The ID is generated as FormName_FieldName. All Field functions should ensure
* that this ID is included in the field.
* The ID is generated as FormName_FieldName. All Field functions should ensure that this ID is
* included in the field.
*
* @return string
*/
@ -237,7 +308,7 @@ class FormField extends RequestHandler {
}
/**
* Returns the raw field name.
* Returns the field name.
*
* @return string
*/
@ -257,10 +328,11 @@ class FormField extends RequestHandler {
}
/**
* Returns the field message type, used by form validation.
* Returns the field message type.
*
* Arbitrary value which is mostly used for CSS classes in the rendered HTML,
* e.g. "required". Use {@link setError()} to set this property.
* Arbitrary value which is mostly used for CSS classes in the rendered HTML, e.g "required".
*
* Use {@link setError()} to set this property.
*
* @return string
*/
@ -269,7 +341,9 @@ class FormField extends RequestHandler {
}
/**
* Returns the field value - used by templates.
* Returns the field value.
*
* @return mixed
*/
public function Value() {
return $this->value;
@ -289,8 +363,7 @@ class FormField extends RequestHandler {
}
/**
* Returns the field value suitable for insertion into the
* {@link DataObject}.
* Returns the field value suitable for insertion into the data object.
*
* @return mixed
*/
@ -308,12 +381,13 @@ class FormField extends RequestHandler {
}
/**
* @param string $val
* @param string $title
*
* @return FormField
* @return $this
*/
public function setTitle($val) {
$this->title = $val;
public function setTitle($title) {
$this->title = $title;
return $this;
}
@ -328,56 +402,78 @@ class FormField extends RequestHandler {
}
/**
* Sets the contextual label.
* @param string $rightTitle
*
* @param $val string Text to set on the label.
* @return $this
*/
public function setRightTitle($val) {
$this->rightTitle = $val;
return $this;
}
public function setRightTitle($rightTitle) {
$this->rightTitle = $rightTitle;
public function LeftTitle() {
return $this->leftTitle;
}
public function setLeftTitle($val) {
$this->leftTitle = $val;
return $this;
}
/**
* Compiles all CSS-classes. Optionally includes a "nolabel"-class
* if no title was set on the formfield.
* Uses {@link Message()} and {@link MessageType()} to add validatoin
* error classes which can be used to style the contained tags.
* @return string
*/
public function LeftTitle() {
return $this->leftTitle;
}
/**
* @param string $leftTitle
*
* @return string CSS-classnames
* @return $this
*/
public function setLeftTitle($leftTitle) {
$this->leftTitle = $leftTitle;
return $this;
}
/**
* Compiles all CSS-classes. Optionally includes a "nolabel" class if no title was set on the
* FormField.
*
* Uses {@link Message()} and {@link MessageType()} to add validation error classes which can
* be used to style the contained tags.
*
* @return string
*/
public function extraClass() {
$classes = array();
$classes[] = $this->Type();
if($this->extraClasses) $classes = array_merge($classes, array_values($this->extraClasses));
if($this->extraClasses) {
$classes = array_merge(
$classes,
array_values($this->extraClasses)
);
}
// Allow customization of label and field tag positioning
if(!$this->Title()) $classes[] = "nolabel";
if(!$this->Title()) {
$classes[] = 'nolabel';
}
// Allow custom styling of any element in the container based
// on validation errors, e.g. red borders on input tags.
// CSS-Class needs to be different from the one rendered
// through {@link FieldHolder()}
if($this->Message()) $classes[] .= "holder-" . $this->MessageType();
// Allow custom styling of any element in the container based on validation errors,
// e.g. red borders on input tags.
//
// CSS class needs to be different from the one rendered through {@link FieldHolder()}.
if($this->Message()) {
$classes[] .= 'holder-' . $this->MessageType();
}
return implode(' ', $classes);
}
/**
* Add one or more CSS-classes to the formfield-container. Multiple class
* names should be space delimited.
* Add one or more CSS-classes to the FormField container.
*
* Multiple class names should be space delimited.
*
* @param string $class
*
* @return $this
*/
public function addExtraClass($class) {
$classes = preg_split('/\s+/', $class);
@ -390,9 +486,11 @@ class FormField extends RequestHandler {
}
/**
* Remove one or more CSS-classes from the formfield-container.
* Remove one or more CSS-classes from the FormField container.
*
* @param string $class
*
* @return $this
*/
public function removeExtraClass($class) {
$classes = preg_split('/\s+/', $class);
@ -407,34 +505,43 @@ class FormField extends RequestHandler {
/**
* Set an HTML attribute on the field element, mostly an <input> tag.
*
* Some attributes are best set through more specialized methods, to avoid interfering with built-in behaviour:
* Some attributes are best set through more specialized methods, to avoid interfering with
* built-in behaviour:
*
* - 'class': {@link addExtraClass()}
* - 'title': {@link setDescription()}
* - 'value': {@link setValue}
* - 'name': {@link setName}
*
* CAUTION Doesn't work on most fields which are composed of more than one HTML form field:
* AjaxUniqueTextField, CheckboxSetField, CompositeField, ConfirmedPasswordField,
* CountryDropdownField, CreditCardField, CurrencyField, DateField, DatetimeField, FieldGroup, GridField,
* HtmlEditorField, ImageField, ImageFormAction, InlineFormAction, ListBoxField, etc.
* Caution: this doesn't work on most fields which are composed of more than one HTML form
* field.
*
* @param string
* @param string
* @param string $name
* @param string $value
*
* @return $this
*/
public function setAttribute($name, $value) {
$this->attributes[$name] = $value;
return $this;
}
/**
* Get an HTML attribute defined by the field, or added through {@link setAttribute()}.
* Caution: Doesn't work on all fields, see {@link setAttribute()}.
*
* @return string
* Caution: this doesn't work on all fields, see {@link setAttribute()}.
*
* @return null|string
*/
public function getAttribute($name) {
$attrs = $this->getAttributes();
if(isset($attrs[$name])) return $attrs[$name];
$attributes = $this->getAttributes();
if(isset($attributes[$name])) {
return $attributes[$name];
}
return null;
}
/**
@ -445,7 +552,7 @@ class FormField extends RequestHandler {
* @return array
*/
public function getAttributes() {
$attrs = array(
$attributes = array(
'type' => 'text',
'name' => $this->getName(),
'value' => $this->Value(),
@ -455,54 +562,67 @@ class FormField extends RequestHandler {
'readonly' => $this->isReadonly()
);
if ($this->Required()) {
$attrs['required'] = 'required';
$attrs['aria-required'] = 'true';
if($this->Required()) {
$attributes['required'] = 'required';
$attributes['aria-required'] = 'true';
}
$attrs = array_merge($attrs, $this->attributes);
$attributes = array_merge($attributes, $this->attributes);
$this->extend('updateAttributes', $attrs);
$this->extend('updateAttributes', $attributes);
return $attrs;
return $attributes;
}
/**
* @param Array Custom attributes to process. Falls back to {@link getAttributes()}.
* If at least one argument is passed as a string, all arguments act as excludes by name.
* Custom attributes to process. Falls back to {@link getAttributes()}.
*
* @return string HTML attributes, ready for insertion into an HTML tag
* If at least one argument is passed as a string, all arguments act as excludes, by name.
*
* @param array $attributes
*
* @return string
*/
public function getAttributesHTML($attrs = null) {
$exclude = (is_string($attrs)) ? func_get_args() : null;
public function getAttributesHTML($attributes = null) {
$exclude = null;
if(!$attrs || is_string($attrs)) {
$attrs = $this->getAttributes();
if(is_string($attributes)) {
$exclude = func_get_args();
}
// Remove empty
$attrs = array_filter((array)$attrs, function($v) {
if(!$attributes || is_string($attributes)) {
$attributes = $this->getAttributes();
}
$attributes = (array) $attributes;
$attributes = array_filter($attributes, function ($v) {
return ($v || $v === 0 || $v === '0');
});
// Remove excluded
if($exclude) {
$attrs = array_diff_key($attrs, array_flip($exclude));
$attributes = array_diff_key(
$attributes,
array_flip($exclude)
);
}
// Create markup
$parts = array();
foreach($attrs as $name => $value) {
$parts[] = ($value === true) ? "{$name}=\"{$name}\"" : "{$name}=\"" . Convert::raw2att($value) . "\"";
foreach($attributes as $name => $value) {
if($value === true) {
$parts[] = sprintf('%s="%s"', $name, $name);
} else {
$parts[] = sprintf('%s="%s"', $name, Convert::raw2att($value));
}
}
return implode(' ', $parts);
}
/**
* Returns a version of a title suitable for insertion into an HTML
* attribute.
* Returns a version of a title suitable for insertion into an HTML attribute.
*
* @return string
*/
@ -511,8 +631,7 @@ class FormField extends RequestHandler {
}
/**
* Returns a version of a title suitable for insertion into an HTML
* attribute.
* Returns a version of a title suitable for insertion into an HTML attribute.
*
* @return string
*/
@ -524,8 +643,9 @@ class FormField extends RequestHandler {
* Set the field value.
*
* @param mixed $value
* @param mixed $data Optional data source passed in by {@see Form::loadDataFrom}
* @return FormField Self reference
* @param null|array|DataObject $data {@see Form::loadDataFrom}
*
* @return $this
*/
public function setValue($value) {
$this->value = $value;
@ -534,11 +654,11 @@ class FormField extends RequestHandler {
}
/**
* Set the field name
* Set the field name.
*
* @param string $name
*
* @return FormField
* @return $this
*/
public function setName($name) {
$this->name = $name;
@ -549,12 +669,11 @@ class FormField extends RequestHandler {
/**
* Set the container form.
*
* This is called whenever you create a new form and put fields inside it,
* so that you don't have to worry about linking the two.
* This is called automatically when fields are added to forms.
*
* @param Form
* @param Form $form
*
* @return FormField
* @return $this
*/
public function setForm($form) {
$this->form = $form;
@ -572,8 +691,7 @@ class FormField extends RequestHandler {
}
/**
* Return TRUE if security token protection is enabled on the parent
* {@link Form}.
* Return true if security token protection is enabled on the parent {@link Form}.
*
* @return bool
*/
@ -588,10 +706,14 @@ class FormField extends RequestHandler {
}
/**
* @param string $message Message to show to the user. Allows HTML content,
* which means you need to use Convert::raw2xml() for any user supplied data.
* Sets the error message to be displayed on the form field.
*
* Allows HTML content, so remember to use Convert::raw2xml().
*
* @param string $message
* @param string $messageType
* @return FormField
*
* @return $this
*/
public function setError($message, $messageType) {
$this->message = $message;
@ -601,24 +723,23 @@ class FormField extends RequestHandler {
}
/**
* Set the custom error message to show instead of the default
* format of Please Fill In XXX. Different from setError() as
* that appends it to the standard error messaging.
* Set the custom error message to show instead of the default format.
*
* @param string $msg Message for the error
* Different from setError() as that appends it to the standard error messaging.
*
* @return FormField
* @param string $customValidationMessage
*
* @return $this
*/
public function setCustomValidationMessage($msg) {
$this->customValidationMessage = $msg;
public function setCustomValidationMessage($customValidationMessage) {
$this->customValidationMessage = $customValidationMessage;
return $this;
}
/**
* Get the custom error message for this form field. If a custom
* message has not been defined then just return blank. The default
* error is defined on {@link Validator}.
* Get the custom error message for this form field. If a custom message has not been defined
* then just return blank. The default error is defined on {@link Validator}.
*
* @return string
*/
@ -629,12 +750,12 @@ class FormField extends RequestHandler {
/**
* Set name of template (without path or extension).
*
* Caution: Not consistently implemented in all subclasses, please check
* the {@link Field()} method on the subclass for support.
* Caution: Not consistently implemented in all subclasses, please check the {@link Field()}
* method on the subclass for support.
*
* @param string $template
*
* @return FormField
* @return $this
*/
public function setTemplate($template) {
$this->template = $template;
@ -657,18 +778,18 @@ class FormField extends RequestHandler {
}
/**
* Set name of template (without path or extension) for the holder,
* which in turn is responsible for rendering {@link Field()}.
* Set name of template (without path or extension) for the holder, which in turn is
* responsible for rendering {@link Field()}.
*
* Caution: Not consistently implemented in all subclasses,
* please check the {@link Field()} method on the subclass for support.
* Caution: Not consistently implemented in all subclasses, please check the {@link Field()}
* method on the subclass for support.
*
* @param string $template
* @param string $fieldHolderTemplate
*
* @return FormField
* @return $this
*/
public function setFieldHolderTemplate($template) {
$this->fieldHolderTemplate = $template;
public function setFieldHolderTemplate($fieldHolderTemplate) {
$this->fieldHolderTemplate = $fieldHolderTemplate;
return $this;
}
@ -681,50 +802,67 @@ class FormField extends RequestHandler {
}
/**
* Set name of template (without path or extension) for the small holder,
* which in turn is responsible for rendering {@link Field()}.
* Set name of template (without path or extension) for the small holder, which in turn is
* responsible for rendering {@link Field()}.
*
* Caution: Not consistently implemented in all subclasses,
* please check the {@link Field()} method on the subclass for support.
* Caution: Not consistently implemented in all subclasses, please check the {@link Field()}
* method on the subclass for support.
*
* @param string
* @param string $smallFieldHolderTemplate
*
* @return $this
*/
public function setSmallFieldHolderTemplate($template) {
$this->smallFieldHolderTemplate = $template;
public function setSmallFieldHolderTemplate($smallFieldHolderTemplate) {
$this->smallFieldHolderTemplate = $smallFieldHolderTemplate;
return $this;
}
/**
* Returns the form field - used by templates.
* Returns the form field.
*
* Although FieldHolder is generally what is inserted into templates, all of the field holder
* templates make use of $Field. It's expected that FieldHolder will give you the "complete"
* templates make use of $Field. It's expected that FieldHolder will give you the "complete"
* representation of the field on the form, whereas Field will give you the core editing widget,
* such as an input tag.
*
* @param array $properties key value pairs of template variables
* @param array $properties
*
* @return string
*/
public function Field($properties = array()) {
$obj = ($properties) ? $this->customise($properties) : $this;
$context = $this;
if(count($properties)) {
$context = $context->customise($properties);
}
$this->extend('onBeforeRender', $this);
return $obj->renderWith($this->getTemplates());
return $context->renderWith($this->getTemplates());
}
/**
* Returns a "field holder" for this field - used by templates.
* Returns a "field holder" for this field.
*
* Forms are constructed by concatenating a number of these field holders.
*
* The default field holder is a label and a form field inside a div.
*
* @see FieldHolder.ss
*
* @param array $properties key value pairs of template variables
* @param array $properties
*
* @return string
*/
public function FieldHolder($properties = array()) {
$obj = ($properties) ? $this->customise($properties) : $this;
$context = $this;
return $obj->renderWith($this->getFieldHolderTemplates());
if(count($properties)) {
$context = $this->customise($properties);
}
return $context->renderWith($this->getFieldHolderTemplates());
}
/**
@ -735,13 +873,17 @@ class FormField extends RequestHandler {
* @return string
*/
public function SmallFieldHolder($properties = array()) {
$obj = ($properties) ? $this->customise($properties) : $this;
$context = $this;
return $obj->renderWith($this->getSmallFieldHolderTemplates());
if(count($properties)) {
$context = $this->customise($properties);
}
return $context->renderWith($this->getSmallFieldHolderTemplates());
}
/**
* Returns an array of templates to use for rendering {@link FieldH}
* Returns an array of templates to use for rendering {@link FieldHolder}.
*
* @return array
*/
@ -750,7 +892,7 @@ class FormField extends RequestHandler {
}
/**
* Returns an array of templates to use for rendering {@link FieldHolder}
* Returns an array of templates to use for rendering {@link FieldHolder}.
*
* @return array
*/
@ -762,7 +904,7 @@ class FormField extends RequestHandler {
}
/**
* Returns an array of templates to use for rendering {@link SmallFieldHolder}
* Returns an array of templates to use for rendering {@link SmallFieldHolder}.
*
* @return array
*/
@ -775,31 +917,37 @@ class FormField extends RequestHandler {
/**
* Generate an array of classname strings to use for rendering this form
* field into HTML
* Generate an array of class name strings to use for rendering this form field into HTML.
*
* @param string $custom custom template (if set)
* @param string $suffix template suffix
* @param string $customTemplate
* @param string $customTemplateSuffix
*
* @return array $stack a stack of
* @return array
*/
private function _templates($custom = null, $suffix = null) {
private function _templates($customTemplate = null, $customTemplateSuffix = null) {
$matches = array();
foreach(array_reverse(ClassInfo::ancestry($this)) as $className) {
$matches[] = $className . $suffix;
$matches[] = $className . $customTemplateSuffix;
if($className == "FormField") break;
if($className == "FormField") {
break;
}
}
if($custom) array_unshift($matches, $custom);
if($customTemplate) {
array_unshift($matches, $customTemplate);
}
return $matches;
}
/**
* Returns true if this field is a composite field.
*
* To create composite field types, you should subclass {@link CompositeField}.
*
* @return bool
*/
public function isComposite() {
return false;
@ -807,99 +955,138 @@ class FormField extends RequestHandler {
/**
* Returns true if this field has its own data.
* Some fields, such as titles and composite fields, don't actually have any data. It doesn't
* make sense for data-focused methods to look at them. By overloading hasData() to return false,
* you can prevent any data-focused methods from looking at it.
*
* Some fields, such as titles and composite fields, don't actually have any data. It doesn't
* make sense for data-focused methods to look at them. By overloading hasData() to return
* false, you can prevent any data-focused methods from looking at it.
*
* @see FieldList::collateDataFields()
*
* @return bool
*/
public function hasData() {
return true;
}
/**
* @return boolean
* @return bool
*/
public function isReadonly() {
return $this->readonly;
}
/**
* Sets readonly-flag on form-field. Please use performReadonlyTransformation()
* to actually transform this instance.
* @param $bool boolean Setting "false" has no effect on the field-state.
* Sets a read-only flag on this FormField.
*
* Use performReadonlyTransformation() to transform this instance.
*
* Setting this to false has no effect on the field.
*
* @param bool $readonly
*
* @return $this
*/
public function setReadonly($bool) {
$this->readonly = $bool;
public function setReadonly($readonly) {
$this->readonly = $readonly;
return $this;
}
/**
* @return boolean
* @return bool
*/
public function isDisabled() {
return $this->disabled;
}
/**
* Sets disabed-flag on form-field. Please use performDisabledTransformation()
* to actually transform this instance.
* @param $bool boolean Setting "false" has no effect on the field-state.
* Sets a disabled flag on this FormField.
*
* Use performDisabledTransformation() to transform this instance.
*
* Setting this to false has no effect on the field.
*
* @param bool $disabled
*
* @return $this
*/
public function setDisabled($bool) {
$this->disabled = $bool;
public function setDisabled($disabled) {
$this->disabled = $disabled;
return $this;
}
/**
* Returns a readonly version of this field
* Returns a read-only version of this field.
*
* @return FormField
*/
public function performReadonlyTransformation() {
$readonlyClassName = $this->class . '_Disabled';
$readonlyClassName = $this->class . '_Readonly';
if(ClassInfo::exists($readonlyClassName)) {
$clone = $this->castedCopy($readonlyClassName);
} else {
$clone = $this->castedCopy('ReadonlyField');
$clone->setReadonly(true);
}
}
$clone->setReadonly(true);
return $clone;
}
/**
* Return a disabled version of this field.
* Tries to find a class of the class name of this field suffixed with "_Disabled",
* failing that, finds a method {@link setDisabled()}.
*
* Tries to find a class of the class name of this field suffixed with "_Disabled", failing
* that, finds a method {@link setDisabled()}.
*
* @return FormField
*/
public function performDisabledTransformation() {
$disabledClassName = $this->class . '_Disabled';
if(ClassInfo::exists($disabledClassName)) {
$clone = $this->castedCopy($disabledClassName);
} else {
$clone = clone $this;
$clone->setDisabled(true);
}
return $clone;
}
$clone->setDisabled(true);
public function transform(FormTransformation $trans) {
return $trans->transform($this);
return $clone;
}
public function hasClass($class){
$patten = '/'.strtolower($class).'/i';
$subject = strtolower($this->class." ".$this->extraClass());
/**
* @param FormTransformation $transformation
*
* @return mixed
*/
public function transform(FormTransformation $transformation) {
return $transformation->transform($this);
}
/**
* @param string $class
*
* @return int
*/
public function hasClass($class) {
$patten = '/' . strtolower($class) . '/i';
$subject = strtolower($this->class . ' ' . $this->extraClass());
return preg_match($patten, $subject);
}
/**
* Returns the field type - used by templates.
* Returns the field type.
*
* The field type is the class name with the word Field dropped off the end, all lowercase.
* It's handy for assigning HTML classes. Doesn't signify the <input type> attribute,
* see {link getAttributes()}.
*
* It's handy for assigning HTML classes. Doesn't signify the <input type> attribute.
*
* @see {link getAttributes()}.
*
* @return string
*/
@ -909,18 +1096,28 @@ class FormField extends RequestHandler {
/**
* @deprecated 4.0 Use FormField::create_tag()
*
* @param string $tag
* @param array $attributes
* @param null|string $content
*
* @return string
*/
public function createTag($tag, $attributes, $content = null) {
Deprecation::notice('4.0', 'Use FormField::create_tag()');
return self::create_tag($tag, $attributes, $content);
}
/**
* Validation method each {@link FormField} subclass should implement,
* determining whether the field is valid or not based on the value.
* Abstract method each {@link FormField} subclass must implement, determines whether the field
* is valid or not based on the value.
*
* @todo Make this abstract.
*
* @param Validator $validator
* @return boolean
*
* @return bool
*/
public function validate($validator) {
return true;
@ -928,13 +1125,16 @@ class FormField extends RequestHandler {
/**
* Describe this field, provide help text for it.
* By default, renders as a <span class="description">
* underneath the form field.
*
* @return string Description
* By default, renders as a <span class="description"> underneath the form field.
*
* @param string $description
*
* @return $this
*/
public function setDescription($description) {
$this->description = $description;
return $this;
}
@ -945,37 +1145,51 @@ class FormField extends RequestHandler {
return $this->description;
}
/**
* @return string
*/
public function debug() {
return "$this->class ($this->name: $this->title : <font style='color:red;'>$this->message</font>)"
. " = $this->value";
return sprintf(
'%s (%s: %s : <span style="color:red;">%s</span>) = %s',
$this->class,
$this->name,
$this->title,
$this->message,
$this->value
);
}
/**
* This function is used by the template processor. If you refer to a field as a $ variable, it
* This function is used by the template processor. If you refer to a field as a $ variable, it
* will return the $Field value.
*
* @return string
*/
public function forTemplate() {
return $this->Field();
}
/**
* @uses Validator->fieldIsRequired()
* @return boolean
* @return bool
*/
public function Required() {
if($this->form && ($validator = $this->form->Validator)) {
return $validator->fieldIsRequired($this->name);
}
return false;
}
/**
* Set the FieldList that contains this field.
*
* @param FieldList $list
* @param FieldList $containerFieldList
*
* @return FieldList
*/
public function setContainerFieldList($list) {
$this->containerFieldList = $list;
public function setContainerFieldList($containerFieldList) {
$this->containerFieldList = $containerFieldList;
return $this;
}
@ -988,31 +1202,46 @@ class FormField extends RequestHandler {
return $this->containerFieldList;
}
/**
* @return null|FieldList
*/
public function rootFieldList() {
if(is_object($this->containerFieldList)) return $this->containerFieldList->rootFieldList();
else user_error("rootFieldList() called on $this->class object without a containerFieldList", E_USER_ERROR);
if(is_object($this->containerFieldList)) {
return $this->containerFieldList->rootFieldList();
}
user_error(
"rootFieldList() called on $this->class object without a containerFieldList",
E_USER_ERROR
);
return null;
}
/**
* Returns another instance of this field, but "cast" to a different class.
* The logic tries to retain all of the instance properties,
* and may be overloaded by subclasses to set additional ones.
* Returns another instance of this field, but "cast" to a different class. The logic tries to
* retain all of the instance properties, and may be overloaded by subclasses to set additional
* ones.
*
* Assumes the standard FormField parameter signature with
* its name as the only mandatory argument. Mainly geared towards
* creating *_Readonly or *_Disabled subclasses of the same type,
* or casting to a {@link ReadonlyField}.
* Assumes the standard FormField parameter signature with its name as the only mandatory
* argument. Mainly geared towards creating *_Readonly or *_Disabled subclasses of the same
* type, or casting to a {@link ReadonlyField}.
*
* Does not copy custom field templates, since they probably won't apply to
* the new instance.
* Does not copy custom field templates, since they probably won't apply to the new instance.
*
* @param mixed $classOrCopy Class name for copy, or existing copy instance to update
*
* @param String $classOrCopy Class name for copy, or existing copy instance to update
* @return FormField
*/
public function castedCopy($classOrCopy) {
$field = (is_object($classOrCopy)) ? $classOrCopy : new $classOrCopy($this->name);
$field = $classOrCopy;
if(!is_object($field)) {
$field = new $classOrCopy($this->name);
}
$field
->setValue($this->value) // get value directly from property, avoid any conversions
->setValue($this->value)
->setForm($this->form)
->setTitle($this->Title())
->setLeftTitle($this->LeftTitle())
@ -1020,12 +1249,12 @@ class FormField extends RequestHandler {
->addExtraClass($this->extraClass())
->setDescription($this->getDescription());
// Only include built-in attributes, ignore anything
// set through getAttributes(), since those might change important characteristics
// of the field, e.g. its "type" attribute.
foreach($this->attributes as $k => $v) {
$field->setAttribute($k, $v);
}
// Only include built-in attributes, ignore anything set through getAttributes().
// Those might change important characteristics of the field, e.g. its "type" attribute.
foreach($this->attributes as $attributeKey => $attributeValue) {
$field->setAttribute($attributeKey, $attributeValue);
}
$field->dontEscape = $this->dontEscape;
return $field;

View File

@ -9,13 +9,16 @@
* of your values.
* For any statics containing natural language, never use the static directly -
* always wrap it in a getter.
*
*
* Classes must be able to be constructed without mandatory arguments, otherwise
* this interface will have no effect.
*
* @package framework
* @subpackage i18n
* @uses i18nTextCollector->collectFromEntityProviders()
*/
interface i18nEntityProvider {
/**
* Example usage:
* <code>
@ -25,13 +28,13 @@ interface i18nEntityProvider {
* foreach($this->stat('my_static_array) as $key => $value) {
* $entities["MyTestClass.my_static_array_{$key}"] = array(
* $value,
*
*
* 'My context description'
* );
* }
* return $entities;
* }
*
*
* public static function my_static_array() {
* $t_my_static_array = array();
* foreach(self::$my_static_array as $k => $v) {
@ -41,9 +44,9 @@ interface i18nEntityProvider {
* }
* }
* </code>
*
*
* 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>
@ -52,7 +55,7 @@ interface i18nEntityProvider {
* $entities = array();
* $entities["MyOtherModuleClass.MYENTITY"] = array(
* $value,
*
*
* 'My context description',
* 'myothermodule'
* );
@ -60,7 +63,7 @@ interface i18nEntityProvider {
* return $entities;
* }
* </code>
*
*
* @return array All entites in an associative array, with
* entity name as the key, and a numerical array of pseudo-arguments
* for _t() as a value.

View File

@ -27,15 +27,28 @@
*/
class i18nTextCollector extends Object {
/**
* Default (master) locale
*
* @var string
*/
protected $defaultLocale;
/**
* @var string $basePath The directory base on which the collector should act.
* The directory base on which the collector should act.
* Usually the webroot set through {@link Director::baseFolder()}.
*
* @todo Fully support changing of basePath through {@link SSViewer} and {@link ManifestBuilder}
*
* @var string
*/
public $basePath;
/**
* Save path
*
* @var string
*/
public $baseSavePath;
/**
@ -43,99 +56,267 @@ class i18nTextCollector extends Object {
*/
protected $writer;
/**
* List of file extensions to parse
*
* @var array
*/
protected $fileExtensions = array('php', 'ss');
/**
* @param $locale
*/
public function __construct($locale = null) {
$this->defaultLocale = ($locale) ? $locale : i18n::get_lang_from_locale(i18n::default_locale());
$this->defaultLocale = $locale
? $locale
: i18n::get_lang_from_locale(i18n::default_locale());
$this->basePath = Director::baseFolder();
$this->baseSavePath = Director::baseFolder();
parent::__construct();
}
/**
* Assign a writer
*
* @param i18nTextCollector_Writer $writer
*/
public function setWriter($writer) {
$this->writer = $writer;
}
/**
* Gets the currently assigned writer, or the default if none is specified.
*
* @return i18nTextCollector_Writer
*/
public function getWriter() {
if(!$this->writer) $this->writer = new i18nTextCollector_Writer_RailsYaml();
if(!$this->writer) {
$this->setWriter(Injector::inst()->get('i18nTextCollector_Writer'));
}
return $this->writer;
}
/**
* This is the main method to build the master string tables with the original strings.
* It will search for existent modules that use the i18n feature, parse the _t() calls
* and write the resultant files in the lang folder of each module.
* This is the main method to build the master string tables with the
* original strings. It will search for existent modules that use the
* i18n feature, parse the _t() calls and write the resultant files
* in the lang folder of each module.
*
* @uses DataObject->collectI18nStatics()
*
* @param array $restrictToModules
* @param array $mergeWithExisting Merge new master strings with existing ones
* already defined in language files, rather than replacing them. This can be useful
* for long-term maintenance of translations across releases, because it allows
* "translation backports" to older releases without removing strings these older releases
* still rely on.
* @param bool $mergeWithExisting Merge new master strings with existing
* ones already defined in language files, rather than replacing them.
* This can be useful for long-term maintenance of translations across
* releases, because it allows "translation backports" to older releases
* without removing strings these older releases still rely on.
*/
public function run($restrictToModules = null, $mergeWithExisting = false) {
$entitiesByModule = $this->collect($restrictToModules, $mergeWithExisting);
if(empty($entitiesByModule)) {
return;
}
// Write each module language file
if($entitiesByModule) foreach($entitiesByModule as $module => $entities) {
$this->getWriter()->write($entities, $this->defaultLocale, $this->baseSavePath . '/' . $module);
foreach($entitiesByModule as $module => $entities) {
// Skip empty translations
if(empty($entities)) {
continue;
}
// Clean sorting prior to writing
ksort($entities);
$path = $this->baseSavePath . '/' . $module;
$this->getWriter()->write($entities, $this->defaultLocale, $path);
}
}
public function collect($restrictToModules = null, $mergeWithExisting = false) {
$modules = scandir($this->basePath);
$themeFolders = array();
/**
* Gets the list of modules in this installer
*
* @param string $directory Path to look in
* @return array List of modules as paths relative to base
*/
protected function getModules($directory) {
// Include self as head module
$modules = array();
// A master string tables array (one mst per module)
$entitiesByModule = array();
// Get all standard modules
foreach(glob($directory."/*", GLOB_ONLYDIR) as $path) {
// Check for _config
if(!is_file("$path/_config.php") && !is_dir("$path/_config")) {
continue;
}
$modules[] = basename($path);
}
foreach($modules as $index => $module){
if($module != 'themes') continue;
else {
$themes = scandir($this->basePath."/themes");
if(count($themes)){
foreach($themes as $theme) {
if(is_dir($this->basePath."/themes/".$theme)
&& substr($theme,0,1) != '.'
&& is_dir($this->basePath."/themes/".$theme."/templates")){
$themeFolders[] = 'themes/'.$theme;
}
}
}
$themesInd = $index;
// Get all themes
foreach(glob($directory."/themes/*", GLOB_ONLYDIR) as $path) {
// Check for templates
if(is_dir("$path/templates")) {
$modules[] = 'themes/'.basename($path);
}
}
if(isset($themesInd)) {
unset($modules[$themesInd]);
return $modules;
}
/**
* Extract all strings from modules and return these grouped by module name
*
* @param array $restrictToModules
* @param bool $mergeWithExisting
* @return array
*/
public function collect($restrictToModules = array(), $mergeWithExisting = false) {
$entitiesByModule = $this->getEntitiesByModule();
// Resolve conflicts between duplicate keys across modules
$entitiesByModule = $this->resolveDuplicateConflicts($entitiesByModule);
// Optionally merge with existing master strings
if($mergeWithExisting) {
$entitiesByModule = $this->mergeWithExisting($entitiesByModule);
}
$modules = array_merge($modules, $themeFolders);
// Restrict modules we update to just the specified ones (if any passed)
if(!empty($restrictToModules)) {
foreach (array_diff(array_keys($entitiesByModule), $restrictToModules) as $module) {
unset($entitiesByModule[$module]);
}
}
return $entitiesByModule;
}
foreach($modules as $module) {
// Only search for calls in folder with a _config.php file or _config folder
// (which means they are modules, including themes folder)
$isValidModuleFolder = (
is_dir("$this->basePath/$module")
&& substr($module,0,1) != '.'
&& (
is_file("$this->basePath/$module/_config.php")
|| is_dir("$this->basePath/$module/_config")
)
) || (
substr($module,0,7) == 'themes/'
&& is_dir("$this->basePath/$module")
/**
* Resolve conflicts between duplicate keys across modules
*
* @param array $entitiesByModule List of all modules with keys
* @return array Filtered listo of modules with duplicate keys unassigned
*/
protected function resolveDuplicateConflicts($entitiesByModule) {
// Find all keys that exist across multiple modules
$conflicts = $this->getConflicts($entitiesByModule);
foreach($conflicts as $conflict) {
// Determine if we can narrow down the ownership
$bestModule = $this->getBestModuleForKey($entitiesByModule, $conflict);
if(!$bestModule) {
continue;
}
// Remove foreign duplicates
foreach($entitiesByModule as $module => $entities) {
if($module !== $bestModule) {
unset($entitiesByModule[$module][$conflict]);
}
}
}
return $entitiesByModule;
}
/**
* Find all keys in the entity list that are duplicated across modules
*
* @param array $entitiesByModule
* @return array List of keys
*/
protected function getConflicts($entitiesByModule) {
$modules = array_keys($entitiesByModule);
$allConflicts = array();
// bubble-compare each group of modules
for($i = 0; $i < count($modules) - 1; $i++) {
$left = array_keys($entitiesByModule[$modules[$i]]);
for($j = $i+1; $j < count($modules); $j++) {
$right = array_keys($entitiesByModule[$modules[$j]]);
$conflicts = array_intersect($left, $right);
$allConflicts = array_merge($allConflicts, $conflicts);
}
}
return array_unique($allConflicts);
}
/**
* Determine the best module to be given ownership over this key
*
* @param array $entitiesByModule
* @param string $key
* @return string Best module, if found
*/
protected function getBestModuleForKey($entitiesByModule, $key) {
// Check classes
$class = current(explode('.', $key));
$owner = i18n::get_owner_module($class);
if($owner) {
return $owner;
}
// @todo - How to determine ownership of templates? Templates can
// exist in multiple locations with the same name.
// Display notice if not found
Debug::message(
"Duplicate key {$key} detected in multiple modules with no obvious owner",
false
);
// Fall back to framework then cms modules
foreach(array('framework', 'cms') as $module) {
if(isset($entitiesByModule[$module][$key])) {
return $module;
}
}
// Do nothing
return null;
}
/**
* Merge all entities with existing strings
*
* @param array $entitiesByModule
* @return array
*/
protected function mergeWithExisting($entitiesByModule) {
// TODO Support all defined source formats through i18n::get_translators().
// Currently not possible because adapter instances can't be fully reset through the Zend API,
// meaning master strings accumulate across modules
foreach($entitiesByModule as $module => $entities) {
$adapter = Injector::inst()->create('i18nRailsYamlAdapter');
$fileName = $adapter->getFilenameForLocale($this->defaultLocale);
$masterFile = "{$this->basePath}/{$module}/lang/{$fileName}";
if(!file_exists($masterFile)) {
continue;
}
$adapter->addTranslation(array(
'content' => $masterFile,
'locale' => $this->defaultLocale
));
$entitiesByModule[$module] = array_merge(
array_map(
// Transform each master string from scalar value to array of strings
function($v) {return array($v);},
$adapter->getMessages($this->defaultLocale)
),
$entities
);
}
return $entitiesByModule;
}
if(!$isValidModuleFolder) continue;
/**
* Collect all entities grouped by module
*
* @return array
*/
protected function getEntitiesByModule() {
// A master string tables array (one mst per module)
$entitiesByModule = array();
$modules = $this->getModules($this->basePath);
foreach($modules as $module) {
// we store the master string tables
$processedEntities = $this->processModule($module);
if(isset($entitiesByModule[$module])) {
$entitiesByModule[$module] = array_merge_recursive($entitiesByModule[$module], $processedEntities);
} else {
@ -143,54 +324,23 @@ class i18nTextCollector extends Object {
}
// extract all entities for "foreign" modules (fourth argument)
// @see CMSMenu::provideI18nEntities for an example usage
foreach($entitiesByModule[$module] as $fullName => $spec) {
if(isset($spec[2]) && $spec[2] && $spec[2] != $module) {
if(!empty($spec[2]) && $spec[2] !== $module) {
$othermodule = $spec[2];
if(!isset($entitiesByModule[$othermodule])) $entitiesByModule[$othermodule] = array();
if(!isset($entitiesByModule[$othermodule])) {
$entitiesByModule[$othermodule] = array();
}
unset($spec[2]);
$entitiesByModule[$othermodule][$fullName] = $spec;
unset($entitiesByModule[$module][$fullName]);
}
}
// Optionally merge with existing master strings
// TODO Support all defined source formats through i18n::get_translators().
// Currently not possible because adapter instances can't be fully reset through the Zend API,
// meaning master strings accumulate across modules
if($mergeWithExisting) {
$adapter = Injector::inst()->create(
'i18nRailsYamlAdapter',
array('locale' => 'auto')
);
$masterFile = "{$this->basePath}/{$module}/lang/"
. $adapter->getFilenameForLocale($this->defaultLocale);
if(!file_exists($masterFile)) continue;
$adapter->addTranslation(array(
'content' => $masterFile,
'locale' => $this->defaultLocale
));
$entitiesByModule[$module] = array_merge(
array_map(
// Transform each master string from scalar value to array of strings
function($v) {return array($v);},
$adapter->getMessages($this->defaultLocale)
),
$entitiesByModule[$module]
);
}
}
// Restrict modules we update to just the specified ones (if any passed)
if($restrictToModules && count($restrictToModules)) {
foreach (array_diff(array_keys($entitiesByModule), $restrictToModules) as $module) {
unset($entitiesByModule[$module]);
}
}
return $entitiesByModule;
}
public function write($module, $entities) {
$this->getWriter()->write($entities, $this->defaultLocale, $this->baseSavePath . '/' . $module);
return $this;
@ -200,38 +350,31 @@ class i18nTextCollector extends Object {
* Builds a master string table from php and .ss template files for the module passed as the $module param
* @see collectFromCode() and collectFromTemplate()
*
* @param string $module A module's name or just 'themes'
* @return array $entities An array of entities found in the files that comprise the module
* @todo Why the type juggling for $this->collectFromBlah()? They always return arrays.
* @param string $module A module's name or just 'themes/<themename>'
* @return array An array of entities found in the files that comprise the module
*/
protected function processModule($module) {
$entities = array();
// Search for calls in code files if these exists
$fileList = array();
if(is_dir("$this->basePath/$module/code")) {
$fileList = $this->getFilesRecursive("$this->basePath/$module/code");
} else if($module == FRAMEWORK_DIR || substr($module, 0, 7) == 'themes/') {
// framework doesn't have the usual module structure, so we'll scan all subfolders
$fileList = $this->getFilesRecursive("$this->basePath/$module", null, null, '/\/(tests|dev)$/');
}
$fileList = $this->getFileListForModule($module);
foreach($fileList as $filePath) {
// exclude ss-templates, they're scanned separately
if(substr($filePath,-3) == 'php') {
$content = file_get_contents($filePath);
$entities = array_merge($entities,(array)$this->collectFromCode($content, $module));
$entities = array_merge($entities, (array)$this->collectFromEntityProviders($filePath, $module));
}
}
// Search for calls in template files if these exists
if(is_dir("$this->basePath/$module/")) {
$fileList = $this->getFilesRecursive("$this->basePath/$module/", null, 'ss');
foreach($fileList as $index => $filePath) {
$content = file_get_contents($filePath);
$extension = pathinfo($filePath, PATHINFO_EXTENSION);
$content = file_get_contents($filePath);
// Filter based on extension
if($extension === 'php') {
$entities = array_merge(
$entities,
$this->collectFromCode($content, $module),
$this->collectFromEntityProviders($filePath, $module)
);
} elseif($extension === 'ss') {
// templates use their filename as a namespace
$namespace = basename($filePath);
$entities = array_merge($entities, (array)$this->collectFromTemplate($content, $module, $namespace));
$entities = array_merge(
$entities,
$this->collectFromTemplate($content, $module, $namespace)
);
}
}
@ -241,11 +384,44 @@ class i18nTextCollector extends Object {
return $entities;
}
/**
* Retrieves the list of files for this module
*
* @param type $module
* @return array List of files to parse
*/
protected function getFileListForModule($module) {
$modulePath = "{$this->basePath}/{$module}";
// Search all .ss files in themes
if(stripos($module, 'themes/') === 0) {
return $this->getFilesRecursive($modulePath, null, 'ss');
}
// If Framework or non-standard module structure, so we'll scan all subfolders
if($module === FRAMEWORK_DIR || !is_dir("{$modulePath}/code")) {
return $this->getFilesRecursive($modulePath);
}
// Get code files
$files = $this->getFilesRecursive("{$modulePath}/code", null, 'php');
// Search for templates in this module
if(is_dir("{$modulePath}/templates")) {
$templateFiles = $this->getFilesRecursive("{$modulePath}/templates", null, 'ss');
} else {
$templateFiles = $this->getFilesRecursive($modulePath, null, 'ss');
}
return array_merge($files, $templateFiles);
}
/**
* Extracts translatables from .php files.
*
* @param string $content The text content of a parsed template-file
* @param string $module Module's name or 'themes'
* @param string $module Module's name or 'themes'. Could also be a namespace
* Generated by templates includes. E.g. 'UploadField.ss'
* @return array $entities An array of entities representing the extracted translation function calls in code
*/
public function collectFromCode($content, $module) {
@ -328,33 +504,10 @@ class i18nTextCollector extends Object {
* @param string $module Module's name or 'themes'
* @param string $fileName The name of a template file when method is used in self-referencing mode
* @return array $entities An array of entities representing the extracted template function calls
*
* @todo Why the type juggling for $this->collectFromTemplate()? It always returns an array.
*/
public function collectFromTemplate($content, $fileName, $module, &$parsedFiles = array()) {
$entities = array();
// Search for included templates
preg_match_all('/<' . '% include +([A-Za-z0-9_]+) +%' . '>/', $content, $regs, PREG_SET_ORDER);
foreach($regs as $reg) {
$includeName = $reg[1];
$includeFileName = "{$includeName}.ss";
$filePath = SSViewer::getTemplateFileByType($includeName, 'Includes');
if(!$filePath) $filePath = SSViewer::getTemplateFileByType($includeName, 'main');
if($filePath && !in_array($filePath, $parsedFiles)) {
$parsedFiles[] = $filePath;
$includeContent = file_get_contents($filePath);
$entities = array_merge(
$entities,
(array)$this->collectFromTemplate($includeContent, $module, $includeFileName, $parsedFiles)
);
}
// @todo Will get massively confused if you include the includer -> infinite loop
}
// use parser to extract <%t style translatable entities
$translatables = i18nTextCollector_Parser::GetTranslatables($content);
$entities = array_merge($entities,(array)$translatables);
$entities = i18nTextCollector_Parser::GetTranslatables($content);
// use the old method of getting _t() style translatable entities
// Collect in actual template
@ -374,31 +527,34 @@ class i18nTextCollector extends Object {
}
/**
* Allows classes which implement i18nEntityProvider to provide
* additional translation strings.
*
* Not all classes can be instanciated without mandatory arguments,
* so entity collection doesn't work for all SilverStripe classes currently
*
* @uses i18nEntityProvider
* @param string $filePath
* @param string $module
* @return array
*/
public function collectFromEntityProviders($filePath, $module = null) {
$entities = array();
// HACK Ugly workaround to avoid "Cannot redeclare class PHPUnit_Framework_TestResult" error
// when running text collector with PHPUnit 3.4. There really shouldn't be any dependencies
// here, but the class reflection enforces autloading of seemingly unrelated classes.
// The main problem here is the CMSMenu class, which iterates through test classes,
// which in turn trigger autoloading of PHPUnit.
$phpunitwrapper = PhpUnitWrapper::inst();
$phpunitwrapper->init();
$classes = ClassInfo::classes_for_file($filePath);
if($classes) foreach($classes as $class) {
// Not all classes can be instanciated without mandatory arguments,
// so entity collection doesn't work for all SilverStripe classes currently
// Requires PHP 5.1+
if(class_exists($class) && in_array('i18nEntityProvider', class_implements($class))) {
$reflectionClass = new ReflectionClass($class);
if($reflectionClass->isAbstract()) continue;
$obj = singleton($class);
$entities = array_merge($entities,(array)$obj->provideI18nEntities());
foreach($classes as $class) {
// Skip non-implementing classes
if(!class_exists($class) || !in_array('i18nEntityProvider', class_implements($class))) {
continue;
}
// Skip abstract classes
$reflectionClass = new ReflectionClass($class);
if($reflectionClass->isAbstract()) {
continue;
}
$obj = singleton($class);
$entities = array_merge($entities, (array)$obj->provideI18nEntities());
}
ksort($entities);
@ -442,30 +598,35 @@ class i18nTextCollector extends Object {
*
* @param string $folder base directory to scan (will scan recursively)
* @param array $fileList Array to which potential files will be appended
* @param string $type Optional, "php" or "ss"
* @param string $folderExclude Regular expression matching folder names to exclude
* @param string $type Optional, "php" or "ss" only
* @param string $folderExclude Regular expression matching folder names to exclude
* @return array $fileList An array of files
*/
protected function getFilesRecursive($folder, $fileList = null, $type = null, $folderExclude = null) {
if(!$folderExclude) $folderExclude = '/\/(tests)$/';
if(!$fileList) $fileList = array();
$items = scandir($folder);
$isValidFolder = (
!in_array('_manifest_exclude', $items)
&& !preg_match($folderExclude, $folder)
);
protected function getFilesRecursive($folder, $fileList = array(), $type = null, $folderExclude = '/\/(tests)$/') {
if(!$fileList) {
$fileList = array();
}
// Skip ignored folders
if(is_file("{$folder}/_manifest_exclude") || preg_match($folderExclude, $folder)) {
return $fileList;
}
if($items && $isValidFolder) foreach($items as $item) {
if(substr($item,0,1) == '.') continue;
if(substr($item,-4) == '.php' && (!$type || $type == 'php')) {
$fileList[substr($item,0,-4)] = "$folder/$item";
} else if(substr($item,-3) == '.ss' && (!$type || $type == 'ss')) {
$fileList[$item] = "$folder/$item";
} else if(is_dir("$folder/$item")) {
foreach(glob($folder.'/*') as $path) {
// Recurse if directory
if(is_dir($path)) {
$fileList = array_merge(
$fileList,
$this->getFilesRecursive("$folder/$item", $fileList, $type, $folderExclude)
$this->getFilesRecursive($path, $fileList, $type, $folderExclude)
);
continue;
}
// Check if this extension is included
$extension = pathinfo($path, PATHINFO_EXTENSION);
if(in_array($extension, $this->fileExtensions)
&& (!$type || $type === $extension)
) {
$fileList[$path] = $path;
}
}
return $fileList;
@ -691,7 +852,9 @@ class i18nTextCollector_Parser extends SSTemplateParser {
// Run the parser and throw away the result
$parser = new i18nTextCollector_Parser($template);
if(substr($template, 0,3) == pack("CCC", 0xef, 0xbb, 0xbf)) $parser->pos = 3;
if(substr($template, 0,3) == pack("CCC", 0xef, 0xbb, 0xbf)) {
$parser->pos = 3;
}
$parser->match_TopTemplate();
return self::$entities;

View File

@ -135,6 +135,10 @@ class DB {
* Set it to null to revert to the main database.
*/
public static function set_alternative_database_name($name = null) {
// Skip if CLI
if(Director::is_cli()) {
return;
}
if($name) {
if(!self::valid_alternative_database_name($name)) {
throw new InvalidArgumentException(sprintf(

View File

@ -419,9 +419,9 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
$whereArguments = func_get_arg(0);
} elseif($numberFuncArgs == 2) {
$whereArguments[func_get_arg(0)] = func_get_arg(1);
} else {
} else {
throw new InvalidArgumentException('Incorrect number of arguments passed to exclude()');
}
}
return $this->alterDataQuery(function($query, $list) use ($whereArguments) {
$subquery = $query->disjunctiveGroup();
@ -436,16 +436,16 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
$t = singleton($list->dataClass())->dbObject($field);
if($filterType) {
$className = "{$filterType}Filter";
} else {
} else {
$className = 'ExactMatchFilter';
}
if(!class_exists($className)){
$className = 'ExactMatchFilter';
array_unshift($modifiers, $filterType);
}
}
$t = new $className($field, $value, $modifiers);
$t->apply($subquery);
}
}
});
}

View File

@ -1771,7 +1771,10 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
$componentClass, $table, $componentField, $parentField,
$this->manyManyExtraFieldsForComponent($componentName)
);
if($this->model) $result->setDataModel($this->model);
$this->extend('updateManyManyComponents', $result);
// If this is called on a singleton, then we return an 'orphaned relation' that can have the
// foreignID set elsewhere.

View File

@ -333,7 +333,7 @@ class DataQuery {
if(!in_array($qualCol, $query->getSelect())) {
unset($newOrderby[$k]);
$newOrderby["\"_SortColumn$i\""] = $dir;
$query->selectField($qualCol, "_SortColumn$i");

View File

@ -58,12 +58,13 @@ class MySQLStatement extends SS_Query {
$variables[] = &$this->boundValues[$field->name];
}
call_user_func_array(array($this->statement, 'bind_result'), $variables);
$this->bound = true;
$this->metadata->free();
// Buffer all results
$this->statement->store_result();
call_user_func_array(array($this->statement, 'bind_result'), $variables);
}
/**

View File

@ -4,27 +4,27 @@
* It is a simple regex based parser that allows you to replace simple bbcode-like tags
* within a HTMLText or HTMLVarchar field when rendered into a template. The API is inspired by and very similar to the
* [Wordpress implementation](http://codex.wordpress.org/Shortcode_API) of shortcodes.
*
*
* @see http://doc.silverstripe.org/framework/en/reference/shortcodes
* @package framework
* @subpackage misc
*/
class ShortcodeParser extends Object {
public function img_shortcode($attrs) {
return "<img src='".$attrs['src']."'>";
}
protected static $instances = array();
protected static $active_instance = 'default';
// --------------------------------------------------------------------------------------------------------------
protected $shortcodes = array();
// --------------------------------------------------------------------------------------------------------------
/**
* Get the {@link ShortcodeParser} instance that is attached to a particular identifier.
*
@ -35,10 +35,10 @@ class ShortcodeParser extends Object {
if(!array_key_exists($identifier, self::$instances)) {
self::$instances[$identifier] = static::create();
}
return self::$instances[$identifier];
}
/**
* Get the currently active/default {@link ShortcodeParser} instance.
*
@ -47,7 +47,7 @@ class ShortcodeParser extends Object {
public static function get_active() {
return static::get(self::$active_instance);
}
/**
* Set the identifier to use for the current active/default {@link ShortcodeParser} instance.
*
@ -56,9 +56,9 @@ class ShortcodeParser extends Object {
public static function set_active($identifier) {
self::$active_instance = (string) $identifier;
}
// --------------------------------------------------------------------------------------------------------------
/**
* Register a shortcode, and attach it to a PHP callback.
*
@ -76,7 +76,7 @@ class ShortcodeParser extends Object {
public function register($shortcode, $callback) {
if(is_callable($callback)) $this->shortcodes[$shortcode] = $callback;
}
/**
* Check if a shortcode has been registered.
*
@ -86,7 +86,7 @@ class ShortcodeParser extends Object {
public function registered($shortcode) {
return array_key_exists($shortcode, $this->shortcodes);
}
/**
* Remove a specific registered shortcode.
*
@ -95,28 +95,64 @@ class ShortcodeParser extends Object {
public function unregister($shortcode) {
if($this->registered($shortcode)) unset($this->shortcodes[$shortcode]);
}
/**
* Remove all registered shortcodes.
*/
public function clear() {
$this->shortcodes = array();
}
/**
* Call a shortcode and return its replacement text
* Returns false if the shortcode isn't registered
*/
public function callShortcode($tag, $attributes, $content, $extra = array()) {
if (!isset($this->shortcodes[$tag])) return false;
if (!$tag || !isset($this->shortcodes[$tag])) return false;
return call_user_func($this->shortcodes[$tag], $attributes, $content, $this, $tag, $extra);
}
/**
* Return the text to insert in place of a shoprtcode.
* Behaviour in the case of missing shortcodes depends on the setting of ShortcodeParser::$error_behavior.
* @param $tag A map containing the the following keys:
* - 'open': The name of the tag
* - 'attrs': Attributes of the tag
* - 'content': Content of the tag
* @param $extra Extra-meta data
* @param $isHTMLAllowed A boolean indicating whether it's okay to insert HTML tags into the result
*/
function getShortcodeReplacementText($tag, $extra = array(), $isHTMLAllowed = true) {
$content = $this->callShortcode($tag['open'], $tag['attrs'], $tag['content'], $extra);
// Missing tag
if ($content === false) {
if(ShortcodeParser::$error_behavior == ShortcodeParser::ERROR) {
user_error('Unknown shortcode tag '.$tag['open'], E_USER_ERRROR);
}
else if (self::$error_behavior == self::WARN && $isHTMLAllowed) {
$content = '<strong class="warning">'.$tag['text'].'</strong>';
}
else if(ShortcodeParser::$error_behavior == ShortcodeParser::STRIP) {
return '';
}
else {
return $tag['text'];
}
}
return $content;
}
// --------------------------------------------------------------------------------------------------------------
protected function removeNode($node) {
$node->parentNode->removeChild($node);
}
protected function insertAfter($new, $after) {
$parent = $after->parentNode; $next = $after->nextSibling;
if ($next) {
$parent->insertBefore($new, $next);
}
@ -124,7 +160,7 @@ class ShortcodeParser extends Object {
$parent->appendChild($new);
}
}
protected function insertListAfter($new, $after) {
$doc = $after->ownerDocument; $parent = $after->parentNode; $next = $after->nextSibling;
@ -132,8 +168,8 @@ class ShortcodeParser extends Object {
$imported = $doc->importNode($new->item($i), true);
if ($next) {
$parent->insertBefore($imported, $next);
}
$parent->insertBefore($imported, $next);
}
else {
$parent->appendChild($imported);
}
@ -147,9 +183,9 @@ class ShortcodeParser extends Object {
'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'ol', 'output', 'p',
'pre', 'section', 'table', 'ul'
);
protected static $attrrx = '
([^\s\/\'"=,]+) # Name
([^\s\/\'"=,]+) # Name
\s* = \s*
(?:
(?:\'([^\']+)\') | # Value surrounded by \'
@ -157,7 +193,7 @@ class ShortcodeParser extends Object {
([^\s,\]]+) # Bare value
)
';
protected static function attrrx() {
return '/'.self::$attrrx.'/xS';
}
@ -165,21 +201,21 @@ class ShortcodeParser extends Object {
protected static $tagrx = '
# HTML Tag
<(?<element>(?:"[^"]*"[\'"]*|\'[^\']*\'[\'"]*|[^\'">])+)>
| # Opening tag
(?<oesc>\[?)
\[
(?<open>\w+)
(?<oesc>\[?)
\[
(?<open>\w+)
[\s,]*
(?<attrs> (?: %s [\s,]*)* )
\/?\]
(?<attrs> (?: %s [\s,]*)* )
\/?\]
(?<cesc1>\]?)
| # Closing tag
\[\/
(?<close>\w+)
\]
(?<cesc2>\]?)
\[\/
(?<close>\w+)
\]
(?<cesc2>\]?)
';
protected static function tagrx() {
@ -199,14 +235,15 @@ class ShortcodeParser extends Object {
* of those tags
*
* Doesn't support nested shortcode tags
*
*
* @param string $content
* @return array - The list of tags found. When using an open/close pair, only one item will be in the array,
* with "content" set to the text between the tags
*/
protected function extractTags($content) {
$tags = array();
// Step 1: perform basic regex scan of individual tags
if(preg_match_all(static::tagrx(), $content, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) {
foreach($matches as $match) {
// Ignore any elements
@ -214,7 +251,7 @@ class ShortcodeParser extends Object {
// Pull the attributes out into a key/value hash
$attrs = array();
if (!empty($match['attrs'][0])) {
preg_match_all(static::attrrx(), $match['attrs'][0], $attrmatches, PREG_SET_ORDER);
@ -223,7 +260,7 @@ class ShortcodeParser extends Object {
$attrs[$name] = $value;
}
}
// And store the indexes, tag details, etc
$tags[] = array(
'text' => $match[0][0],
@ -236,14 +273,15 @@ class ShortcodeParser extends Object {
'escaped' => !empty($match['oesc'][0]) || !empty($match['cesc1'][0]) || !empty($match['cesc2'][0])
);
}
}
}
// Step 2: cluster open/close tag pairs into single entries
$i = count($tags);
while($i--) {
if(!empty($tags[$i]['close'])) {
// If the tag just before this one isn't the related opening tag, throw an error
$err = null;
if ($i == 0) {
$err = 'Close tag "'.$tags[$i]['close'].'" is the first found tag, so has no related open tag';
}
@ -255,10 +293,10 @@ class ShortcodeParser extends Object {
$err = 'Close tag "'.$tags[$i]['close'].'" doesn\'t match preceding open tag "'.
$tags[$i-1]['open'].'"';
}
if($err) {
if(self::$error_behavior == self::ERROR) user_error($err, E_USER_ERRROR);
}
if(self::$error_behavior == self::ERROR) user_error($err, E_USER_ERRROR);
}
else {
if ($tags[$i]['escaped']) {
if (!$tags[$i-1]['escaped']) {
@ -272,12 +310,23 @@ class ShortcodeParser extends Object {
$tags[$i-1]['escaped'] = false;
}
}
// Otherwise, grab content between tags, save in opening tag & delete the closing one
$tags[$i-1]['text'] = substr($content, $tags[$i-1]['s'], $tags[$i]['e'] - $tags[$i-1]['s']);
$tags[$i-1]['content'] = substr($content, $tags[$i-1]['e'], $tags[$i]['s'] - $tags[$i-1]['e']);
$tags[$i-1]['e'] = $tags[$i]['e'];
unset($tags[$i]);
}
}
}
// Step 3: remove any tags that don't have handlers registered
// Only do this if self::$error_behavior == self::LEAVE
// This is optional but speeds things up.
if(self::$error_behavior == self::LEAVE) {
foreach($tags as $i => $tag) {
if(empty($this->shortcodes[$tag['open']])) {
unset($tags[$i]);
}
}
@ -311,7 +360,7 @@ class ShortcodeParser extends Object {
else {
$str = $generator($i, $tags[$i]) . $tail . $str;
}
$li = $tags[$i]['s'];
}
@ -337,27 +386,14 @@ class ShortcodeParser extends Object {
if($tags) {
$node->nodeValue = $this->replaceTagsWithText($node->nodeValue, $tags,
function($idx, $tag) use ($parser, $extra){
$content = $parser->callShortcode($tag['open'], $tag['attrs'], $tag['content'], $extra);
if ($content === false) {
if(ShortcodeParser::$error_behavior == ShortcodeParser::ERROR) {
user_error('Unknown shortcode tag '.$tag['open'], E_USER_ERRROR);
}
else if(ShortcodeParser::$error_behavior == ShortcodeParser::STRIP) {
return '';
}
else {
return $tag['text'];
}
function($idx, $tag) use ($parser, $extra) {
return $parser->getShortcodeReplacementText($tag, $extra, false);
}
return $content;
});
}
);
}
}
}
/**
* Replace the element-scoped tags with markers
*
@ -368,18 +404,18 @@ class ShortcodeParser extends Object {
if($tags) {
$markerClass = self::$marker_class;
$content = $this->replaceTagsWithText($content, $tags, function($idx, $tag) use ($markerClass) {
return '<img class="'.$markerClass.'" data-tagid="'.$idx.'" />';
});
}
}
return array($content, $tags);
}
}
protected function findParentsForMarkers($nodes) {
$parents = array();
foreach($nodes as $node) {
$parent = $node;
@ -392,34 +428,34 @@ class ShortcodeParser extends Object {
$node->setAttribute('data-parentid', count($parents));
$parents[] = $parent;
}
return $parents;
}
const BEFORE = 'before';
const AFTER = 'after';
const SPLIT = 'split';
const INLINE = 'inline';
/**
* Given a node with represents a shortcode marker and a location string, mutates the DOM to put the
* marker in the compliant location
*
*
* For shortcodes inserted BEFORE, that location is just before the block container that
* the marker is in
*
*
* For shortcodes inserted AFTER, that location is just after the block container that
* the marker is in
*
*
* For shortcodes inserted SPLIT, that location is where the marker is, but the DOM
* is split around it up to the block container the marker is in - for instance,
*
*
* <p>A<span>B<marker />C</span>D</p>
*
* becomes
*
*
* becomes
*
* <p>A<span>B</span></p><marker /><p><span>C</span>D</p>
*
*
* For shortcodes inserted INLINE, no modification is needed (but in that case the shortcode handler needs to
* generate only inline blocks)
*
@ -458,7 +494,7 @@ class ShortcodeParser extends Object {
if(in_array(strtolower($node->tagName), self::$block_level_elements)) {
user_error(
'Requested to insert block tag '.$node->tagName.
' inline - probably this will break HTML compliance',
' inline - probably this will break HTML compliance',
E_USER_WARNING
);
}
@ -472,35 +508,19 @@ class ShortcodeParser extends Object {
/**
* Given a node with represents a shortcode marker and some information about the shortcode, call the
* shortcode handler & replace the marker with the actual content
*
*
* @param DOMElement $node
* @param array $tag
*/
protected function replaceMarkerWithContent($node, $tag) {
$content = false;
if($tag['open']) $content = $this->callShortcode($tag['open'], $tag['attrs'], $tag['content']);
if ($content === false) {
if(self::$error_behavior == self::ERROR) {
user_error('Unknown shortcode tag '.$tag['open'], E_USER_ERRROR);
}
if (self::$error_behavior == self::WARN) {
$content = '<strong class="warning">'.$tag['text'].'</strong>';
}
else if (self::$error_behavior == self::LEAVE) {
$content = $tag['text'];
}
else {
// self::$error_behavior == self::STRIP - NOP
}
}
$content = $this->getShortcodeReplacementText($tag);
if ($content) {
$parsed = Injector::inst()->create('HTMLValue', $content);
$body = $parsed->getBody();
if ($body) $this->insertListAfter($body->childNodes, $node);
}
$this->removeNode($node);
}
@ -545,11 +565,11 @@ class ShortcodeParser extends Object {
foreach($shortcodes as $shortcode) {
$tag = $tags[$shortcode->getAttribute('data-tagid')];
$parent = $parents[$shortcode->getAttribute('data-parentid')];
$class = null;
if(!empty($tag['attrs']['location'])) $class = $tag['attrs']['location'];
if(!empty($tag['attrs']['location'])) $class = $tag['attrs']['location'];
else if(!empty($tag['attrs']['class'])) $class = $tag['attrs']['class'];
$location = self::INLINE;
if($class == 'left' || $class == 'right') $location = self::BEFORE;
if($class == 'center' || $class == 'leftALone') $location = self::SPLIT;
@ -567,8 +587,21 @@ class ShortcodeParser extends Object {
$this->replaceMarkerWithContent($shortcode, $tag);
}
return $htmlvalue->getContent();
$content = $htmlvalue->getContent();
// Clean up any marker classes left over, for example, those injected into <script> tags
$parser = $this;
$content = preg_replace_callback(
// Not a general-case parser; assumes that the HTML generated in replaceElementTagsWithMarkers()
// hasn't been heavily modified
'/<img[^>]+class="'.preg_quote(self::$marker_class).'"[^>]+data-tagid="([^"]+)"[^>]+>/i',
function ($matches) use ($tags, $parser) {
$tag = $tags[$matches[1]];
return $parser->getShortcodeReplacementText($tag);
},
$content
);
return $content;
}
}

View File

@ -18,7 +18,7 @@
// TODO .middleColumn styling should probably be theme specific (eg cms ui will look different than blackcandy)
// so we should move this style into the cms and black candy files
min-width: 510px;
max-width: 600px; // Capped width. 600px is about the average size of a preview split view
max-width: $grid-x * 87; // Capped width to line up with text fields
width:100%;
margin-left:0;
clear:both;

View File

@ -5,7 +5,7 @@
* @subpackage security
*/
class ChangePasswordForm extends Form {
/**
* Constructor
*
@ -28,7 +28,7 @@ class ChangePasswordForm extends Form {
if(!$fields) {
$fields = new FieldList();
// Security/changepassword?h=XXX redirects to Security/changepassword
// without GET parameter to avoid potential HTTP referer leakage.
// In this case, a user is not logged in, and no 'old password' should be necessary.
@ -65,7 +65,7 @@ class ChangePasswordForm extends Form {
if(empty($data['OldPassword']) || !$member->checkPassword($data['OldPassword'])->valid()) {
$this->clearMessage();
$this->sessionMessage(
_t('Member.ERRORPASSWORDNOTMATCH', "Your current password does not match, please try again"),
_t('Member.ERRORPASSWORDNOTMATCH', "Your current password does not match, please try again"),
"bad"
);
// redirect back to the form, instead of using redirectBack() which could send the user elsewhere.
@ -99,7 +99,7 @@ class ChangePasswordForm extends Form {
$isValid = $member->changePassword($data['NewPassword1']);
if($isValid->valid()) {
$member->logIn();
// TODO Add confirmation message to login redirect
Session::clear('AutoLoginHash');
@ -127,11 +127,12 @@ class ChangePasswordForm extends Form {
$this->clearMessage();
$this->sessionMessage(
_t(
'Member.INVALIDNEWPASSWORD',
'Member.INVALIDNEWPASSWORD',
"We couldn't accept that password: {password}",
array('password' => nl2br("\n".$isValid->starredList()))
),
"bad"
array('password' => nl2br("\n".Convert::raw2xml($isValid->starredList())))
),
"bad",
false
);
// redirect back to the form, instead of using redirectBack() which could send the user elsewhere.

View File

@ -59,7 +59,9 @@ class Member extends DataObject implements TemplateGlobalProvider {
private static $has_one = array();
private static $has_many = array();
private static $has_many = array(
'LoggedPasswords' => 'MemberPassword',
);
private static $many_many = array();
@ -879,6 +881,26 @@ class Member extends DataObject implements TemplateGlobalProvider {
}
}
public function onAfterDelete() {
parent::onAfterDelete();
//prevent orphaned records remaining in the DB
$this->deletePasswordLogs();
}
/**
* Delete the MemberPassword objects that are associated to this user
*
* @return self
*/
protected function deletePasswordLogs() {
foreach ($this->LoggedPasswords() as $password) {
$password->delete();
$password->destroy();
}
return $this;
}
/**
* If any admin groups are requested, deny the whole save operation.
*

View File

@ -1118,7 +1118,7 @@ class Security extends Controller implements TemplateGlobalProvider {
/**
* Defines global accesible templates variables.
* Defines global accessible templates variables.
*
* @return array
*/

View File

@ -4,9 +4,9 @@
* @subpackage tasks
*/
class i18nTextCollectorTask extends BuildTask {
protected $title = "i18n Textcollector Task";
protected $description = "
Traverses through files in order to collect the 'entity master tables'
stored in each module.
@ -17,27 +17,66 @@ class i18nTextCollectorTask extends BuildTask {
- module: One or more modules to limit collection (comma-separated)
- merge: Merge new strings with existing ones already defined in language files (default: FALSE)
";
public function init() {
parent::init();
$canAccess = (Director::isDev() || Director::is_cli() || Permission::check("ADMIN"));
if(!$canAccess) return Security::permissionFailure($this);
if(!$canAccess) {
return Security::permissionFailure($this);
}
}
/**
* This is the main method to build the master string tables with the original strings.
* It will search for existent modules that use the i18n feature, parse the _t() calls
* and write the resultant files in the lang folder of each module.
*
*
* @uses DataObject->collectI18nStatics()
*/
*
* @param SS_HTTPRequest $request
*/
public function run($request) {
increase_time_limit_to();
$c = new i18nTextCollector($request->getVar('locale'));
$writer = $request->getVar('writer');
if($writer) $c->setWriter(new $writer());
$restrictModules = ($request->getVar('module')) ? explode(',', $request->getVar('module')) : null;
return $c->run($restrictModules, (bool)$request->getVar('merge'));
$collector = i18nTextCollector::create($request->getVar('locale'));
$merge = $this->getIsMerge($request);
// Custom writer
$writerName = $request->getVar('writer');
if($writerName) {
$writer = Injector::inst()->get($writerName);
$collector->setWriter($writer);
}
// Get restrictions
$restrictModules = ($request->getVar('module'))
? explode(',', $request->getVar('module'))
: null;
$collector->run($restrictModules, $merge);
Debug::message(__CLASS__ . " completed!", false);
}
/**
* Check if we should merge
*
* @param SS_HTTPRequest $request
*/
protected function getIsMerge($request) {
$merge = $request->getVar('merge');
// Default to false if not given
if(!isset($merge)) {
Deprecation::notice(
"4.0",
"merge will be enabled by default in 4.0. Please use merge=false if you do not want to merge."
);
return false;
}
// merge=0 or merge=false will disable merge
return !in_array($merge, array('0', 'false'));
}
}

View File

View File

@ -0,0 +1 @@
<?php

View File

@ -0,0 +1 @@
<p></p>

View File

@ -0,0 +1 @@
<?php

View File

@ -0,0 +1 @@
<?php

View File

@ -0,0 +1,2 @@
<?php

View File

@ -4,25 +4,25 @@
* @subpackage tests
*/
class i18nTextCollectorTest extends SapphireTest {
/**
* @var string $tmpBasePath Used to write language files.
* We don't want to store them inside framework (or in any web-accessible place)
* in case something goes wrong with the file parsing.
*/
protected $alternateBaseSavePath;
/**
* @var string $alternateBasePath Fake webroot with a single module
* /i18ntestmodule which contains some files with _t() calls.
*/
protected $alternateBasePath;
protected $manifest;
public function setUp() {
parent::setUp();
$this->alternateBasePath = $this->getCurrentAbsolutePath() . "/_fakewebroot";
$this->alternateBaseSavePath = TEMP_FOLDER . '/i18nTextCollectorTest_webroot';
Filesystem::makeFolder($this->alternateBaseSavePath);
@ -32,12 +32,12 @@ class i18nTextCollectorTest extends SapphireTest {
$this->manifest = new SS_ClassManifest(
$this->alternateBasePath, false, true, false
);
$manifest = new SS_TemplateManifest($this->alternateBasePath, null, false, true);
$manifest->regenerate(false);
SS_TemplateLoader::instance()->pushManifest($manifest);
}
public function tearDown() {
SS_TemplateLoader::instance()->popManifest();
parent::tearDown();
@ -58,7 +58,7 @@ _t(
_t(
'Test.CONCATENATED2',
"Line \"4\" and " .
"Line \"4\" and " .
"Line 5");
PHP;
$this->assertEquals(
@ -120,7 +120,7 @@ SS;
'Test.DOUBLEQUOTE' => array("Double Quote and Spaces")
)
);
$html = <<<SS
<% _t("Test.NOSEMICOLON","No Semicolon") %>
SS;
@ -166,7 +166,7 @@ SS;
<% _t(
'Test.PRIOANDCOMMENT',
" Prio and Value with 'Single Quotes'",
"Comment with 'Single Quotes'"
) %>
SS;
@ -181,7 +181,7 @@ SS;
public function testCollectFromCodeSimple() {
$c = new i18nTextCollector();
$php = <<<PHP
_t('Test.SINGLEQUOTE','Single Quote');
PHP;
@ -191,7 +191,7 @@ PHP;
'Test.SINGLEQUOTE' => array('Single Quote')
)
);
$php = <<<PHP
_t( "Test.DOUBLEQUOTE", "Double Quote and Spaces" );
PHP;
@ -202,7 +202,7 @@ PHP;
)
);
}
public function testCollectFromCodeAdvanced() {
$c = new i18nTextCollector();
@ -218,12 +218,12 @@ PHP;
'Test.NEWLINES' => array("New Lines")
)
);
$php = <<<PHP
_t(
'Test.PRIOANDCOMMENT',
' Value with "Double Quotes"',
'Comment with "Double Quotes"'
);
PHP;
@ -233,12 +233,12 @@ PHP;
'Test.PRIOANDCOMMENT' => array(' Value with "Double Quotes"','Comment with "Double Quotes"')
)
);
$php = <<<PHP
_t(
'Test.PRIOANDCOMMENT',
" Value with 'Single Quotes'",
"Comment with 'Single Quotes'"
);
PHP;
@ -248,7 +248,7 @@ PHP;
'Test.PRIOANDCOMMENT' => array(" Value with 'Single Quotes'","Comment with 'Single Quotes'")
)
);
$php = <<<PHP
_t(
'Test.PRIOANDCOMMENT',
@ -261,7 +261,7 @@ PHP;
'Test.PRIOANDCOMMENT' => array("Value with 'Escaped Single Quotes'")
)
);
$php = <<<PHP
_t(
'Test.PRIOANDCOMMENT',
@ -275,8 +275,8 @@ PHP;
)
);
}
public function testNewlinesInEntityValues() {
$c = new i18nTextCollector();
@ -364,24 +364,24 @@ PHP;
*/
public function testPhpWriterLangArrayCodeForEntity() {
$c = new i18nTextCollector_Writer_Php();
$this->assertEquals(
$c->langArrayCodeForEntitySpec('Test.SIMPLE', array('Simple Value'), 'en_US'),
"\$lang['en_US']['Test']['SIMPLE'] = 'Simple Value';" . PHP_EOL
);
$this->assertEquals(
// single quotes should be properly escaped by the parser already
$c->langArrayCodeForEntitySpec('Test.ESCAPEDSINGLEQUOTES',
array("Value with 'Escaped Single Quotes'"), 'en_US'),
"\$lang['en_US']['Test']['ESCAPEDSINGLEQUOTES'] = 'Value with \'Escaped Single Quotes\'';" . PHP_EOL
);
$this->assertEquals(
$c->langArrayCodeForEntitySpec('Test.DOUBLEQUOTES', array('Value with "Double Quotes"'), 'en_US'),
"\$lang['en_US']['Test']['DOUBLEQUOTES'] = 'Value with \"Double Quotes\"';" . PHP_EOL
);
$php = <<<PHP
\$lang['en_US']['Test']['PRIOANDCOMMENT'] = array (
0 => 'Value with \'Single Quotes\'',
@ -394,7 +394,7 @@ PHP;
array("Value with 'Single Quotes'","Comment with 'Single Quotes'"), 'en_US'),
$php
);
$php = <<<PHP
\$lang['en_US']['Test']['PRIOANDCOMMENT'] = array (
0 => 'Value with "Double Quotes"',
@ -434,21 +434,19 @@ de:
YAML;
$this->assertEquals($yaml, Convert::nl2os($writer->getYaml($entities, 'de')));
}
public function testCollectFromIncludedTemplates() {
$c = new i18nTextCollector();
$templateFilePath = $this->alternateBasePath . '/i18ntestmodule/templates/Layout/i18nTestModule.ss';
$html = file_get_contents($templateFilePath);
$matches = $c->collectFromTemplate($html, 'mymodule', 'RandomNamespace');
/*
$this->assertArrayHasKey('i18nTestModule.ss.LAYOUTTEMPLATENONAMESPACE', $matches);
$this->assertArrayHasKey('RandomNamespace.LAYOUTTEMPLATENONAMESPACE', $matches);
$this->assertEquals(
$matches['i18nTestModule.ss.LAYOUTTEMPLATENONAMESPACE'],
$matches['RandomNamespace.LAYOUTTEMPLATENONAMESPACE'],
array('Layout Template no namespace')
);
*/
$this->assertArrayHasKey('RandomNamespace.SPRINTFNONAMESPACE', $matches);
$this->assertEquals(
$matches['RandomNamespace.SPRINTFNONAMESPACE'],
@ -464,98 +462,70 @@ YAML;
$matches['i18nTestModule.SPRINTFNAMESPACE'],
array('My replacement: %s')
);
$this->assertArrayHasKey('i18nTestModule.WITHNAMESPACE', $matches);
$this->assertEquals(
$matches['i18nTestModule.WITHNAMESPACE'],
array('Include Entity with Namespace')
);
$this->assertArrayHasKey('i18nTestModuleInclude.ss.NONAMESPACE', $matches);
$this->assertEquals(
$matches['i18nTestModuleInclude.ss.NONAMESPACE'],
array('Include Entity without Namespace')
);
$this->assertArrayHasKey('i18nTestModuleInclude.ss.SPRINTFINCLUDENAMESPACE', $matches);
$this->assertEquals(
$matches['i18nTestModuleInclude.ss.SPRINTFINCLUDENAMESPACE'],
array('My include replacement: %s')
);
$this->assertArrayHasKey('i18nTestModuleInclude.ss.SPRINTFINCLUDENONAMESPACE', $matches);
$this->assertEquals(
$matches['i18nTestModuleInclude.ss.SPRINTFINCLUDENONAMESPACE'],
array('My include replacement no namespace: %s')
);
// Includes should not automatically inject translations into parent templates
$this->assertArrayNotHasKey('i18nTestModule.WITHNAMESPACE', $matches);
$this->assertArrayNotHasKey('i18nTestModuleInclude.ss.NONAMESPACE', $matches);
$this->assertArrayNotHasKey('i18nTestModuleInclude.ss.SPRINTFINCLUDENAMESPACE', $matches);
$this->assertArrayNotHasKey('i18nTestModuleInclude.ss.SPRINTFINCLUDENONAMESPACE', $matches);
}
public function testCollectFromThemesTemplates() {
$c = new i18nTextCollector();
$theme = Config::inst()->get('SSViewer', 'theme');
Config::inst()->update('SSViewer', 'theme', 'testtheme1');
$templateFilePath = $this->alternateBasePath . '/themes/testtheme1/templates/Layout/i18nTestTheme1.ss';
$html = file_get_contents($templateFilePath);
$matches = $c->collectFromTemplate($html, 'themes/testtheme1', 'i18nTestTheme1.ss');
// Collect from layout
$layoutFilePath = $this->alternateBasePath . '/themes/testtheme1/templates/Layout/i18nTestTheme1.ss';
$layoutHTML = file_get_contents($layoutFilePath);
$layoutMatches = $c->collectFromTemplate($layoutHTML, 'themes/testtheme1', 'i18nTestTheme1.ss');
// all entities from i18nTestTheme1.ss
$this->assertEquals(
$matches['i18nTestTheme1.LAYOUTTEMPLATE'],
array('Theme1 Layout Template')
array(
'i18nTestTheme1.LAYOUTTEMPLATE'
=> array('Theme1 Layout Template'),
'i18nTestTheme1.SPRINTFNAMESPACE'
=> array('Theme1 My replacement: %s'),
'i18nTestTheme1.ss.LAYOUTTEMPLATENONAMESPACE'
=> array('Theme1 Layout Template no namespace'),
'i18nTestTheme1.ss.SPRINTFNONAMESPACE'
=> array('Theme1 My replacement no namespace: %s'),
),
$layoutMatches
);
$this->assertArrayHasKey('i18nTestTheme1.ss.LAYOUTTEMPLATENONAMESPACE', $matches);
$this->assertEquals(
$matches['i18nTestTheme1.ss.LAYOUTTEMPLATENONAMESPACE'],
array('Theme1 Layout Template no namespace')
);
$this->assertEquals(
$matches['i18nTestTheme1.SPRINTFNAMESPACE'],
array('Theme1 My replacement: %s')
);
$this->assertArrayHasKey('i18nTestTheme1.ss.SPRINTFNONAMESPACE', $matches);
$this->assertEquals(
$matches['i18nTestTheme1.ss.SPRINTFNONAMESPACE'],
array('Theme1 My replacement no namespace: %s')
);
// Collect from include
$includeFilePath = $this->alternateBasePath . '/themes/testtheme1/templates/Includes/i18nTestTheme1Include.ss';
$includeHTML = file_get_contents($includeFilePath);
$includeMatches = $c->collectFromTemplate($includeHTML, 'themes/testtheme1', 'i18nTestTheme1Include.ss');
// all entities from i18nTestTheme1Include.ss
$this->assertEquals(
$matches['i18nTestTheme1Include.WITHNAMESPACE'],
array('Theme1 Include Entity with Namespace')
array(
'i18nTestTheme1Include.SPRINTFINCLUDENAMESPACE'
=> array('Theme1 My include replacement: %s'),
'i18nTestTheme1Include.WITHNAMESPACE'
=> array('Theme1 Include Entity with Namespace'),
'i18nTestTheme1Include.ss.NONAMESPACE'
=> array('Theme1 Include Entity without Namespace'),
'i18nTestTheme1Include.ss.SPRINTFINCLUDENONAMESPACE'
=> array('Theme1 My include replacement no namespace: %s')
),
$includeMatches
);
$this->assertArrayHasKey('i18nTestTheme1Include.ss.NONAMESPACE', $matches);
$this->assertEquals(
$matches['i18nTestTheme1Include.ss.NONAMESPACE'],
array('Theme1 Include Entity without Namespace')
);
$this->assertEquals(
$matches['i18nTestTheme1Include.SPRINTFINCLUDENAMESPACE'],
array('Theme1 My include replacement: %s')
);
$this->assertArrayHasKey('i18nTestTheme1Include.ss.SPRINTFINCLUDENONAMESPACE', $matches);
$this->assertEquals(
$matches['i18nTestTheme1Include.ss.SPRINTFINCLUDENONAMESPACE'],
array('Theme1 My include replacement no namespace: %s')
);
Config::inst()->update('SSViewer', 'theme', $theme);
}
public function testCollectMergesWithExisting() {
$defaultlocal = i18n::default_locale();
$local = i18n::get_locale();
i18n::set_locale('en_US');
i18n::set_locale('en_US');
i18n::set_default_locale('en_US');
$c = new i18nTextCollector();
$c->setWriter(new i18nTextCollector_Writer_Php());
$c->basePath = $this->alternateBasePath;
$c->baseSavePath = $this->alternateBaseSavePath;
$entitiesByModule = $c->collect(null, true /* merge */);
$this->assertArrayHasKey(
'i18nTestModule.ENTITY',
@ -568,7 +538,7 @@ YAML;
'Adds new entities'
);
}
public function testCollectFromFilesystemAndWriteMasterTables() {
$defaultlocal = i18n::default_locale();
$local = i18n::get_locale();
@ -579,16 +549,16 @@ YAML;
$c->setWriter(new i18nTextCollector_Writer_Php());
$c->basePath = $this->alternateBasePath;
$c->baseSavePath = $this->alternateBaseSavePath;
$c->run();
// i18ntestmodule
$moduleLangFile = "{$this->alternateBaseSavePath}/i18ntestmodule/lang/" . $c->getDefaultLocale() . '.php';
$this->assertTrue(
file_exists($moduleLangFile),
'Master language file can be written to modules /lang folder'
);
$moduleLangFileContent = file_get_contents($moduleLangFile);
$this->assertContains(
"\$lang['en']['i18nTestModule']['ADDITION'] = 'Addition';",
@ -617,7 +587,7 @@ YAML;
"\$lang['en']['i18nTestModuleInclude.ss']['NONAMESPACE'] = 'Include Entity without Namespace';",
$moduleLangFileContent
);
// i18nothermodule
$otherModuleLangFile = "{$this->alternateBaseSavePath}/i18nothermodule/lang/" . $c->getDefaultLocale() . '.php';
$this->assertTrue(
@ -633,7 +603,7 @@ YAML;
"\$lang['en']['i18nOtherModule']['MAINTEMPLATE'] = 'Main Template Other Module';",
$otherModuleLangFileContent
);
// testtheme1
$theme1LangFile = "{$this->alternateBaseSavePath}/themes/testtheme1/lang/" . $c->getDefaultLocale() . '.php';
$this->assertTrue(
@ -661,7 +631,7 @@ YAML;
"\$lang['en']['i18nTestTheme1.ss']['SPRINTFNONAMESPACE'] = 'Theme1 My replacement no namespace: %s';",
$theme1LangFileContent
);
$this->assertContains(
"\$lang['en']['i18nTestTheme1Include']['SPRINTFINCLUDENAMESPACE'] = 'Theme1 My include replacement: %s';",
$theme1LangFileContent
@ -679,7 +649,7 @@ YAML;
. " 'Theme1 My include replacement no namespace: %s';",
$theme1LangFileContent
);
// testtheme2
$theme2LangFile = "{$this->alternateBaseSavePath}/themes/testtheme2/lang/" . $c->getDefaultLocale() . '.php';
$this->assertTrue(
@ -695,7 +665,7 @@ YAML;
i18n::set_locale($local); //set the locale to the US locale expected in the asserts
i18n::set_default_locale($defaultlocal);
}
public function testCollectFromEntityProvidersInCustomObject() {
$c = new i18nTextCollector();
@ -713,5 +683,164 @@ YAML;
$matches['i18nTextCollectorTestMyObject.SINGULARNAME'][0]
);
}
/**
* Test that duplicate keys are resolved to the appropriate modules
*/
public function testResolveDuplicates() {
$collector = new i18nTextCollectorTest_Collector();
// Dummy data as collected
$data1 = array(
'framework' => array(
'DataObject.PLURALNAME' => array('Data Objects'),
'DataObject.SINGULARNAME' => array('Data Object')
),
'mymodule' => array(
'DataObject.PLURALNAME' => array('Ignored String'),
'DataObject.STREETNAME' => array('Shortland Street')
)
);
$expected = array(
'framework' => array(
'DataObject.PLURALNAME' => array('Data Objects'),
// Because DataObject is in framework module
'DataObject.SINGULARNAME' => array('Data Object')
),
'mymodule' => array(
// Because this key doesn't exist in framework strings
'DataObject.STREETNAME' => array('Shortland Street')
)
);
$resolved = $collector->resolveDuplicateConflicts_Test($data1);
$this->assertEquals($expected, $resolved);
// Test getConflicts
$data2 = array(
'module1' => array(
'DataObject.ONE' => array('One'),
'DataObject.TWO' => array('Two'),
'DataObject.THREE' => array('Three'),
),
'module2' => array(
'DataObject.THREE' => array('Three'),
),
'module3' => array(
'DataObject.TWO' => array('Two'),
'DataObject.THREE' => array('Three'),
)
);
$conflictsA = $collector->getConflicts_Test($data2);
sort($conflictsA);
$this->assertEquals(
array('DataObject.THREE', 'DataObject.TWO'),
$conflictsA
);
// Removing module3 should remove a conflict
unset($data2['module3']);
$conflictsB = $collector->getConflicts_Test($data2);
$this->assertEquals(
array('DataObject.THREE'),
$conflictsB
);
}
/**
* Test ability for textcollector to detect modules
*/
public function testModuleDetection() {
$collector = new i18nTextCollectorTest_Collector();
$modules = $collector->getModules_Test($this->alternateBasePath);
$this->assertEquals(
array(
'i18nnonstandardmodule',
'i18nothermodule',
'i18ntestmodule',
'themes/testtheme1',
'themes/testtheme2'
),
$modules
);
}
/**
* Test that text collector can detect module file lists properly
*/
public function testModuleFileList() {
$collector = new i18nTextCollectorTest_Collector();
$collector->basePath = $this->alternateBasePath;
$collector->baseSavePath = $this->alternateBaseSavePath;
// Non-standard modules can't be safely filtered, so just index everything
$nonStandardFiles = $collector->getFileListForModule_Test('i18nnonstandardmodule');
$nonStandardRoot = $this->alternateBasePath . '/i18nnonstandardmodule';
$this->assertEquals(3, count($nonStandardFiles));
$this->assertArrayHasKey("{$nonStandardRoot}/_config.php", $nonStandardFiles);
$this->assertArrayHasKey("{$nonStandardRoot}/phpfile.php", $nonStandardFiles);
$this->assertArrayHasKey("{$nonStandardRoot}/template.ss", $nonStandardFiles);
// Normal module should have predictable dir structure
$testFiles = $collector->getFileListForModule_Test('i18ntestmodule');
$testRoot = $this->alternateBasePath . '/i18ntestmodule';
$this->assertEquals(6, count($testFiles));
// Code in code folder is detected
$this->assertArrayHasKey("{$testRoot}/code/i18nTestModule.php", $testFiles);
$this->assertArrayHasKey("{$testRoot}/code/subfolder/_config.php", $testFiles);
$this->assertArrayHasKey("{$testRoot}/code/subfolder/i18nTestSubModule.php", $testFiles);
// Templates in templates folder is detected
$this->assertArrayHasKey("{$testRoot}/templates/Includes/i18nTestModuleInclude.ss", $testFiles);
$this->assertArrayHasKey("{$testRoot}/templates/Layout/i18nTestModule.ss", $testFiles);
$this->assertArrayHasKey("{$testRoot}/templates/i18nTestModule.ss", $testFiles);
// Standard modules with code in odd places should only have code in those directories detected
$otherFiles = $collector->getFileListForModule_Test('i18nothermodule');
$otherRoot = $this->alternateBasePath . '/i18nothermodule';
$this->assertEquals(3, count($otherFiles));
// Only detect well-behaved files
$this->assertArrayHasKey("{$otherRoot}/code/i18nOtherModule.php", $otherFiles);
$this->assertArrayHasKey("{$otherRoot}/code/i18nTestModuleDecorator.php", $otherFiles);
$this->assertArrayHasKey("{$otherRoot}/templates/i18nOtherModule.ss", $otherFiles);
// Themes should detect all ss files only
$theme1Files = $collector->getFileListForModule_Test('themes/testtheme1');
$theme1Root = $this->alternateBasePath . '/themes/testtheme1/templates';
$this->assertEquals(3, count($theme1Files));
// Find only ss files
$this->assertArrayHasKey("{$theme1Root}/Includes/i18nTestTheme1Include.ss", $theme1Files);
$this->assertArrayHasKey("{$theme1Root}/Layout/i18nTestTheme1.ss", $theme1Files);
$this->assertArrayHasKey("{$theme1Root}/i18nTestTheme1Main.ss", $theme1Files);
// Only 1 file here
$theme2Files = $collector->getFileListForModule_Test('themes/testtheme2');
$this->assertEquals(1, count($theme2Files));
$this->assertArrayHasKey(
$this->alternateBasePath . '/themes/testtheme2/templates/i18nTestTheme2.ss',
$theme2Files
);
}
}
/**
* Assist with testing of specific protected methods
*/
class i18nTextCollectorTest_Collector extends i18nTextCollector implements TestOnly {
public function getModules_Test($directory) {
return $this->getModules($directory);
}
public function resolveDuplicateConflicts_Test($entitiesByModule) {
return $this->resolveDuplicateConflicts($entitiesByModule);
}
public function getFileListForModule_Test($module) {
return parent::getFileListForModule($module);
}
public function getConflicts_Test($entitiesByModule) {
return parent::getConflicts($entitiesByModule);
}
}

View File

@ -4,17 +4,17 @@
* @subpackage tests
*/
class ShortcodeParserTest extends SapphireTest {
protected $arguments, $contents, $tagName, $parser;
protected $extra = array();
public function setUp() {
ShortcodeParser::get('test')->register('test_shortcode', array($this, 'shortcodeSaver'));
$this->parser = ShortcodeParser::get('test');
parent::setUp();
}
/**
* Tests that valid short codes that have not been registered are not replaced.
*/
@ -37,7 +37,7 @@ class ShortcodeParserTest extends SapphireTest {
'<strong class="warning">[not_shortcode]</strong>',
$this->parser->parse('[not_shortcode]')
);
ShortcodeParser::$error_behavior = ShortcodeParser::LEAVE;
$this->assertEquals('[not_shortcode]',
@ -56,66 +56,66 @@ class ShortcodeParserTest extends SapphireTest {
$this->parser->parse('<img class="[not_shortcode]">')
);
}
public function testSimpleTag() {
$tests = array(
'[test_shortcode]',
'[test_shortcode]',
'[test_shortcode ]', '[test_shortcode,]', '[test_shortcode, ]'.
'[test_shortcode/]', '[test_shortcode /]', '[test_shortcode,/]', '[test_shortcode, /]'
);
foreach($tests as $test) {
$this->parser->parse($test);
$this->assertEquals(array(), $this->arguments, $test);
$this->assertEquals('', $this->contents, $test);
$this->assertEquals('test_shortcode', $this->tagName, $test);
}
}
public function testOneArgument() {
$tests = array (
'[test_shortcode foo="bar"]', '[test_shortcode,foo="bar"]',
"[test_shortcode foo='bar']", "[test_shortcode,foo='bar']",
'[test_shortcode foo = "bar" /]', '[test_shortcode, foo = "bar" /]'
);
foreach($tests as $test) {
$this->parser->parse($test);
$this->assertEquals(array('foo' => 'bar'), $this->arguments, $test);
$this->assertEquals('', $this->contents, $test);
$this->assertEquals('test_shortcode', $this->tagName, $test);
}
}
public function testMultipleArguments() {
$this->parser->parse('[test_shortcode foo = "bar",bar=\'foo\', baz="buz"]');
$this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', 'baz' => 'buz'), $this->arguments);
$this->assertEquals('', $this->contents);
$this->assertEquals('test_shortcode', $this->tagName);
}
public function testEnclosing() {
$this->parser->parse('[test_shortcode]foo[/test_shortcode]');
$this->assertEquals(array(), $this->arguments);
$this->assertEquals('foo', $this->contents);
$this->assertEquals('test_shortcode', $this->tagName);
}
public function testEnclosingWithArguments() {
$this->parser->parse('[test_shortcode,foo = "bar",bar=\'foo\',baz="buz"]foo[/test_shortcode]');
$this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', 'baz' => 'buz'), $this->arguments);
$this->assertEquals('foo', $this->contents);
$this->assertEquals('test_shortcode', $this->tagName);
}
public function testShortcodeEscaping() {
$this->assertEquals(
'[test_shortcode]',
'[test_shortcode]',
$this->parser->parse('[[test_shortcode]]')
);
@ -123,12 +123,12 @@ class ShortcodeParserTest extends SapphireTest {
'[test_shortcode /]',
$this->parser->parse('[[test_shortcode /]]')
);
$this->assertEquals(
'[test_shortcode]content[/test_shortcode]',
$this->parser->parse('[[test_shortcode]content[/test_shortcode]]'
));
$this->assertEquals(
'[test_shortcode]content',
$this->parser->parse('[[test_shortcode]][test_shortcode]content[/test_shortcode]')
@ -138,12 +138,12 @@ class ShortcodeParserTest extends SapphireTest {
'[test_shortcode]content[/test_shortcode]content2',
$this->parser->parse('[[test_shortcode]content[/test_shortcode]][test_shortcode]content2[/test_shortcode]'
));
$this->assertEquals(
'[[Doesnt strip double [ character if not a shortcode',
$this->parser->parse('[[Doesnt strip double [ character if not a [test_shortcode]shortcode[/test_shortcode]'
));
$this->assertEquals(
'[[Doesnt shortcode get confused by double ]] characters',
$this->parser->parse(
@ -155,7 +155,7 @@ class ShortcodeParserTest extends SapphireTest {
$this->assertEquals('', $this->parser->parse('[test_shortcode,foo=bar!,baz = buz123]'));
$this->assertEquals(array('foo' => 'bar!', 'baz' => 'buz123'), $this->arguments);
}
public function testSpacesForDelimiter() {
$this->assertEquals('', $this->parser->parse('[test_shortcode foo=bar! baz = buz123]'));
$this->assertEquals(array('foo' => 'bar!', 'baz' => 'buz123'), $this->arguments);
@ -167,22 +167,22 @@ class ShortcodeParserTest extends SapphireTest {
$this->parser->parse('[test_shortcode,id="1"/]more[test_shortcode,id="2"]content[/test_shortcode]'),
'Assert that self-closing tags are respected during parsing.'
);
$this->assertEquals(2, $this->arguments['id']);
}
public function testConsecutiveTags() {
$this->assertEquals('', $this->parser->parse('[test_shortcode][test_shortcode]'));
}
protected function assertEqualsIgnoringWhitespace($a, $b, $message = null) {
$this->assertEquals(preg_replace('/\s+/', '', $a), preg_replace('/\s+/', '', $b), $message);
}
public function testtExtract() {
// Left extracts to before the current block
$this->assertEqualsIgnoringWhitespace(
'Code<div>FooBar</div>',
'Code<div>FooBar</div>',
$this->parser->parse('<div>Foo[test_shortcode class=left]Code[/test_shortcode]Bar</div>')
);
@ -194,16 +194,16 @@ class ShortcodeParserTest extends SapphireTest {
// Center splits the current block
$this->assertEqualsIgnoringWhitespace(
'<div>Foo</div>Code<div>Bar</div>',
'<div>Foo</div>Code<div>Bar</div>',
$this->parser->parse('<div>Foo[test_shortcode class=center]Code[/test_shortcode]Bar</div>')
);
// Even if the immediate parent isn't a the current block
$this->assertEqualsIgnoringWhitespace(
'<div>Foo<b>Bar</b></div>Code<div><b>Baz</b>Qux</div>',
'<div>Foo<b>Bar</b></div>Code<div><b>Baz</b>Qux</div>',
$this->parser->parse('<div>Foo<b>Bar[test_shortcode class=center]Code[/test_shortcode]Baz</b>Qux</div>')
);
// No class means don't extract
$this->assertEqualsIgnoringWhitespace(
'<div>FooCodeBar</div>',
@ -211,6 +211,37 @@ class ShortcodeParserTest extends SapphireTest {
);
}
public function testShortcodesInsideScriptTag() {
$this->assertEqualsIgnoringWhitespace(
'<script>hello</script>',
$this->parser->parse('<script>[test_shortcode]hello[/test_shortcode]</script>')
);
}
public function testNumericShortcodes() {
$this->assertEqualsIgnoringWhitespace(
'[2]',
$this->parser->parse('[2]')
);
$this->assertEqualsIgnoringWhitespace(
'<script>[2]</script>',
$this->parser->parse('<script>[2]</script>')
);
$this->parser->register('2', function($attributes, $content, $this, $tag, $extra) {
return 'this is 2';
});
$this->assertEqualsIgnoringWhitespace(
'this is 2',
$this->parser->parse('[2]')
);
$this->assertEqualsIgnoringWhitespace(
'<script>this is 2</script>',
$this->parser->parse('<script>[2]</script>')
);
}
public function testExtraContext() {
$this->parser->parse('<a href="[test_shortcode]">Test</a>');
@ -220,7 +251,7 @@ class ShortcodeParserTest extends SapphireTest {
}
// -----------------------------------------------------------------------------------------------------------------
/**
* Stores the result of a shortcode parse in object properties for easy testing access.
*/
@ -232,5 +263,5 @@ class ShortcodeParserTest extends SapphireTest {
return $content;
}
}

View File

@ -172,6 +172,13 @@ class MemberTest extends FunctionalTest {
$this->assertInstanceOf('DataObject', $passwords->current());
$this->assertTrue($passwords->current()->checkPassword('1nitialPassword'),
"Password 1nitialPassword not found in MemberRecord");
//check we don't retain orphaned records when a member is deleted
$member->delete();
$passwords = MemberPassword::get()->filter('MemberID', $member->OldID);
$this->assertCount(0, $passwords);
}
/**