MINOR Merged from branches/2.3

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@69704 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2009-01-05 06:19:48 +00:00
parent a32a79e816
commit 085346f0e0
41 changed files with 638 additions and 292 deletions

View File

@ -9,11 +9,9 @@
class RestfulService extends ViewableData {
protected $baseURL;
protected $queryString;
protected $rawXML;
protected $errorTag;
protected $checkErrors;
protected $cache_expire;
protected $authUsername, $authPassword;
protected $customHeaders = array();
@ -59,7 +57,7 @@ class RestfulService extends ViewableData {
*/
public function connect($subURL = '') {
user_error("RestfulService::connect is deprecated; use RestfulService::request", E_USER_NOTICE);
return $this->request($subURL, 'GET');
return $this->request($subURL)->getBody();
}
/**
@ -72,7 +70,7 @@ class RestfulService extends ViewableData {
* This is a replacement of {@link connect()}.
*/
public function request($subURL = '', $method = "GET", $data = null, $headers = null) {
$url = $this->baseURL . $subURL; //url for the request
$url = $this->baseURL . $subURL; // Url for the request
if($this->queryString) {
if(strpos($url, '?') !== false) {
$url .= '&' . $this->queryString;
@ -80,68 +78,68 @@ class RestfulService extends ViewableData {
$url .= '?' . $this->queryString;
}
}
$url = str_replace(' ', '%20', $url); // spaces should be encoded
$url = str_replace(' ', '%20', $url); // Encode spaces
$method = strtoupper($method);
assert(in_array($method, array('GET','POST','PUT','DELETE','HEAD','OPTIONS')));
//check for file exists in cache
//set the cache directory
$cachedir = TEMP_FOLDER; // Default silverstripe cache
$cache_file = md5($url); // Encoded name of cache file
$cache_path = $cachedir."/xmlresponse_$cache_file";
/* we've disabled caching until we can figure out how to deal with storing responses
$cachedir=TEMP_FOLDER; //default silverstrip-cache
$cache_file = md5($url); //encoded name of cache file
$cache_path = $cachedir."/$cache_file";
if( !isset($_GET['flush']) && ( @file_exists("$cache_path") && ((@filemtime($cache_path) + $this->cache_expire) > ( time() )))){
$this->rawXML = file_get_contents($cache_path);
// Check for unexpired cached feed (unless flush is set)
if(!isset($_GET['flush']) && @file_exists($cache_path) && @filemtime($cache_path) + $this->cache_expire > time()) {
$store = file_get_contents($cache_path);
$response = unserialize($store);
} else {//not available in cache fetch from server
*/
$ch = curl_init();
$timeout = 5;
$useragent = "SilverStripe/2.2";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
} else {
$ch = curl_init();
$timeout = 5;
$useragent = "SilverStripe/2.2";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if($this->customHeaders) {
$headers = array_merge((array)$this->customHeaders, (array)$headers);
}
if($headers) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if($this->authUsername) curl_setopt($ch, CURLOPT_USERPWD, "$this->authUsername:$this->authPassword");
if($method == 'POST') {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$responseBody = curl_exec($ch);
if($responseBody === false) {
$curlError = curl_error($ch);
// Problem verifying the server SSL certificate; just ignore it as it's not mandatory
if(strpos($curlError,'14090086') !== false) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$responseBody = curl_exec($ch);
$curlError = curl_error($ch);
// Add headers
if($this->customHeaders) {
$headers = array_merge((array)$this->customHeaders, (array)$headers);
}
if($respnoseBody === false) {
if($headers) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Add authentication
if($this->authUsername) curl_setopt($ch, CURLOPT_USERPWD, "$this->authUsername:$this->authPassword");
// Add fields to POST requests
if($method == 'POST') {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$responseBody = curl_exec($ch);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$responseBody = curl_exec($ch);
$curlError = curl_error($ch);
if($curlError) {
user_error("Curl Error:" . $curlError, E_USER_WARNING);
return;
}
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$response = new RestfulService_Response($responseBody, curl_getinfo($ch, CURLINFO_HTTP_CODE));
curl_close($ch);
// Serialise response object and write to cache
$store = serialize($response);
file_put_contents($cache_path,$store);
}
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$response = new RestfulService_Response($responseBody, curl_getinfo($ch, CURLINFO_HTTP_CODE));
curl_close($ch);
return $response;
}
@ -164,14 +162,13 @@ class RestfulService extends ViewableData {
$childElements = $xml->{$collection}->{$element};
if($childElements){
foreach($childElements as $child){
$data = array();
foreach($child->attributes() as $key => $value){
$data["$key"] = Convert::raw2xml($value);
foreach($childElements as $child){
$data = array();
foreach($child->attributes() as $key => $value){
$data["$key"] = Convert::raw2xml($value);
}
$output->push(new ArrayData($data));
}
$output->push(new ArrayData($data));
}
}
return $output;

View File

@ -39,7 +39,7 @@ class XMLDataFormatter extends DataFormatter {
$id = $obj->ID;
$objHref = Director::absoluteURL(self::$api_base . "$obj->class/$obj->ID");
$json = "<$className href=\"$objHref.xml\">\n";
$xml = "<$className href=\"$objHref.xml\">\n";
foreach($this->getFieldsForObj($obj) as $fieldName => $fieldType) {
// Field filtering
if($fields && !in_array($fieldName, $fields)) continue;
@ -48,9 +48,9 @@ class XMLDataFormatter extends DataFormatter {
if(!mb_check_encoding($fieldValue,'utf-8')) $fieldValue = "(data is badly encoded)";
if(is_object($fieldValue) && is_subclass_of($fieldValue, 'Object') && $fieldValue->hasMethod('toXML')) {
$json .= $fieldValue->toXML();
$xml .= $fieldValue->toXML();
} else {
$json .= "<$fieldName>" . Convert::raw2xml($fieldValue) . "</$fieldName>\n";
$xml .= "<$fieldName>" . Convert::raw2xml($fieldValue) . "</$fieldName>\n";
}
}
@ -66,7 +66,7 @@ class XMLDataFormatter extends DataFormatter {
} else {
$href = Director::absoluteURL(self::$api_base . "$className/$id/$relName");
}
$json .= "<$relName linktype=\"has_one\" href=\"$href.xml\" id=\"{$obj->$fieldName}\" />\n";
$xml .= "<$relName linktype=\"has_one\" href=\"$href.xml\" id=\"" . $obj->$fieldName . "\"></$relName>\n";
}
foreach($obj->has_many() as $relName => $relClass) {
@ -74,14 +74,14 @@ class XMLDataFormatter extends DataFormatter {
if($fields && !in_array($relName, $fields)) continue;
if($this->customRelations && !in_array($relName, $this->customRelations)) continue;
$json .= "<$relName linktype=\"has_many\" href=\"$objHref/$relName.xml\">\n";
$xml .= "<$relName linktype=\"has_many\" href=\"$objHref/$relName.xml\">\n";
$items = $obj->$relName();
foreach($items as $item) {
//$href = Director::absoluteURL(self::$api_base . "$className/$id/$relName/$item->ID");
$href = Director::absoluteURL(self::$api_base . "$relClass/$item->ID");
$json .= "<$relClass href=\"$href.xml\" id=\"{$item->ID}\" />\n";
$xml .= "<$relClass href=\"$href.xml\" id=\"{$item->ID}\"></$relClass>\n";
}
$json .= "</$relName>\n";
$xml .= "</$relName>\n";
}
foreach($obj->many_many() as $relName => $relClass) {
@ -89,19 +89,19 @@ class XMLDataFormatter extends DataFormatter {
if($fields && !in_array($relName, $fields)) continue;
if($this->customRelations && !in_array($relName, $this->customRelations)) continue;
$json .= "<$relName linktype=\"many_many\" href=\"$objHref/$relName.xml\">\n";
$xml .= "<$relName linktype=\"many_many\" href=\"$objHref/$relName.xml\">\n";
$items = $obj->$relName();
foreach($items as $item) {
$href = Director::absoluteURL(self::$api_base . "$relClass/$item->ID");
$json .= "<$relClass href=\"$href.xml\" id=\"{$item->ID}\" />\n";
$xml .= "<$relClass href=\"$href.xml\" id=\"{$item->ID}\"></$relClass>\n";
}
$json .= "</$relName>\n";
$xml .= "</$relName>\n";
}
}
$json .= "</$className>";
return $json;
$xml .= "</$className>";
return $xml;
}
/**

View File

@ -49,22 +49,33 @@ class Convert extends Object {
}
}
static function raw2xml($val) {
/**
* Ensure that text is properly escaped for XML.
*
* @param array|string $val String to escape, or array of strings
* @return array|string
*/
static function raw2xml($val) {
if(is_array($val)) {
foreach($val as $k => $v) $val[$k] = self::raw2xml($v);
return $val;
} else {
return str_replace(array('&', '<', '>', "\n"), array('&amp;', '&lt;', '&gt;', '<br />'), $val);
}
}
/**
* Ensure that text is properly escaped for Javascript.
*
* @param array|string $val String to escape, or array of strings
* @return array|string
*/
static function raw2js($val) {
if(is_array($val)) {
foreach($val as $k => $v) $val[$k] = self::raw2js($v);
return $val;
} else {
return str_replace(array("\\", '"',"\n","\r", "'"), array("\\\\", '\"','\n','\r', "\\'"), $val);
return str_replace(array("\\", '"', "\n", "\r", "'"), array("\\\\", '\"', '\n', '\r', "\\'"), $val);
}
}

View File

@ -55,7 +55,7 @@ class ContentNegotiator {
* @usedby Controller->handleRequest()
*/
static function process(HTTPResponse $response) {
if(self::$disabled) return;
if(!self::enabled_for($response)) return;
$mimes = array(
"xhtml" => "application/xhtml+xml",
@ -138,19 +138,46 @@ class ContentNegotiator {
$response->addHeader("Vary", "Accept");
$content = $response->getBody();
$hasXMLHeader = (substr($content,0,5) == '<' . '?xml' );
$content = ereg_replace("<\\?xml[^>]+\\?>\n?",'',$content);
$content = str_replace(array('/>','xml:lang','application/xhtml+xml'),array('>','lang','text/html'), $content);
$content = ereg_replace('<!DOCTYPE[^>]+>', '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">', $content);
// Only replace the doctype in templates with the xml header
if($hasXMLHeader) {
$content = ereg_replace('<!DOCTYPE[^>]+>', '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">', $content);
}
$content = ereg_replace('<html xmlns="[^"]+"','<html ', $content);
$response->setBody($content);
}
protected static $disabled;
static function disable() {
self::$disabled = true;
protected static $enabled = false;
/**
* Enable content negotiation for all templates, not just those with the xml header.
*/
static function enable() {
self::$enabled = true;
}
/**
* @deprecated in 2.3
*/
static function disable() {
self::$enabled = false;
}
/**
* Returns true if negotation is enabled for the given response.
* By default, negotiation is only enabled for pages that have the xml header.
*/
static function enabled_for($response) {
if(self::$enabled) return true;
else return (substr($response->getBody(),0,5) == '<' . '?xml');
}
}
?>

View File

@ -811,12 +811,22 @@ class i18n extends Object {
*/
static function _t($entity, $string = "", $priority = 40, $context = "") {
global $lang;
// get current locale (either default or user preference)
$locale = i18n::get_locale();
// parse $entity into its parts
$entityParts = explode('.',$entity);
$realEntity = array_pop($entityParts);
$class = implode('.',$entityParts);
if(!isset($lang[$locale][$class])) i18n::include_by_class($class);
// if language table isn't loaded for this locale, get it for each of the modules
if(!isset($lang[$locale])) i18n::include_by_locale($locale);
// fallback to the passed $string if no translation is present
$transEntity = isset($lang[$locale][$class][$realEntity]) ? $lang[$locale][$class][$realEntity] : $string;
// entities can be stored in both array and literal values in the language tables
return (is_array($transEntity) ? $transEntity[0] : $transEntity);
}

View File

@ -63,15 +63,25 @@ class i18nTextCollector extends Object {
* and write the resultant files in the lang folder of each module.
*
* @uses DataObject->collectI18nStatics()
*
* @param array $restrictToModules
*/
public function run($restrictToModule = null) {
public function run($restrictToModules = null) {
//Debug::message("Collecting text...", false);
$modules = array();
// A master string tables array (one mst per module)
$entitiesByModule = array();
//Search for and process existent modules, or use the passed one instead
$modules = (isset($restrictToModule)) ? array(basename($restrictToModule)) : scandir($this->basePath);
if($restrictToModules && count($restrictToModules)) {
foreach($restrictToModules as $restrictToModule) {
$modules[] = basename($restrictToModule);
}
} else {
$modules = scandir($this->basePath);
}
foreach($modules as $module) {
// Only search for calls in folder with a _config.php file (which means they are modules)
@ -83,9 +93,25 @@ class i18nTextCollector extends Object {
if(!$isValidModuleFolder) continue;
// we store the master string tables
$entitiesByModule[$module] = $this->processModule($module);
$processedEntities = $this->processModule($module);
if(isset($entitiesByModule[$module])) {
$entitiesByModule[$module] = array_merge_recursive($entitiesByModule[$module], $processedEntities);
} else {
$entitiesByModule[$module] = $processedEntities;
}
// extract all entities for "foreign" modules (fourth argument)
foreach($entitiesByModule[$module] as $fullName => $spec) {
if(isset($spec[3]) && $spec[3] != $module) {
$othermodule = $spec[3];
if(!isset($entitiesByModule[$othermodule])) $entitiesByModule[$othermodule] = array();
unset($spec[3]);
$entitiesByModule[$othermodule][$fullName] = $spec;
unset($entitiesByModule[$module][$fullName]);
}
}
}
// Write the generated master string tables
$this->writeMasterStringFile($entitiesByModule);

View File

@ -26,7 +26,8 @@ class i18nTextCollectorTask extends BuildTask {
*/
public function run($request) {
$c = new i18nTextCollector();
return $c->run($request->getVar('module'));
$restrictModules = ($request->getVar('module')) ? explode(',', $request->getVar('module')) : null;
return $c->run($restrictModules);
}
}
?>

View File

@ -711,7 +711,7 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
// Update the changed array with references to changed obj-fields
foreach($this->record as $k => $v) {
if(is_object($v) && $v->isChanged()) {
if(is_object($v) && method_exists($v, 'isChanged') && $v->isChanged()) {
$this->changed[$k] = true;
}
}
@ -1302,7 +1302,7 @@ class DataObject extends ViewableData implements DataObjectInterface,i18nEntityP
if(!is_string($k) || is_numeric($k) || !is_string($v)) user_error("$class::\$db has a bad entry: "
. var_export($k,true). " => " . var_export($v,true) . ". Each map key should be a property name, and the map value should be the property type.", E_USER_ERROR);
}
$items = isset($items) ? array_merge($newItems, (array)$items) : $newItems;
$items = isset($items) ? array_merge((array)$items, $newItems) : $newItems;
}
}

View File

@ -77,8 +77,8 @@ class DatabaseAdmin extends Controller {
// Get all our classes
ManifestBuilder::create_manifest_file();
require(MANIFEST_FILE);
$this->doBuild(isset($_REQUEST['quiet']) || isset($_REQUEST['from_installer']));
$this->doBuild(isset($_REQUEST['quiet']) || isset($_REQUEST['from_installer']), !isset($_REQUEST['dont_populate']));
}
/**

View File

@ -11,17 +11,22 @@ class SQLMap extends Object implements IteratorAggregate {
* @var SQLQuery
*/
protected $query;
protected $keyField, $titleField;
/**
* Construct a SQLMap.
* @param SQLQuery $query The query to generate this map. THis isn't executed until it's needed.
*/
public function __construct(SQLQuery $query) {
public function __construct(SQLQuery $query, $keyField = "ID", $titleField = "Title") {
if(!$query) {
user_error('SQLMap constructed with null query.', E_USER_ERROR);
}
$this->query = $query;
$this->keyField = $keyField;
$this->titleField = $titleField;
parent::__construct();
}
/**
@ -44,7 +49,7 @@ class SQLMap extends Object implements IteratorAggregate {
public function getIterator() {
$this->genItems();
return new SQLMap_Iterator($this->items->getIterator());
return new SQLMap_Iterator($this->items->getIterator(), $this->keyField, $this->titleField);
}
/**
@ -80,9 +85,12 @@ class SQLMap extends Object implements IteratorAggregate {
class SQLMap_Iterator extends Object implements Iterator {
protected $items;
protected $keyField, $titleField;
function __construct(Iterator $items) {
function __construct(Iterator $items, $keyField, $titleField) {
$this->items = $items;
$this->keyField = $keyField;
$this->titleField = $titleField;
}
@ -90,20 +98,20 @@ class SQLMap_Iterator extends Object implements Iterator {
* Iterator functions - necessary for foreach to work
*/
public function rewind() {
return $this->items->rewind() ? $this->items->rewind()->Title : null;
return $this->items->rewind() ? $this->items->rewind()->{$this->titleField} : null;
}
public function current() {
return $this->items->current()->Title;
return $this->items->current()->{$this->titleField};
}
public function key() {
return $this->items->current()->ID;
return $this->items->current()->{$this->keyField};
}
public function next() {
$next = $this->items->next();
return isset($next->Title) ? $next->Title : null;
return isset($next->{$this->titleField}) ? $next->{$this->titleField} : null;
}
public function valid() {

View File

@ -415,7 +415,16 @@ class SQLQuery extends Object {
*
* TODO Respect HAVING and GROUPBY, which can affect the result-count
*/
function unlimitedRowCount( $column = "*" ) {
function unlimitedRowCount( $column = null) {
// Choose a default column
if($column == null) {
if($this->groupby) {
$column = 'DISTINCT ' . implode(", ", $this->groupby);
} else {
$column = '*';
}
}
$clone = clone $this;
$clone->select = array("count($column)");
$clone->limit = null;

View File

@ -7,7 +7,7 @@
* In addition, it contains a number of static methods for querying the site tree.
* @package cms
*/
class SiteTree extends DataObject implements PermissionProvider {
class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvider {
/**
* Indicates what kind of children this page type can have.
@ -1485,7 +1485,6 @@ class SiteTree extends DataObject implements PermissionProvider {
$classes = ClassInfo::getValidSubClasses('SiteTree');
array_shift($classes);
$currentAddAction = null;
$currentClass = null;
$result = array();
@ -1493,22 +1492,45 @@ class SiteTree extends DataObject implements PermissionProvider {
$instance = singleton($class);
if((($instance instanceof HiddenClass) || !$instance->canCreate()) && ($class != $this->class)) continue;
$addAction = $instance->i18n_singular_name();
$pageTypeName = $instance->i18n_singular_name();
if($class == $this->class) {
$currentClass = $class;
$currentAddAction = $addAction;
$result[$class] = $pageTypeName;
} else {
$result[$class] = ($class == $this->class)
? _t('SiteTree.CURRENTLY', 'Currently').' '.$addAction
: _t('SiteTree.CHANGETO', 'Change to').' '.$addAction;
$translation = _t(
'SiteTree.CHANGETO',
'Change to "%s"',
PR_MEDIUM,
"Pagetype selection dropdown with class names"
);
// @todo legacy fix to avoid empty classname dropdowns when translation doesn't include %s
if(strpos($translation, '%s') !== FALSE) {
$result[$class] = sprintf(
$translation,
$pageTypeName
);
} else {
$result[$class] = "{$translation} \"{$pageTypeName}\"";
}
}
// if we're in translation mode, the link between the translated pagetype
// title and the actual classname might not be obvious, so we add it in parantheses
// Example: class "RedirectorPage" has the title "Weiterleitung" in German,
// so it shows up as "Weiterleitung (RedirectorPage)"
if(i18n::get_locale() != 'en_US') {
$result[$class] = $result[$class] . " ({$class})";
}
}
// sort alphabetically, and put current on top
asort($result);
$currentPageTypeName = $result[$currentClass];
unset($result[$currentClass]);
$result = array_reverse($result);
$result[$currentClass] = $currentAddAction.' ('._t('SiteTree.CURRENT','current').')';
$result[$currentClass] = $currentPageTypeName;
$result = array_reverse($result);
return $result;
@ -1739,6 +1761,19 @@ class SiteTree extends DataObject implements PermissionProvider {
)
);
}
/**
* Overloaded to also provide entities for 'Page' class which is usually
* located in custom code, hence textcollector picks it up for the wrong folder.
*/
function provideI18nEntities() {
$entities = parent::provideI18nEntities();
if(isset($entities['Page.SINGULARNAME'])) $entities['Page.SINGULARNAME'][3] = 'sapphire';
if(isset($entities['Page.PLURALNAME'])) $entities['Page.PLURALNAME'][3] = 'sapphire';
return $entities;
}
}
?>

View File

@ -16,7 +16,7 @@ class Date extends DBField {
if(ereg('^([0-9]+)/([0-9]+)/([0-9]+)$', $value, $parts))
$value = "$parts[2]/$parts[1]/$parts[3]";
if($value) $this->value = date('Y-m-d', strtotime($value));
if($value && is_string($value)) $this->value = date('Y-m-d', strtotime($value));
else $value = null;
}
@ -95,10 +95,27 @@ class Date extends DBField {
*/
function Ago() {
if($this->value) {
if(time() < strtotime($this->value)) $agoWord = _t("Date.AWAY", " away");
else $agoWord = _t("Date.AGO", " ago");
return $this->TimeDiff() . ' ' . $agoWord;
if(time() > strtotime($this->value)) {
return sprintf(
_t(
'Date.TIMEDIFFAGO',
"%s ago",
PR_MEDIUM,
'Natural language time difference, e.g. 2 hours ago'
),
$this->TimeDiff()
);
} else {
return sprintf(
_t(
'Date.TIMEDIFFAWAY',
"%s away",
PR_MEDIUM,
'Natural language time difference, e.g. 2 hours away'
),
$this->TimeDiff()
);
}
}
}
@ -109,27 +126,27 @@ class Date extends DBField {
if($ago < 60) {
$span = $ago;
return ($span != 1) ? "{$span}"._t("Date.SECS", " secs") : "{$span}"._t("Date.SEC", " sec");
return ($span != 1) ? "{$span} "._t("Date.SECS", " secs") : "{$span} "._t("Date.SEC", " sec");
}
if($ago < 3600) {
$span = round($ago/60);
return ($span != 1) ? "{$span}"._t("Date.MINS", " mins") : "{$span}"._t("Date.MIN", " min");
return ($span != 1) ? "{$span} "._t("Date.MINS", " mins") : "{$span} "._t("Date.MIN", " min");
}
if($ago < 86400) {
$span = round($ago/3600);
return ($span != 1) ? "{$span}"._t("Date.HOURS", " hours") : "{$span}"._t("Date.HOUR", " hour");
return ($span != 1) ? "{$span} "._t("Date.HOURS", " hours") : "{$span} "._t("Date.HOUR", " hour");
}
if($ago < 86400*30) {
$span = round($ago/86400);
return ($span != 1) ? "{$span}"._t("Date.DAYS", " days") : "{$span}"._t("Date.DAY", " day");
return ($span != 1) ? "{$span} "._t("Date.DAYS", " days") : "{$span} "._t("Date.DAY", " day");
}
if($ago < 86400*365) {
$span = round($ago/86400/30);
return ($span != 1) ? "{$span}"._t("Date.MONTHS", " months") : "{$span}"._t("Date.MONTH", " month");
return ($span != 1) ? "{$span} "._t("Date.MONTHS", " months") : "{$span} "._t("Date.MONTH", " month");
}
if($ago > 86400*365) {
$span = round($ago/86400/365);
return ($span != 1) ? "{$span}"._t("Date.YEARS", " years") : "{$span}"._t("Date.YEAR", " year");
return ($span != 1) ? "{$span} "._t("Date.YEARS", " years") : "{$span} "._t("Date.YEAR", " year");
}
}
}

View File

@ -43,9 +43,8 @@ class ForeignKey extends Int {
$field = new FileField($relationName, $title, $this->value);
}
} else {
$objs = DataObject::get($hasOneClass);
$titleField = (singleton($hasOneClass)->hasField('Title')) ? "Title" : "Name";
$map = ($objs) ? $objs->toDropdownMap("ID", $titleField) : false;
$map = new SQLMap(singleton($hasOneClass)->extendedSQL(), "ID", $titleField);
$field = new DropdownField($this->name, $title, $map, null, null, ' ');
}

View File

@ -22,12 +22,8 @@ class PrimaryKey extends Int {
}
public function scaffoldFormField($title = null, $params = null) {
$objs = DataObject::get($this->object->class);
$titleField = (singleton($this->object->class)->hasField('Title')) ? "Title" : "Name";
$map = ($objs) ? $objs->toDropdownMap("ID", $titleField) : false;
$titleField = ($this->object->hasField('Title')) ? "Title" : "Name";
$map = new SQLMap($this->object->extendedSQL(), "ID", $titleField);
return new DropdownField($this->name, $title, $map, null, null, ' ');
}
}

View File

@ -19,16 +19,24 @@ class Text extends DBField {
return ($this->value || $this->value == '0');
}
//useed for search results show only limited contents
function LimitWordCount($numWords = 26) {
$this->value = Convert::xml2raw($this->value);
$ret = explode(" ", $this->value, $numWords);
/**
* Limit this field's content by a number of words.
* CAUTION: This is not XML safe. Please use
* {@link LimitWordCountXML()} instead.
*
* @param int $numWords Number of words to limit by
* @param string $add Ellipsis to add to the end of truncated string
* @return string
*/
function LimitWordCount($numWords = 26, $add = '...') {
$this->value = trim(Convert::xml2raw($this->value));
$ret = explode(' ', $this->value, $numWords + 1);
if( Count($ret) < $numWords-1 ){
$ret=$this->value;
}else{
if(count($ret) <= $numWords - 1) {
$ret = $this->value;
} else {
array_pop($ret);
$ret=implode(" ", $ret)."...";
$ret = implode(' ', $ret) . $add;
}
return $ret;
@ -45,11 +53,23 @@ class Text extends DBField {
return HTTP::absoluteURLs($this->value);
}
/**
* Limit this field's content by a number of characters.
* CAUTION: Does not take into account HTML tags, so it
* has the potential to return malformed HTML.
*
* @param int $limit Number of characters to limit by
* @param string $add Ellipsis to add to the end of truncated string
* @return string
*/
function LimitCharacters($limit = 20, $add = "...") {
$value = trim($this->value);
return (strlen($value) > $limit) ? substr($value, 0, $limit) . $add : $value;
}
/**
* @deprecated. Please use {@link LimitWordCount()}
*/
function LimitWordCountPlainText($numWords = 26) {
$ret = $this->LimitWordCount( $numWords );
// Use LimitWordCountXML() instead!
@ -57,11 +77,18 @@ class Text extends DBField {
return $ret;
}
function LimitWordCountXML( $numWords = 26 ) {
$ret = $this->LimitWordCount( $numWords );
$ret = Convert::raw2xml($ret);
return $ret;
/**
* Limit the number of words of the current field's
* content. This is XML safe, so characters like &
* are converted to &amp;
*
* @param int $numWords Number of words to limit by
* @param string $add Ellipsis to add to the end of truncated string
* @return string
*/
function LimitWordCountXML($numWords = 26, $add = '...') {
$ret = $this->LimitWordCount($numWords, $add);
return Convert::raw2xml($ret);
}
/**
@ -221,12 +248,19 @@ class Text extends DBField {
}
}
/**
* Perform context searching to give some context to searches, optionally
* highlighting the search term.
*
* @param int $characters Number of characters in the summary
* @param boolean $string Supplied string ("keywords")
* @param boolean $striphtml Strip HTML?
* @param boolean $highlight Add a highlight <span> element around search query?
* @return string
*/
function ContextSummary($characters = 500, $string = false, $striphtml = true, $highlight = true) {
if(!$string) {
// If no string is supplied, use the string from a SearchForm
$string = $_REQUEST['Search'];
}
if(!$string) $string = $_REQUEST['Search']; // Use the default "Search" request variable (from SearchForm)
// Remove HTML tags so we don't have to deal with matching tags
$text = $striphtml ? $this->NoHTML() : $this->value;
@ -236,7 +270,6 @@ class Text extends DBField {
// We want to search string to be in the middle of our block to give it some context
$position = max(0, $position - ($characters / 2));
if($position > 0) {
// We don't want to start mid-word
$position = max((int) strrpos(substr($text, 0, $position), ' '), (int) strrpos(substr($text, 0, $position), "\n"));
@ -244,13 +277,20 @@ class Text extends DBField {
$summary = substr($text, $position, $characters);
$stringPieces = explode(' ', $string);
if($highlight) {
// Add a span around all occurences of the search term
$summary = str_ireplace($string, "<span class=\"highlight\">$string</span>", $summary);
// Add a span around all key words from the search term as well
if($stringPieces) {
foreach($stringPieces as $stringPiece) {
$summary = str_ireplace($stringPiece, "<span class=\"highlight\">$stringPiece</span>", $summary);
}
}
}
// trim it, because if we counted back and found a space then there will be an extra
// space at the front
return trim($summary);
}

View File

@ -105,6 +105,10 @@ form button.minorAction {
/**
* Messages
*/
form .message.notice {
background-color: #FCFFDF;
border-color: #FF9300;
}
form .message {
margin: 1em 0;
padding: 0.5em;

View File

@ -16,6 +16,38 @@ class DevelopmentAdmin extends Controller {
'$Action//$Action/$ID' => 'handleAction',
);
function init() {
parent::init();
// check for valid url mapping
// lacking this information can cause really nasty bugs,
// e.g. when running Director::test() from a FunctionalTest instance
global $_FILE_TO_URL_MAPPING;
if(Director::is_cli()) {
if(isset($_FILE_TO_URL_MAPPING)) {
$fullPath = $testPath = $_SERVER['SCRIPT_FILENAME'];
while($testPath && $testPath != "/") {
$matched = false;
if(isset($_FILE_TO_URL_MAPPING[$testPath])) {
$matched = true;
break;
}
$testPath = dirname($testPath);
}
if(!$matched) {
echo 'Warning: You probably want to define '.
'an entry in $_FILE_TO_URL_MAPPING that covers "' . Director::baseFolder() . '"' . "\n";
}
}
else {
echo 'Warning: You probably want to define $_FILE_TO_URL_MAPPING in '.
'your _ss_environment.php as instructed on the "sake" page of the doc.silverstripe.com wiki' . "\n";
}
}
}
function index() {
$actions = array(
"build" => "Build/rebuild this environment (formerly db/build). Call this whenever you have updated your project sources",

View File

@ -19,11 +19,12 @@ class TaskRunner extends Controller {
$renderer->writeHeader();
$renderer->writeInfo("Sapphire Development Tools: Tasks", Director::absoluteBaseURL());
$base = Director::baseURL();
if(strpos($base,-1) != '/') $base .= '/';
echo "<ul>";
foreach($tasks as $task) {
echo "<li>";
echo "<a href=\"" . $task['class'] . "\">" . $task['title'] . "</a><br />";
echo "<a href=\"{$base}dev/tasks/" . $task['class'] . "\">" . $task['title'] . "</a><br />";
echo "<span class=\"description\">" . $task['description'] . "</span>";
echo "</li>\n";
}
@ -48,6 +49,7 @@ class TaskRunner extends Controller {
$task = new $taskName();
if ($task->isEnabled()) $task->run($request);
else echo "<p>{$title} is disabled</p>";
} else {
echo "Build task '$taskName' not found.";
if(class_exists($taskName)) echo " It isn't a subclass of BuildTask.";

View File

@ -322,7 +322,7 @@ class Folder extends File {
$fileList->setFolder($this);
$fileList->setPopupCaption(_t('Folder.VIEWEDITASSET', "View/Edit Asset"));
$nameField = ($this->ID && $this->ID != "root") ? new TextField("Name", "Folder Name") : new HiddenField("Name");
$nameField = ($this->ID && $this->ID != "root") ? new TextField("Name", _t('Folder.TITLE')) : new HiddenField("Name");
if( $this->canEdit() ) {
$deleteButton = new InlineFormAction('deletemarked',_t('Folder.DELSELECTED','Delete selected files'), 'delete');
$deleteButton->includeDefaultJS(false);

View File

@ -16,6 +16,7 @@ HTML;
}
function Field() {
Requirements::javascript(THIRDPARTY_DIR . "/behaviour.js");
Requirements::javascript(THIRDPARTY_DIR . "/calendar/calendar.js");
Requirements::javascript(THIRDPARTY_DIR . "/calendar/lang/calendar-en.js");
Requirements::javascript(THIRDPARTY_DIR . "/calendar/calendar-setup.js");

View File

@ -966,7 +966,10 @@ class ComplexTableField_Popup extends Form {
$actions = new FieldSet();
if(!$readonly) {
$actions->push(
$saveAction = new FormAction("saveComplexTableField", "Save")
$saveAction = new FormAction(
"saveComplexTableField",
_t('CMSMain.SAVE')
)
);
$saveAction->addExtraClass('save');
}

View File

@ -8,11 +8,11 @@
class CountryDropdownField extends DropdownField {
protected $defaultToVisitorCountry = true;
function __construct($name, $title, $source = null, $value = "", $form=null) {
function __construct($name, $title = null, $source = null, $value = "", $form=null) {
if(!is_array($source)) $source = Geoip::getCountryDropDown();
if(!$value) $value = Geoip::visitor_country();
parent::__construct($name, $title, $source, $value, $form);
parent::__construct($name, ($title===null) ? $name : $title, $source, $value, $form);
}
function defaultToVisitorCountry($val) {

View File

@ -71,6 +71,11 @@ class DropdownField extends FormField {
$source = $this->getSource();
if($source) {
// For SQLMap sources, the empty string needs to be added specially
if(is_object($source) && $this->emptyString) {
$options .= $this->createTag('option', array('value' => ''), $this->emptyString);
}
foreach($source as $value => $title) {
$selected = ($value == $this->value) ? 'selected' : null;
if($selected && $this->value != 0) {

View File

@ -201,6 +201,22 @@ class FieldSet extends DataObjectSet {
return false;
}
/**
* Rename the title of a particular field name in this set.
*
* @param string $fieldName Name of field to rename title of
* @param string $newFieldTitle New title of field
* @return boolean
*/
function renameField($fieldName, $newFieldTitle) {
$field = $this->dataFieldByName($fieldName);
if(!$field) return false;
$field->setTitle($newFieldTitle);
return $field->Title() == $newFieldTitle;
}
/**
* @return boolean
*/
@ -456,25 +472,8 @@ class FieldSet extends DataObjectSet {
*/
function makeFieldReadonly($field) {
$fieldName = ($field instanceof FormField) ? $field->Name() : $field;
// Iterate on items, looking for the applicable field
foreach($this->items as $i => $item) {
if($item->isComposite()) {
$item->makeFieldReadonly($fieldName);
} else {
// Once it's found, use FormField::transform to turn the field into a readonly version of itself.
if($item->Name() == $fieldName) {
$this->items[$i] = $item->transform(new ReadonlyTransformation());
// Clear an internal cache
$this->sequentialSet = null;
// A true results indicates that the field was foudn
return true;
}
}
}
return false;
$srcField = $this->dataFieldByName($fieldName);
$this->replaceField($fieldName, $srcField->performReadonlyTransformation());
}
/**

View File

@ -67,7 +67,10 @@ class FormScaffolder extends Object {
$fields = new FieldSet();
// tabbed or untabbed
if($this->tabbed) $fields->push(new TabSet("Root", new Tab("Main")));
if($this->tabbed) {
$fields->push(new TabSet("Root", $mainTab = new Tab("Main")));
$mainTab->setTitle(_t('SiteTree.TABMAIN', "Main"));
}
// add database fields
foreach($this->obj->db() as $fieldName => $fieldType) {

View File

@ -68,33 +68,24 @@ class HasManyComplexTableField extends ComplexTableField {
}
function sourceItems() {
if($this->sourceItems)
return $this->sourceItems;
if($this->sourceItems) return $this->sourceItems;
$limitClause = '';
if(isset($_REQUEST[ 'ctf' ][ $this->Name() ][ 'start' ]) && is_numeric($_REQUEST[ 'ctf' ][ $this->Name() ][ 'start' ]))
if(isset($_REQUEST['ctf'][$this->Name()]['start']) && is_numeric($_REQUEST['ctf'][$this->Name()]['start'])) {
$limitClause = $_REQUEST[ 'ctf' ][ $this->Name() ][ 'start' ] . ", $this->pageSize";
else
} else {
$limitClause = "0, $this->pageSize";
}
$dataQuery = $this->getQuery($limitClause);
$records = $dataQuery->execute();
$items = new DataObjectSet();
foreach($records as $record) {
if(! get_class($record))
$record = new DataObject($record);
$items->push($record);
}
$sourceClass = $this->sourceClass;
$dataobject = new $sourceClass();
$items = $dataobject->buildDataObjectSet($records, 'DataObjectSet');
$dataQuery = $this->getQuery();
$records = $dataQuery->execute();
$unpagedItems = new DataObjectSet();
foreach($records as $record) {
if(! get_class($record))
$record = new DataObject($record);
$unpagedItems->push($record);
}
$this->unpagedSourceItems = $unpagedItems;
$this->unpagedSourceItems = $dataobject->buildDataObjectSet($records, 'DataObjectSet');
$this->totalCount = ($this->unpagedSourceItems) ? $this->unpagedSourceItems->TotalItems() : null;
@ -133,9 +124,11 @@ class HasManyComplexTableField extends ComplexTableField {
function ExtraData() {
$items = array();
foreach($this->unpagedSourceItems as $item) {
if($item->{$this->joinField} == $this->controller->ID)
$items[] = $item->ID;
if($this->unpagedSourceItems) {
foreach($this->unpagedSourceItems as $item) {
if($item->{$this->joinField} == $this->controller->ID)
$items[] = $item->ID;
}
}
$list = implode(',', $items);
$inputId = $this->id() . '_' . $this->htmlListEndName;

View File

@ -26,11 +26,7 @@ class HtmlEditorField extends TextareaField {
*/
function Field() {
Requirements::javascript(MCE_ROOT . "tiny_mce_src.js");
Requirements::javascript(THIRDPARTY_DIR . "/tiny_mce_improvements.js");
Requirements::css('cms/css/TinyMCEImageEnhancement.css');
Requirements::javascript('jsparty/SWFUpload/SWFUpload.js');
Requirements::javascript('cms/javascript/Upload.js');
Requirements::javascript('cms/javascript/TinyMCEImageEnhancement.js');
Requirements::javascript(SAPPHIRE_DIR . '/javascript/HtmlEditorField.js');
// Don't allow unclosed tags - they will break the whole application ;-)
$cleanVal = $this->value;
@ -353,6 +349,9 @@ class HtmlEditorField_Toolbar extends RequestHandler {
* @return Form
*/
function LinkForm() {
Requirements::javascript(THIRDPARTY_DIR . "/behaviour.js");
Requirements::javascript(THIRDPARTY_DIR . "/tiny_mce_improvements.js");
$form = new Form(
$this->controller,
"{$this->name}/LinkForm",
@ -396,6 +395,10 @@ class HtmlEditorField_Toolbar extends RequestHandler {
* @return Form
*/
function ImageForm() {
Requirements::javascript(THIRDPARTY_DIR . "/behaviour.js");
Requirements::javascript(THIRDPARTY_DIR . "/tiny_mce_improvements.js");
Requirements::css('cms/css/TinyMCEImageEnhancement.css');
Requirements::javascript('cms/javascript/TinyMCEImageEnhancement.js');
Requirements::javascript(THIRDPARTY_DIR . '/SWFUpload/SWFUpload.js');
Requirements::javascript(CMS_DIR . '/javascript/Upload.js');
@ -452,6 +455,8 @@ class HtmlEditorField_Toolbar extends RequestHandler {
}
function FlashForm() {
Requirements::javascript(THIRDPARTY_DIR . "/behaviour.js");
Requirements::javascript(THIRDPARTY_DIR . "/tiny_mce_improvements.js");
Requirements::javascript(THIRDPARTY_DIR . '/SWFUpload/SWFUpload.js');
Requirements::javascript(CMS_DIR . '/javascript/Upload.js');

View File

@ -1,11 +1,5 @@
<?php
/**
* @package sapphire
* @subpackage misc
*/
/**
* Routines for DNS to country resolution
*
@ -22,8 +16,9 @@ class Geoip extends Object {
public static $default_country_code = false;
/** ISO 3166 Country Codes **/
/**
* ISO 3166 Country Codes
*
* Includes additional codes for Europe,
* Asia Pacific Region,Anonymous Proxies
* & Satellite Provider.
@ -275,52 +270,44 @@ class Geoip extends Object {
'ZR' => "Zaire",
'ZW' => "Zimbabwe"
);
/**
* Returns the country code of the person given an IP
* Returns the country code of the person given an IP.
*
* @param address - The IP address of the user,
* @param codeOnly - Returns just the code of the IP instead of array( $CountryCode => $CountryName)
*/
static function ip2country($address, $codeOnly = false) {
// Detect internal networks - this is us, so we're NZ
if(substr($address,0,7)=="192.168" || substr($address,0,4)=="127.") {
$code = "NZ";
if(substr($address, 0, 7) == "192.168" || substr($address,0,4) == "127.") {
$code = 'NZ';
} else {
$cmd = "geoiplookup ".escapeshellarg($address);
$cmd = 'geoiplookup ' . escapeshellarg($address);
exec($cmd, $result, $code);
// Note: At time of writing, $result is always zero for this program
if ($code == 127) {
return false;
}
if ($result == false) {
// don't return any error - @see http://open.silverstripe.com/ticket/1458
//user_error("ip2country($address): geoiplookup executable returned nothing.", E_USER_NOTICE);
return false;
}
if($code == 127) return false;
if($result == false) return false;
// Always returns one line of code, e.g. :
// Geoip Country Edition: GB, United Kingdom
// NZ
$country = $result[0];
$start = strpos($country, ':');
if ($start) $start+=2;
if($start) $start += 2;
$code = substr($country, $start, 2); // skip space
}
if ($code == 'IP' || $code == '--') {
if (self::$default_country_code) $code = self::$default_country_code;
if($code == 'IP' || $code == '--') {
if(self::$default_country_code) $code = self::$default_country_code;
else return false;
}
if(!$codeOnly) {
$name = substr($country, $start+4);
if (! $name) $name = CountryCode2Name($code);
if(!$name) $name = $this->countryCode2name($code);
return array('code' => $code, 'name' => $name);
} else {
@ -358,7 +345,7 @@ class Geoip extends Object {
foreach ($checks as $url => $expectedResponse) {
$response = ip2country($url);
if (!$response && $expectedResponse) {
if(!$response && $expectedResponse) {
user_error("ip2country_check failed sanity check: ip2country($url) returned false. Expected code: '$expectedResponse'", E_USER_WARNING);
$status = false;
} elseif ($response != $expectedResponse) {
@ -372,16 +359,10 @@ class Geoip extends Object {
/**
* Returns the country name from the appropriate code.
* @return null|string String if country found, null if none found
*/
static function countryCode2name($code) {
$name = Geoip::$iso_3166_countryCodes[ $code ];
if (! $name ) {
if (! $code )
trigger_error("countryCode2name() Failed to find a country name as no code was provided.", E_USER_WARNING);
else
trigger_error("countryCode2name() Failed to find a country name matching the ISO 3166 code '$code'", E_USER_WARNING);
}
static function countryCode2name($code) {
$name = isset(Geoip::$iso_3166_countryCodes[$code]) ? Geoip::$iso_3166_countryCodes[$code] : null;
return $name;
}

View File

@ -1,5 +1,5 @@
if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
console.error('Class ss.i18n not defined');
if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined');
} else {
ss.i18n.addDictionary('en_US', {
'VALIDATOR.FIELDREQUIRED': 'Please fill out "%s", it is required.',

15
javascript/lang/fr_FR.js Normal file
View File

@ -0,0 +1,15 @@
if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
console.error('Class ss.i18n not defined');
} else {
ss.i18n.addDictionary('fr_FR', {
'VALIDATOR.FIELDREQUIRED': 'Veuillez remplir "%s", c\'est un champ requis.',
'HASMANYFILEFIELD.UPLOADING': 'Uploading... %s',
'TABLEFIELD.DELETECONFIRMMESSAGE': 'Etes-vous sûr de vouloir supprimer cet enregistrement ?',
'LOADING': 'chargement...',
'UNIQUEFIELD.SUGGESTED': "Changez la valeur de '%s' : %s",
'UNIQUEFIELD.ENTERNEWVALUE': 'You devez saisir une nouvelle valeur pou ce champ',
'UNIQUEFIELD.CANNOTLEAVEEMPTY': 'Ce champ ne peut être laissé vide',
'RESTRICTEDTEXTFIELD.CHARCANTBEUSED': "Le character '%s' ne peut être utilisé dans ce champ",
'UPDATEURL.CONFIRM': 'Voulez-vous que je change l\'URL en:\n\n%s/\n\nCliquez Ok pour changer l\'URL, cliquez Annuler pour la laisser à:\n\n%s'
});
}

View File

@ -60,8 +60,19 @@ $lang['de_DE']['BBCodeParser']['UNORDEREDEXAMPLE1'] = 'Ungeordneter Eintrag 1';
$lang['de_DE']['BBCodeParser']['UNORDEREDEXAMPLE2'] = 'Ungeordneter Eintrag 2';
$lang['de_DE']['ChangePasswordEmail.ss']['CHANGEPASSWORDTEXT1'] = 'Sie haben ihr Passwort geändert für';
$lang['de_DE']['ChangePasswordEmail.ss']['CHANGEPASSWORDTEXT2'] = 'Sie können nun folgende Angaben benutzen um sich einzuloggen';
$lang['de_DE']['ChangePasswordEmail.ss']['EMAIL'] = 'E-Mail';
$lang['de_DE']['ChangePasswordEmail.ss']['HELLO'] = 'Hi';
$lang['de_DE']['ChangePasswordEmail.ss']['PASSWORD'] = 'Passwort';
$lang['de_DE']['CMSMain']['DELETE'] = 'Von Entwurf-Seite löschen';
$lang['de_DE']['CollectionController.ss']['ADDNEWRECORD'] = 'Neuen Eintrag hinzufügen';
$lang['de_DE']['CollectionController.ss']['SEARCH'] = 'Suche';
$lang['de_DE']['CollectionController_Results.ss']['NEXT'] = 'nächster';
$lang['de_DE']['CollectionController_Results.ss']['NORESULTSFOUND'] = 'Keine Einträge gefunden';
$lang['de_DE']['CollectionController_Results.ss']['PREV'] = 'vorheriger';
$lang['de_DE']['CollectionController_Results.ss']['RESULTS'] = 'Ergebnisse';
$lang['de_DE']['ComplexTableField']['CLOSEPOPUP'] = 'Popup schließen';
$lang['de_DE']['ComplexTableField.ss']['ADDITEM'] = 'Hinzufügen';
$lang['de_DE']['ComplexTableField.ss']['CSVEXPORT'] = 'CSV Export';
$lang['de_DE']['ComplexTableField.ss']['DELETE'] = 'löschen';
$lang['de_DE']['ComplexTableField.ss']['DELETEROW'] = 'Zeile löschen';
$lang['de_DE']['ComplexTableField.ss']['EDIT'] = 'ändern';
@ -95,6 +106,8 @@ $lang['de_DE']['CreditCardField']['VALIDATIONJS1'] = 'Bitte versichern Sie sich,
$lang['de_DE']['CreditCardField']['VALIDATIONJS2'] = 'Kreditkartenummer richtig';
$lang['de_DE']['CurrencyField']['CURRENCYSYMBOL'] = '€';
$lang['de_DE']['CurrencyField']['VALIDATIONJS'] = 'Bitte geben Sie eine gültige Währung ein.';
$lang['de_DE']['DataObject']['PLURALNAME'] = 'DataObjects';
$lang['de_DE']['DataObject']['SINGULARNAME'] = 'DataObject';
$lang['de_DE']['DataReport']['EXPORTCSV'] = 'Ins CSV exportieren.';
$lang['de_DE']['Date']['AGO'] = 'vor';
$lang['de_DE']['Date']['AWAY'] = 'weg';
@ -108,6 +121,8 @@ $lang['de_DE']['Date']['MONTH'] = 'Monat';
$lang['de_DE']['Date']['MONTHS'] = 'Monat';
$lang['de_DE']['Date']['SEC'] = 'Sekunden';
$lang['de_DE']['Date']['SECS'] = 'Sekunden';
$lang['de_DE']['Date']['TIMEDIFFAGO'] = 'vor %s';
$lang['de_DE']['Date']['TIMEDIFFAWAY'] = 'noch %s';
$lang['de_DE']['Date']['YEAR'] = 'Jahr';
$lang['de_DE']['Date']['YEARS'] = 'Jahre';
$lang['de_DE']['DateField']['NODATESET'] = 'Kein Datum gesetzt.';
@ -145,8 +160,12 @@ $lang['de_DE']['ErrorPage']['505'] = '505 - HTTP Version wird nicht unterstützt
$lang['de_DE']['ErrorPage']['CODE'] = 'Fehlercode';
$lang['de_DE']['ErrorPage']['DEFAULTERRORPAGECONTENT'] = '<p>Entschuldigung, möglicherweise versuchen Sie eine Seite zu erreichen die nicht existiert.</p><p>Bitte überprüfen Sie die Schreibweise der URL die Sie versucht haben zu erreichen und versuchen Sie es noch einmal.</p>';
$lang['de_DE']['ErrorPage']['DEFAULTERRORPAGETITLE'] = 'Seite nicht gefunden';
$lang['de_DE']['ErrorPage']['PLURALNAME'] = 'Fehlerseiten';
$lang['de_DE']['ErrorPage']['SINGULARNAME'] = 'Fehlerseite';
$lang['de_DE']['File']['NOFILESIZE'] = 'Dateigröße ist 0 bytes';
$lang['de_DE']['FileIFrameField']['NOTEADDFILES'] = 'Sie können Dateien hinzufügen sobald Sie das erste mal gespeichert haben';
$lang['de_DE']['File']['PLURALNAME'] = 'Dateien';
$lang['de_DE']['File']['SINGULARNAME'] = 'Datei';
$lang['de_DE']['FileIframeField']['NOTEADDFILES'] = 'Sie können Dateien hinzufügen sobald Sie das erste mal gespeichert haben';
$lang['de_DE']['Folder']['CREATED'] = 'Zuerst hochgeladen';
$lang['de_DE']['Folder']['DELETEUNUSEDTHUMBNAILS'] = 'löschen ungebrauchte Vorschaubilder';
$lang['de_DE']['Folder']['DELSELECTED'] = 'Löschen selektierte Dateien';
@ -154,6 +173,8 @@ $lang['de_DE']['Folder']['DETAILSTAB'] = 'Detail';
$lang['de_DE']['Folder']['FILENAME'] = 'Dateiname';
$lang['de_DE']['Folder']['FILESTAB'] = 'Dateien';
$lang['de_DE']['Folder']['LASTEDITED'] = 'Zuletzt geändert';
$lang['de_DE']['Folder']['PLURALNAME'] = 'Ordner';
$lang['de_DE']['Folder']['SINGULARNAME'] = 'Ordner';
$lang['de_DE']['Folder']['TITLE'] = 'Titel';
$lang['de_DE']['Folder']['TYPE'] = 'Typ';
$lang['de_DE']['Folder']['UNUSEDFILESTAB'] = 'ungebrauchte Dateien';
@ -185,6 +206,10 @@ $lang['de_DE']['Form']['VALIDATOR'] = 'Prüfer';
$lang['de_DE']['Form']['VALIDCURRENCY'] = 'Bitte geben Sie eine gültige Währung an';
$lang['de_DE']['FormField']['NONE'] = 'keine';
$lang['de_DE']['GhostPage']['NOLINKED'] = 'Diese Stellvertreter-Seite ist nicht verlinkt.';
$lang['de_DE']['GhostPage']['PLURALNAME'] = 'Kopien';
$lang['de_DE']['GhostPage']['SINGULARNAME'] = 'Kopie';
$lang['de_DE']['Group']['PLURALNAME'] = 'Gruppen';
$lang['de_DE']['Group']['SINGULARNAME'] = 'Gruppe';
$lang['de_DE']['GSTNumberField']['VALIDATION'] = 'Bitte geben Sie eine gültige GST Nummer ein';
$lang['de_DE']['GSTNumberField']['VALIDATIONJS'] = 'Bitte geben Sie eine korrekte Steuernummer ein.';
$lang['de_DE']['HtmlEditorField']['ALTTEXT'] = 'Beschreibung';
@ -230,6 +255,7 @@ $lang['de_DE']['HtmlEditorField']['FORMATH4'] = 'Überschrift 4';
$lang['de_DE']['HtmlEditorField']['FORMATH5'] = 'Überschrift 5';
$lang['de_DE']['HtmlEditorField']['FORMATH6'] = 'Überschrift 6';
$lang['de_DE']['HtmlEditorField']['FORMATP'] = 'Paragraph';
$lang['de_DE']['HtmlEditorField']['FORMATPRE'] = 'Präformatiert';
$lang['de_DE']['HtmlEditorField']['HR'] = 'Horizontale Linie einfügen';
$lang['de_DE']['HtmlEditorField']['IMAGE'] = 'Bild';
$lang['de_DE']['HtmlEditorField']['IMAGEDIMENSIONS'] = 'Dimensionen';
@ -264,6 +290,8 @@ $lang['de_DE']['HtmlEditorField']['UNLINK'] = 'Verweis entfernen';
$lang['de_DE']['HtmlEditorField']['UPLOAD'] = 'hochladen';
$lang['de_DE']['HtmlEditorField']['URL'] = 'URL';
$lang['de_DE']['HtmlEditorField']['VISUALAID'] = 'Hinweistexte anzeigen/verbergen';
$lang['de_DE']['Image']['PLURALNAME'] = 'Bilder';
$lang['de_DE']['Image']['SINGULARNAME'] = 'Bild';
$lang['de_DE']['ImageField']['NOTEADDIMAGES'] = 'Sie können Bilder hinzufügen nachdem Sie das erste mal gespeichert haben';
$lang['de_DE']['ImageUplaoder']['ONEFROMFILESTORE'] = 'mit einem aus dem Dateispeicher';
$lang['de_DE']['ImageUploader']['ATTACH'] = '%s anhängen';
@ -274,6 +302,8 @@ $lang['de_DE']['ImageUploader']['ONEFROMCOMPUTER'] = 'mit einer von Ihrem Comput
$lang['de_DE']['ImageUploader']['REALLYDELETE'] = 'Möchten Sie wirklich %s löschen?';
$lang['de_DE']['ImageUploader']['REPLACE'] = 'Ersetzen';
$lang['de_DE']['Image_iframe.ss']['TITLE'] = 'Iframe Bilder hochladen';
$lang['de_DE']['LoginAttempt']['PLURALNAME'] = 'Loginversuche';
$lang['de_DE']['LoginAttempt']['SINGULARNAME'] = 'Login-Versuch';
$lang['de_DE']['Member']['ADDRESS'] = 'Adresse';
$lang['de_DE']['Member']['BUTTONCHANGEPASSWORD'] = 'Passwort ändern';
$lang['de_DE']['Member']['BUTTONLOGIN'] = 'Einloggen';
@ -303,7 +333,10 @@ $lang['de_DE']['Member']['PASSWORD'] = 'Passwort';
$lang['de_DE']['Member']['PASSWORDCHANGED'] = 'Ihr Passwort wurde geändert und eine Kopie wurde per Email an Sie versendet';
$lang['de_DE']['Member']['PERSONALDETAILS'] = 'Persönliche Daten';
$lang['de_DE']['Member']['PHONE'] = 'Telefon';
$lang['de_DE']['Member']['PLURALNAME'] = 'Benutzer';
$lang['de_DE']['Member']['REMEMBERME'] = 'Für das nächste mal merken?';
$lang['de_DE']['Member']['SECURITYGROUPS'] = 'Sicherheitsgruppen';
$lang['de_DE']['Member']['SINGULARNAME'] = 'Benutzer';
$lang['de_DE']['Member']['SUBJECTPASSWORDCHANGED'] = 'Ihr Passwort wurde geändert';
$lang['de_DE']['Member']['SUBJECTPASSWORDRESET'] = 'Ihr Link zur Passwortrücksetzung';
$lang['de_DE']['Member']['SURNAME'] = 'Nachname';
@ -312,19 +345,32 @@ $lang['de_DE']['Member']['VALIDATIONMEMBEREXISTS'] = 'Es gibt bereits ein Mitgli
$lang['de_DE']['Member']['WELCOMEBACK'] = 'Willkommen zurück %s';
$lang['de_DE']['Member']['YOUROLDPASSWORD'] = 'Ihr alten Passwort';
$lang['de_DE']['MemberAuthenticator']['TITLE'] = 'Email &amp; Passwort';
$lang['de_DE']['MemberPassword']['PLURALNAME'] = 'Benutzerpasswörter';
$lang['de_DE']['MemberPassword']['SINGULARNAME'] = 'Benutzerpasswort';
$lang['de_DE']['NumericField']['VALIDATION'] = '%s ist keine Zahl, nur Zahlen dürfen in dieses Feld eingetragen werden';
$lang['de_DE']['NumericField']['VALIDATIONJS'] = 'ist keine Ziffer. Dieses Feld akzeptiert nur Ziffern.';
$lang['de_DE']['Page']['PLURALNAME'] = 'Seiten';
$lang['de_DE']['Page']['SINGULARNAME'] = 'Seite';
$lang['de_DE']['Permission']['FULLADMINRIGHTS'] = 'Unbeschränkte Administratorenrechte';
$lang['de_DE']['Permission']['PERMSDEFINED'] = 'Die folgenden Berechtigungen sind definiert:';
$lang['de_DE']['Permission']['PLURALNAME'] = 'Zugriffsberechtigungen';
$lang['de_DE']['Permission']['SINGULARNAME'] = 'Zugriffsberechtigung';
$lang['de_DE']['PhoneNumberField']['VALIDATION'] = 'Bitte geben Sie eine gültige Telefonnummer ein';
$lang['de_DE']['QueuedEmail']['PLURALNAME'] = 'Emails';
$lang['de_DE']['QueuedEmail']['SINGULARNAME'] = 'Zeitverzögerte Email';
$lang['de_DE']['RecordController']['DELETESUCCESS'] = 'Eintrag erfolgreich gelöscht';
$lang['de_DE']['RecordController']['SAVESUCCESS'] = 'Eintrag gespeichert';
$lang['de_DE']['RedirectorPage']['HASBEENSETUP'] = 'Eine Weiterleitungsseite wurde erstellt ohne das eine Weiterleitung definiert wurde.';
$lang['de_DE']['RedirectorPage']['HEADER'] = 'Diese Seite wird Nutzer auf eine andere Seite weiterleiten';
$lang['de_DE']['RedirectorPage']['OTHERURL'] = 'Andere Webseiten URL';
$lang['de_DE']['RedirectorPage']['PLURALNAME'] = 'Weiterleitungen';
$lang['de_DE']['RedirectorPage']['REDIRECTTO'] = 'Weiterleiten zu';
$lang['de_DE']['RedirectorPage']['REDIRECTTOEXTERNAL'] = 'Andere Website';
$lang['de_DE']['RedirectorPage']['REDIRECTTOPAGE'] = 'Eine Seite auf Ihrer Website';
$lang['de_DE']['RedirectorPage']['SINGULARNAME'] = 'Weiterleitung';
$lang['de_DE']['RedirectorPage']['YOURPAGE'] = 'Seite auf Ihrer Website';
$lang['de_DE']['RelationComplexTableField.ss']['ADD'] = 'Hinzufügen';
$lang['de_DE']['RelationComplexTableField.ss']['CSVEXPORT'] = 'CSV Export';
$lang['de_DE']['RelationComplexTableField.ss']['DELETE'] = 'löschen';
$lang['de_DE']['RelationComplexTableField.ss']['EDIT'] = 'editieren';
$lang['de_DE']['RelationComplexTableField.ss']['NOTFOUND'] = 'Keine Artikel gefunden';
@ -380,7 +426,7 @@ $lang['de_DE']['SiteTree']['ALLOWCOMMENTS'] = 'Kommentare auf dieser Seite erlau
$lang['de_DE']['SiteTree']['APPEARSVIRTUALPAGES'] = 'Dieser Inhalt erscheint auch auf den virtuellen Seiten im %s Bereich.';
$lang['de_DE']['SiteTree']['BUTTONCANCELDRAFT'] = 'Verwerfe Entwurfsänderungen';
$lang['de_DE']['SiteTree']['BUTTONCANCELDRAFTDESC'] = 'Löschen Sie Ihren Entwurf und kehren Sie zur derzeit veröffentlichten Seite zurück.';
$lang['de_DE']['SiteTree']['BUTTONSAVEPUBLISH'] = 'Sichern & Veröffentlichen';
$lang['de_DE']['SiteTree']['BUTTONSAVEPUBLISH'] = 'Speichern und Veröffentlichen';
$lang['de_DE']['SiteTree']['BUTTONUNPUBLISH'] = 'Veröffentlichung zurücknehmen';
$lang['de_DE']['SiteTree']['BUTTONUNPUBLISHDESC'] = 'Entferne diese Seite aus der veröffentlichten Website';
$lang['de_DE']['SiteTree']['CHANGETO'] = 'Ändern zu';
@ -416,12 +462,15 @@ $lang['de_DE']['SiteTree']['NOTEUSEASHOMEPAGE'] = 'Diese Seite als "Homepage" f
$lang['de_DE']['SiteTree']['PAGESLINKING'] = 'Die folgenden Seiten verweisen auf diese Seite:';
$lang['de_DE']['SiteTree']['PAGETITLE'] = 'Seiten Name';
$lang['de_DE']['SiteTree']['PAGETYPE'] = 'Seitentyp';
$lang['de_DE']['SiteTree']['PLURALNAME'] = 'Seiten';
$lang['de_DE']['SiteTree']['PRIORITYAUTOSET'] = 'Automatisch, basierend auf der Tiefe der Verschachtelung der Seite';
$lang['de_DE']['SiteTree']['PRIORITYLEASTIMPORTANT'] = 'am wenigsten wichtig';
$lang['de_DE']['SiteTree']['PRIORITYMOSTIMPORTANT'] = 'am wichtigsten';
$lang['de_DE']['SiteTree']['PRIORITYNOTINDEXED'] = 'Nicht indiziert.';
$lang['de_DE']['SiteTree']['REMOVEDFROMDRAFT'] = 'von der Entwurfsseite entfernt ';
$lang['de_DE']['SiteTree']['SHOWINMENUS'] = 'In Menüs anzeigen?';
$lang['de_DE']['SiteTree']['SHOWINSEARCH'] = 'In der Suche anzeigen?';
$lang['de_DE']['SiteTree']['SINGULARNAME'] = 'Seite';
$lang['de_DE']['SiteTree']['TABACCESS'] = 'Zugriff';
$lang['de_DE']['SiteTree']['TABBACKLINKS'] = 'Rückverweise';
$lang['de_DE']['SiteTree']['TABBEHAVIOUR'] = 'Verhalten';
@ -461,5 +510,11 @@ $lang['de_DE']['TypeDropdown']['NONE'] = 'Keine';
$lang['de_DE']['VirtualPage']['CHOOSE'] = 'Wählen Sie eine Seite auf die Sie verweisen möchten';
$lang['de_DE']['VirtualPage']['EDITCONTENT'] = 'drücken Sie hier um den Inhalt abzuändern';
$lang['de_DE']['VirtualPage']['HEADER'] = 'Dies ist eine virtuelle Seite';
$lang['de_DE']['ConfirmedFormAction']['CONFIRMATION'] = 'Sind Sie sicher?';
$lang['de_DE']['VirtualPage']['PLURALNAME'] = 'Virtuelle Seiten';
$lang['de_DE']['VirtualPage']['SINGULARNAME'] = 'Virtuelle Seite';
$lang['de_DE']['Widget']['PLURALNAME'] = 'Widgets';
$lang['de_DE']['Widget']['SINGULARNAME'] = 'Widget';
$lang['de_DE']['WidgetArea']['PLURALNAME'] = 'Widgetbereiche';
$lang['de_DE']['WidgetArea']['SINGULARNAME'] = 'Widgetbereich';
?>

View File

@ -2,6 +2,16 @@
global $lang;
$lang['en_US']['Page']['PLURALNAME'] = array(
'Pags',
50,
'Pural name of the object, used in dropdowns and to generally identify a collection of this object in the interface'
);
$lang['en_US']['Page']['SINGULARNAME'] = array(
'Page',
50,
'Singular name of the object, used in dropdowns and to generally identify a single object in the interface'
);
$lang['en_US']['AdvancedSearchForm']['ALLWORDS'] = 'All Words';
$lang['en_US']['AdvancedSearchForm']['ATLEAST'] = 'At Least One Of the Words';
$lang['en_US']['AdvancedSearchForm']['EXACT'] = 'Exact Phrase';
@ -107,8 +117,6 @@ $lang['en_US']['DataObject']['SINGULARNAME'] = array(
50,
'Singular name of the object, used in dropdowns and to generally identify a single object in the interface'
);
$lang['en_US']['Date']['AGO'] = ' ago';
$lang['en_US']['Date']['AWAY'] = ' away';
$lang['en_US']['Date']['DAY'] = ' day';
$lang['en_US']['Date']['DAYS'] = ' days';
$lang['en_US']['Date']['HOUR'] = ' hour';
@ -119,6 +127,16 @@ $lang['en_US']['Date']['MONTH'] = ' month';
$lang['en_US']['Date']['MONTHS'] = ' months';
$lang['en_US']['Date']['SEC'] = ' sec';
$lang['en_US']['Date']['SECS'] = ' secs';
$lang['en_US']['Date']['TIMEDIFFAGO'] = array(
'%s ago',
PR_MEDIUM,
'Natural language time difference, e.g. 2 hours ago'
);
$lang['en_US']['Date']['TIMEDIFFAWAY'] = array(
'%s away',
PR_MEDIUM,
'Natural language time difference, e.g. 2 hours away'
);
$lang['en_US']['Date']['YEAR'] = ' year';
$lang['en_US']['Date']['YEARS'] = ' years';
$lang['en_US']['DateField']['NODATESET'] = 'No date set';
@ -664,9 +682,11 @@ $lang['en_US']['SiteTree']['BUTTONCANCELDRAFTDESC'] = 'Delete your draft and rev
$lang['en_US']['SiteTree']['BUTTONSAVEPUBLISH'] = 'Save and Publish';
$lang['en_US']['SiteTree']['BUTTONUNPUBLISH'] = 'Unpublish';
$lang['en_US']['SiteTree']['BUTTONUNPUBLISHDESC'] = 'Remove this page from the published site';
$lang['en_US']['SiteTree']['CHANGETO'] = 'Change to';
$lang['en_US']['SiteTree']['CURRENT'] = 'current';
$lang['en_US']['SiteTree']['CURRENTLY'] = 'Currently';
$lang['en_US']['SiteTree']['CHANGETO'] = array(
'Change to "%s"',
PR_MEDIUM,
'Pagetype selection dropdown with class names'
);
$lang['en_US']['SiteTree']['Comments'] = 'Comments';
$lang['en_US']['SiteTree']['Content'] = array(
'Content',

View File

@ -76,9 +76,13 @@ if (isset($_GET['url'])) {
// Lighttpd uses this
} else {
list($url, $query) = explode('?', $_SERVER['REQUEST_URI'], 2);
parse_str($query, $_GET);
if ($_GET) $_REQUEST = array_merge((array)$_REQUEST, (array)$_GET);
if(strpos($_SERVER['REQUEST_URI'],'?') !== false) {
list($url, $query) = explode('?', $_SERVER['REQUEST_URI'], 2);
parse_str($query, $_GET);
if ($_GET) $_REQUEST = array_merge((array)$_REQUEST, (array)$_GET);
} else {
$url = $_SERVER["REQUEST_URI"];
}
}
// Fix glitches in URL generation
@ -96,7 +100,8 @@ require_once("core/model/DB.php");
// Redirect to the installer if no database is selected
if(!isset($databaseConfig) || !isset($databaseConfig['database']) || !$databaseConfig['database']) {
$installURL = dirname(dirname($_SERVER['SCRIPT_NAME'])) . '/install.php';
$s = (isset($_SERVER['SSL']) || (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')) ? 's' : '';
$installURL = "http$s://" . $_SERVER['HTTP_HOST'] . dirname(dirname($_SERVER['SCRIPT_NAME'])) . '/install.php';
header("Location: $installURL");
die();
}

View File

@ -51,8 +51,32 @@ class BBCodeParser extends TextParser {
new ArrayData(array(
"Title" => _t('BBCodeParser.ALIGNEMENT', 'Alignment'),
"Example" => '[align=right]'._t('BBCodeParser.ALIGNEMENTEXAMPLE', 'right aligned').'[/align]'
)),
new ArrayData(array(
"Title" => _t('BBCodeParser.CODE', 'Code Block'),
"Description" => _t('BBCodeParser.CODEDESCRIPTION', 'Unformatted code block'),
"Example" => '[code]'._t('BBCodeParser.CODEEXAMPLE', 'Code block').'[/code]'
)),
new ArrayData(array(
"Title" => _t('BBCodeParser.EMAILLINK', 'Email link'),
"Description" => _t('BBCodeParser.EMAILLINKDESCRIPTION', 'Create link to an email address'),
"Example" => "[email]you@yoursite.com[/email]"
)),
new ArrayData(array(
"Title" => _t('BBCodeParser.EMAILLINK', 'Email link'),
"Description" => _t('BBCodeParser.EMAILLINKDESCRIPTION', 'Create link to an email address'),
"Example" => "[email=you@yoursite.com]Email[/email]"
)),
new ArrayData(array(
"Title" => _t('BBCodeParser.UNORDERED', 'Unordered list'),
"Description" => _t('BBCodeParser.UNORDEREDDESCRIPTION', 'Unordered list'),
"Example" => '[ulist][*]'._t('BBCodeParser.UNORDEREDEXAMPLE1', 'unordered item 1').'[/ulist]'
)),
new ArrayData(array(
"Title" => _t('BBCodeParser.IMAGE', 'Image'),
"Description" => _t('BBCodeParser.IMAGEDESCRIPTION', 'Show an image in your post'),
"Example" => "[img]http://www.website.com/image.jpg[/img]"
)),
new ArrayData(array(
"Title" => _t('BBCodeParser.LINK', 'Website link'),
"Description" => _t('BBCodeParser.LINKDESCRIPTION', 'Link to another website or URL'),
@ -61,37 +85,8 @@ class BBCodeParser extends TextParser {
new ArrayData(array(
"Title" => _t('BBCodeParser.LINK', 'Website link'),
"Description" => _t('BBCodeParser.LINKDESCRIPTION', 'Link to another website or URL'),
"Example" => "[url=http://www.website.com/]Some website[/url]"
)),
new ArrayData(array(
"Title" => _t('BBCodeParser.EMAILLINK', 'Email link'),
"Description" => _t('BBCodeParser.EMAILLINKDESCRIPTION', 'Create link to an email address'),
"Example" => "[email]you@yoursite.com[/email]"
)),
new ArrayData(array(
"Title" => _t('BBCodeParser.EMAILLINK', 'Email link'),
"Description" => _t('BBCodeParser.EMAILLINKDESCRIPTION', 'Create link to an email address'),
"Example" => "[email=you@yoursite.com]email me[/email]"
)),
new ArrayData(array(
"Title" => _t('BBCodeParser.IMAGE', 'Image'),
"Description" => _t('BBCodeParser.IMAGEDESCRIPTION', 'Show an image in your post'),
"Example" => "[img]http://www.website.com/image.jpg[/img]"
)),
new ArrayData(array(
"Title" => _t('BBCodeParser.CODE', 'Code Block'),
"Description" => _t('BBCodeParser.CODEDESCRIPTION', 'Unformatted code block'),
"Example" => '[code]'._t('BBCodeParser.CODEEXAMPLE', 'Code block').'[/code]'
)),
new ArrayData(array(
"Title" => _t('BBCodeParser.UNORDERED', 'Unordered list'),
"Description" => _t('BBCodeParser.UNORDEREDDESCRIPTION', 'Unordered list'),
"Example" => '[ulist][*]'._t('BBCodeParser.UNORDEREDEXAMPLE1', 'unordered item 1').'[*]'._t('BBCodeParser.UNORDEREDEXAMPLE2', 'unordered item 2').'[/ulist]'
))
"Example" => "[url=http://www.website.com/]Website[/url]"
))
);
}
@ -107,6 +102,10 @@ class BBCodeParser extends TextParser {
$this->content = str_replace(array('&', '<', '>'), array('&amp;', '&lt;', '&gt;'), $this->content);
$this->content = SSHTMLBBCodeParser::staticQparse($this->content);
$this->content = "<p>".$this->content."</p>";
$this->content = preg_replace('/(<p[^>]*>)\s+/i', '\\1', $this->content);
$this->content = preg_replace('/\s+(<\/p[^>]*>)/i', '\\1', $this->content);
$this->content = preg_replace("/\n\s*\n/", "</p><p>", $this->content);
$this->content = str_replace("\n", "<br />", $this->content);
return $this->content;

View File

@ -65,12 +65,12 @@ class SSHTMLBBCodeParser_Filter_Extended extends SSHTMLBBCodeParser_Filter
'htmlclose' => 'q',
'allowed' => 'all',
'attributes'=> array('quote' =>'cite=%2$s%1$s%2$s')),
'code' => array('htmlopen' => 'div class="codesnippet"',
'htmlclose' => 'div',
'code' => array('htmlopen' => 'div class="codesnippet"><p',
'htmlclose' => 'p></div',
'allowed' => 'all',
'attributes' => array()),
'php' => array('htmlopen' => 'div class="codesnippet"',
'htmlclose' => 'div',
'php' => array('htmlopen' => 'div class="codesnippet"><p',
'htmlclose' => 'p></div',
'allowed' => 'all',
'attributes' => array()),
'h1' => array('htmlopen' => 'h1',

View File

@ -819,12 +819,13 @@ class Member extends DataObject {
$password = new ConfirmedPasswordField(
'Password',
'Password',
null,
null,
null,
true // showOnClick
);
$password->setCanBeEmpty(true);
if(!$this->ID) $password->showOnClick = false;
$mainFields->replaceField('Password', $password);
$mainFields->insertBefore(
@ -860,6 +861,7 @@ class Member extends DataObject {
$mainFields->removeByName('Salt');
$mainFields->removeByName('NumVisit');
$mainFields->removeByName('LastVisited');
$mainFields->removeByName('BlacklistedEmail');
$fields->removeByName('Subscriptions');
$fields->removeByName('UnsubscribedRecords');

View File

@ -70,6 +70,26 @@ class RestfulServerTest extends SapphireTest {
unset($_SERVER['PHP_AUTH_USER']);
unset($_SERVER['PHP_AUTH_PW']);
}
public function testGETRelationshipsXML() {
$author1 = $this->objFromFixture('RestfulServerTest_Author', 'author1');
$rating1 = $this->objFromFixture('RestfulServerTest_AuthorRating', 'rating1');
$rating2 = $this->objFromFixture('RestfulServerTest_AuthorRating', 'rating2');
// @todo should be set up by fixtures, doesn't work for some reason...
$author1->Ratings()->add($rating1);
$author1->Ratings()->add($rating2);
$url = "/api/v1/RestfulServerTest_Author/" . $author1->ID;
$response = Director::test($url, null, null, 'GET');
$this->assertEquals($response->getStatusCode(), 200);
$responseArr = Convert::xml2array($response->getBody());
$ratingsArr = $responseArr['Ratings']['RestfulServerTest_AuthorRating'];
$this->assertEquals(count($ratingsArr), 2);
$this->assertEquals($ratingsArr[0]['@attributes']['id'], $rating1->ID);
$this->assertEquals($ratingsArr[1]['@attributes']['id'], $rating2->ID);
}
public function testPUTWithFormEncoded() {
$_SERVER['PHP_AUTH_USER'] = 'editor@test.com';
@ -366,6 +386,10 @@ class RestfulServerTest_Author extends DataObject implements TestOnly {
static $has_many = array(
'Ratings' => 'RestfulServerTest_AuthorRating',
);
public function canView($member = null) {
return true;
}
}
class RestfulServerTest_AuthorRating extends DataObject implements TestOnly {

View File

@ -1,7 +1,3 @@
RestfulServerTest_Comment:
comment1:
Name: Joe
Comment: This is a test comment
Member:
editor:
FirstName: Editor
@ -39,6 +35,11 @@ Permission:
RestfulServerTest_Page:
page1:
Title: Testpage without API Access
RestfulServerTest_Comment:
comment1:
Name: Joe
Comment: This is a test comment
Page: =>RestfulServerTest_Page.page1
RestfulServerTest_Author:
author1:
FirstName: Author 1
@ -48,6 +49,9 @@ RestfulServerTest_AuthorRating:
WriteProtectedField: Dont overwrite me
SecretField: Dont look at me!
Author: =>RestfulServerTest_Author.author1
rating2:
Rating: 5
Author: =>RestfulServerTest_Author.author1
RestfulServerTest_SecretThing:
thing1:
Name: Unspeakable

View File

@ -40,7 +40,7 @@ class RestfulServiceTest extends SapphireTest {
}
function testPostData() {
$connection = new RestfulService(Director::absoluteBaseURL());
$connection = new RestfulService(Director::absoluteBaseURL(), 0);
$test1params = array(
'test1a' => mktime(),
'test1b' => mt_rand(),
@ -88,4 +88,4 @@ XML;
}
}
?>
?>

View File

@ -166,6 +166,24 @@ class FieldSetTest extends SapphireTest {
/* We have 1 field inside our tab */
$this->assertEquals(1, $tab->Fields()->Count());
}
function testRenameField() {
$fields = new FieldSet();
$nameField = new TextField('Name', 'Before title');
$fields->push($nameField);
/* The title of the field object is the same as what we put in */
$this->assertSame('Before title', $nameField->Title());
/* The field gets renamed to a different title */
$fields->renameField('Name', 'After title');
/* The title of the field object is the title we renamed to, this
includes the original object we created ($nameField), and getting
the field back out of the set */
$this->assertSame('After title', $nameField->Title());
$this->assertSame('After title', $fields->dataFieldByName('Name')->Title());
}
function testReplaceAFieldInADifferentTab() {
/* A FieldSet gets created with a TabSet and some field objects */