mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge remote-tracking branch 'composer/3.1' into 3
Conflicts: .editorconfig docs/en/00_Getting_Started/00_Server_Requirements.md docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Windows_IIS7.md docs/en/00_Getting_Started/01_Installation/04_Other_installation_Options/Windows_Platform_Installer.md docs/en/00_Getting_Started/04_Directory_Structure.md docs/en/00_Getting_Started/index.md docs/en/01_Tutorials/01_Building_A_Basic_Site.md docs/en/01_Tutorials/02_Extending_A_Basic_Site.md docs/en/01_Tutorials/03_Forms.md docs/en/01_Tutorials/04_Site_Search.md docs/en/01_Tutorials/05_Dataobject_Relationship_Management.md docs/en/01_Tutorials/index.md docs/en/02_Developer_Guides/00_Model/01_Data_Model_and_ORM.md docs/en/02_Developer_Guides/00_Model/11_Scaffolding.md docs/en/02_Developer_Guides/01_Templates/06_Themes.md docs/en/02_Developer_Guides/03_Forms/How_Tos/Simple_Contact_Form.md docs/en/02_Developer_Guides/05_Extending/05_Injector.md docs/en/02_Developer_Guides/09_Security/04_Secure_Coding.md docs/en/02_Developer_Guides/10_Email/index.md docs/en/02_Developer_Guides/11_Integration/01_RestfulService.md docs/en/02_Developer_Guides/12_Search/01_Searchcontext.md docs/en/02_Developer_Guides/14_Files/index.md docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/03_CMS_Layout.md docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/06_Javascript_Development.md docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Tree.md docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_Site_Reports.md docs/en/02_Developer_Guides/18_Cookies_And_Sessions/01_Cookies.md docs/en/04_Changelogs/3.1.9.md docs/en/05_Contributing/00_Issues_and_Bugs.md docs/en/05_Contributing/02_Release_Process.md docs/en/05_Contributing/03_Documentation.md filesystem/File.php filesystem/GD.php model/DataDifferencer.php model/Versioned.php security/BasicAuth.php security/Member.php tests/filesystem/FileTest.php tests/forms/uploadfield/UploadFieldTest.php tests/model/VersionedTest.php tests/security/BasicAuthTest.php
This commit is contained in:
commit
88fdc75456
@ -1,12 +1,18 @@
|
||||
root = true
|
||||
# For more information about the properties used in
|
||||
# this file, please see the EditorConfig documentation:
|
||||
# http://editorconfig.org/
|
||||
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = tab
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# indentation for YAML config files
|
||||
[_config/*.yml]
|
||||
indent_style = space
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
|
@ -4,9 +4,24 @@ Any open source product is only as good as the community behind it. You can part
|
||||
|
||||
See our [high level overview](http://silverstripe.org/contributing-to-silverstripe) on silverstripe.org on how you can help out.
|
||||
|
||||
Or, for more detailed guidance, read one of the following pages:
|
||||
## Contributing to the correct version
|
||||
|
||||
* [Sharing your opinion and raising issues](http://doc.silverstripe.org/framework/en/trunk/misc/contributing/issues)
|
||||
* [Providing code, whether it's creating a feature or fixing a bug](http://doc.silverstripe.org/framework/en/trunk/misc/contributing/code)
|
||||
* [Writing and translating documentation](http://doc.silverstripe.org/framework/en/trunk/misc/contributing/documentation)
|
||||
* [Translating user-interface elements](http://doc.silverstripe.org/framework/en/trunk/misc/contributing/translation)
|
||||
SilverStripe core and module releases (since the 3.1.8 release) follow the [Semantic Versioning](http://semver.org)
|
||||
(SemVar) specification for releases. Using this specification declares to the entire development community the severity
|
||||
and intention of each release. It gives developers the ability to safely declare their dependencies and understand the
|
||||
scope involved in each upgrade.
|
||||
|
||||
Each release is labeled in the format `$MAJOR`.`$MINOR`.`$PATCH`. For example, 3.1.8 or 3.2.0.
|
||||
|
||||
* `$MAJOR` version is incremented if any backwards incompatible changes are introduced to the public API.
|
||||
* `$MINOR` version is incremented if new, backwards compatible **functionality** is introduced to the public API or
|
||||
improvements are introduced within the private code.
|
||||
* `$PATCH` version is incremented if only backwards compatible **bug fixes** are introduced. A bug fix is defined as
|
||||
an internal change that fixes incorrect behavior.
|
||||
|
||||
Git Branches are setup for each `$MINOR` version (i.e 3.1, 3.2). Each `$PATCH` release is a git tag off the `$MINOR`
|
||||
branch. For example, 3.1.8 will be a git tag of 3.1.8.
|
||||
|
||||
When contributing code, be aware of the scope of your changes. If your change is backwards incompatible, raise your
|
||||
change against the `master` branch. The master branch contains the next `$MAJOR` release. If the change is backwards
|
||||
compatible raise it against the correct `$MINOR` branch.
|
||||
|
@ -677,7 +677,7 @@ body.cms-dialog { overflow: auto; background: url("../images/textures/bg_cms_mai
|
||||
.htmleditorfield-mediaform .ss-gridfield table.ss-gridfield-table tr td { padding: 4px; }
|
||||
.htmleditorfield-mediaform .htmleditorfield-from-web .ss-uploadfield .middleColumn, .htmleditorfield-mediaform .htmleditorfield-from-cms .ss-uploadfield .middleColumn { width: auto; background: none; border: none; margin-top: 13px; }
|
||||
.htmleditorfield-mediaform .htmleditorfield-from-cms .ss-uploadfield h4 { float: left; margin-top: 4px; margin-bottom: 0; }
|
||||
.htmleditorfield-mediaform .htmleditorfield-from-cms .ss-uploadfield .middleColumn { margin-top: 16px; margin-left: 184px; }
|
||||
.htmleditorfield-mediaform .htmleditorfield-from-cms .ss-uploadfield .middleColumn { margin-top: 16px; margin-left: 184px; min-width: 0; clear: none; }
|
||||
.htmleditorfield-mediaform .htmleditorfield-from-cms .ss-uploadfield .field.treedropdown { border-bottom: 0; padding: 0; }
|
||||
.htmleditorfield-mediaform .ss-assetuploadfield .ss-uploadfield-editandorganize .ss-uploadfield-files .ss-uploadfield-item-info { background-color: #9e9e9e; background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzllOWU5ZSIvPjxzdG9wIG9mZnNldD0iOCUiIHN0b3AtY29sb3I9IiM5ZDlkOWQiLz48c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iIzg3ODc4NyIvPjxzdG9wIG9mZnNldD0iNTQlIiBzdG9wLWNvbG9yPSIjODY4Njg2Ii8+PHN0b3Agb2Zmc2V0PSI5NiUiIHN0b3AtY29sb3I9IiM2YjZiNmIiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM2YzZjNmMiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA='); background-size: 100%; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #9e9e9e), color-stop(8%, #9d9d9d), color-stop(50%, #878787), color-stop(54%, #868686), color-stop(96%, #6b6b6b), color-stop(100%, #6c6c6c)); background-image: -moz-linear-gradient(top, #9e9e9e 0%, #9d9d9d 8%, #878787 50%, #868686 54%, #6b6b6b 96%, #6c6c6c 100%); background-image: -webkit-linear-gradient(top, #9e9e9e 0%, #9d9d9d 8%, #878787 50%, #868686 54%, #6b6b6b 96%, #6c6c6c 100%); background-image: linear-gradient(to bottom, #9e9e9e 0%, #9d9d9d 8%, #878787 50%, #868686 54%, #6b6b6b 96%, #6c6c6c 100%); }
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
(function($) {
|
||||
|
||||
$.entwine('ss', function($){
|
||||
$.entwine('ss', function($) {
|
||||
|
||||
// setup jquery.entwine
|
||||
$.entwine.warningLevel = $.entwine.WARN_LEVEL_BESTPRACTISE;
|
||||
|
||||
/**
|
||||
* Hoizontal collapsible panel. Generic enough to work with CMS menu as well as various "filter" panels.
|
||||
* Horizontal collapsible panel. Generic enough to work with CMS menu as well as various "filter" panels.
|
||||
*
|
||||
* A panel consists of the following parts:
|
||||
* - Container div: The outer element, with class ".cms-panel"
|
||||
@ -45,7 +45,7 @@
|
||||
// Set panel width same as the content panel it contains. Assumes the panel has overflow: hidden.
|
||||
this.setWidthExpanded(this.find('.cms-panel-content').innerWidth());
|
||||
|
||||
// Assumes the collasped width is indicated by the toggle, or by an optional collapsed view
|
||||
// Assumes the collapsed width is indicated by the toggle, or by an optionally collapsed view
|
||||
var collapsedContent = this.find('.cms-panel-content-collapsed');
|
||||
this.setWidthCollapsed(collapsedContent.length ? collapsedContent.innerWidth() : this.find('.toggle-expand').innerWidth());
|
||||
|
||||
@ -134,5 +134,12 @@
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$('.cms-content-tools.collapsed').entwine({
|
||||
// Expand CMS' centre pane, when the pane itself is clicked somewhere
|
||||
onclick: function(e) {
|
||||
$('.cms-panel .toggle-expand').trigger('click');
|
||||
}
|
||||
});
|
||||
});
|
||||
}(jQuery));
|
||||
|
@ -515,7 +515,18 @@ jQuery.noConflict();
|
||||
// Set 'fake' referer - we call pushState() before making the AJAX request, so we have to
|
||||
// set our own referer here
|
||||
if (typeof state.data.__forceReferer !== 'undefined') {
|
||||
headers['X-Backurl'] = state.data.__forceReferer;
|
||||
// Ensure query string is properly encoded if present
|
||||
var url = state.data.__forceReferer;
|
||||
|
||||
try {
|
||||
// Prevent double-encoding by attempting to decode
|
||||
url = decodeURI(url);
|
||||
} catch(e) {
|
||||
// URL not encoded, or was encoded incorrectly, so do nothing
|
||||
} finally {
|
||||
// Set our referer header to the encoded URL
|
||||
headers['X-Backurl'] = encodeURI(url);
|
||||
}
|
||||
}
|
||||
|
||||
contentEls.addClass('loading');
|
||||
|
10
admin/javascript/lang/src/lt.js
Normal file
10
admin/javascript/lang/src/lt.js
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"LeftAndMain.CONFIRMUNSAVED": "Ar tikrai norite išeiti iš šio puslapio?\n\nDĖMESIO: Jūsų pakeitimai neišsaugoti.\n\nNorėdami tęsti, spauskite OK, jeigu norite likti, spauskite Cancel.",
|
||||
"LeftAndMain.CONFIRMUNSAVEDSHORT": "DĖMESIO: Jūsų pakeitimai neišsaugoti.",
|
||||
"SecurityAdmin.BATCHACTIONSDELETECONFIRM": "Ar tikrai norite ištrinti %s grupes?",
|
||||
"ModelAdmin.SAVED": "Išsaugota",
|
||||
"ModelAdmin.REALLYDELETE": "Ar tikrai norite ištrinti?",
|
||||
"ModelAdmin.DELETED": "Ištrinta",
|
||||
"ModelAdmin.VALIDATIONERROR": "Tikrinimo klaida",
|
||||
"LeftAndMain.PAGEWASDELETED": "Šis puslapis ištrintas. Norėdami redaguoti puslapį, pasirinkite jį kairėje."
|
||||
}
|
@ -1559,6 +1559,8 @@ body.cms-dialog {
|
||||
.middleColumn {
|
||||
margin-top: $grid-y*2; // same as left-floated h4
|
||||
margin-left: $grid-x*23; // make room for headline
|
||||
min-width: 0; // fit within available space
|
||||
clear: none; // headline and dropdown on same line
|
||||
}
|
||||
.field.treedropdown {
|
||||
border-bottom: 0; // don't show border, dropdown and gridfield visually belong together
|
||||
|
@ -1,7 +1,9 @@
|
||||
<div class="cms-content-tools west cms-panel cms-panel-layout" id="cms-content-tools-ModelAdmin" data-expandOnClick="true" data-layout-type="border">
|
||||
<div class="cms-panel-content center">
|
||||
<% if $SearchForm %>
|
||||
<h3 class="cms-panel-header"><% _t('ModelAdmin_Tools_ss.FILTER', 'Filter') %></h3>
|
||||
$SearchForm
|
||||
<% end_if %>
|
||||
|
||||
<% if $ImportForm %>
|
||||
<h3 class="cms-panel-header"><% _t('ModelAdmin_Tools_ss.IMPORT', 'Import') %></h3>
|
||||
|
@ -95,9 +95,9 @@ Injector::set_inst($injector);
|
||||
// Regenerate the manifest if ?flush is set, or if the database is being built.
|
||||
// The coupling is a hack, but it removes an annoying bug where new classes
|
||||
// referenced in _config.php files can be referenced during the build process.
|
||||
$flush = (isset($_GET['flush']) || isset($_REQUEST['url']) && (
|
||||
$_REQUEST['url'] == 'dev/build' || $_REQUEST['url'] == BASE_URL . '/dev/build'
|
||||
));
|
||||
$requestURL = isset($_REQUEST['url']) ? trim($_REQUEST['url'], '/') : false;
|
||||
$flush = (isset($_GET['flush']) || $requestURL == 'dev/build' || $requestURL == BASE_URL . '/dev/build');
|
||||
|
||||
global $manifest;
|
||||
$manifest = new SS_ClassManifest(BASE_PATH, false, $flush);
|
||||
|
||||
@ -111,16 +111,17 @@ if(file_exists(BASE_PATH . '/vendor/autoload.php')) {
|
||||
require_once BASE_PATH . '/vendor/autoload.php';
|
||||
}
|
||||
|
||||
// Now that the class manifest is up, load the configuration
|
||||
// Now that the class manifest is up, load the static configuration
|
||||
$configManifest = new SS_ConfigStaticManifest(BASE_PATH, false, $flush);
|
||||
Config::inst()->pushConfigStaticManifest($configManifest);
|
||||
|
||||
// Now that the class manifest is up, load the configuration
|
||||
// And then the yaml configuration
|
||||
$configManifest = new SS_ConfigManifest(BASE_PATH, false, $flush);
|
||||
Config::inst()->pushConfigYamlManifest($configManifest);
|
||||
|
||||
// Load template manifest
|
||||
SS_TemplateLoader::instance()->pushManifest(new SS_TemplateManifest(
|
||||
BASE_PATH, project(), false, isset($_GET['flush'])
|
||||
BASE_PATH, project(), false, $flush
|
||||
));
|
||||
|
||||
// If in live mode, ensure deprecation, strict and notices are not reported
|
||||
|
@ -16,7 +16,6 @@ class SS_TemplateManifest {
|
||||
protected $cacheKey;
|
||||
protected $project;
|
||||
protected $inited;
|
||||
protected $forceRegen;
|
||||
protected $templates = array();
|
||||
|
||||
/**
|
||||
@ -40,7 +39,9 @@ class SS_TemplateManifest {
|
||||
$this->cache = new $cacheClass('templatemanifest'.($includeTests ? '_tests' : ''));
|
||||
$this->cacheKey = $this->getCacheKey($includeTests);
|
||||
|
||||
$this->forceRegen = $forceRegen;
|
||||
if ($forceRegen) {
|
||||
$this->regenerate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -208,7 +209,7 @@ class SS_TemplateManifest {
|
||||
}
|
||||
|
||||
protected function init() {
|
||||
if (!$this->forceRegen && $data = $this->cache->load($this->cacheKey)) {
|
||||
if ($data = $this->cache->load($this->cacheKey)) {
|
||||
$this->templates = $data;
|
||||
$this->inited = true;
|
||||
} else {
|
||||
|
@ -1554,6 +1554,8 @@ HTML;
|
||||
|
||||
if($base != '.') $baseClause = "RewriteBase '$base'\n";
|
||||
else $baseClause = "";
|
||||
if(strpos(strtolower(php_sapi_name()), "cgi") !== false) $cgiClause = "RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]\n";
|
||||
else $cgiClause = "";
|
||||
$modulePath = FRAMEWORK_NAME;
|
||||
$rewrite = <<<TEXT
|
||||
# Deny access to templates (but allow from localhost)
|
||||
@ -1583,6 +1585,7 @@ ErrorDocument 500 /assets/error-500.html
|
||||
SetEnv HTTP_MOD_REWRITE On
|
||||
RewriteEngine On
|
||||
$baseClause
|
||||
$cgiClause
|
||||
|
||||
# Deny access to potentially sensitive files and folders
|
||||
RewriteRule ^vendor(/|$) - [F,L,NC]
|
||||
|
@ -8,7 +8,7 @@ Our web-based [PHP installer](/installation) can check if you meet the requireme
|
||||
|
||||
## Web server software requirements
|
||||
|
||||
* PHP 5.3.3+
|
||||
* PHP 5.3.2+
|
||||
* We recommend using a PHP accelerator or opcode cache, such as [xcache](http://xcache.lighttpd.net/) or [WinCache](http://www.iis.net/download/wincacheforphp).
|
||||
* Allocate at least 48MB of memory to each PHP process. (SilverStripe can be resource hungry for some intensive operations.)
|
||||
* Required modules: dom, gd2, fileinfo, hash, iconv, mbstring, mysqli (or other database driver), session, simplexml, tokenizer, xml.
|
||||
@ -45,7 +45,7 @@ comfortably allows over a million page views per month. Caching and other optimi
|
||||
ten or even one hundred times. SilverStripe CMS can be used in multiple-server architectures to improve scalability and
|
||||
redundancy.
|
||||
|
||||
For more information on how to scale SilverStripe see the [Performance](../../developer_guides/performance/) Gluide.
|
||||
For more information on how to scale SilverStripe see the [Performance](/developer_guides/performance/) Guide.
|
||||
|
||||
## Client side (CMS) requirements
|
||||
|
||||
@ -57,5 +57,5 @@ systems.
|
||||
|
||||
SilverStripe CMS is designed to make excellent, standards-compliant websites that are compatible with a wide range of
|
||||
industry standard browsers and operating systems. A competent developer is able to produce websites that meet W3C
|
||||
guidelines for HTML, CSS, JavaScript, and accessibility, in addition to meeting specific guildelines, such as
|
||||
guidelines for HTML, CSS, JavaScript, and accessibility, in addition to meeting specific guide lines, such as
|
||||
e-government requirements.
|
||||
|
@ -27,7 +27,7 @@ We'll also install SQL Server 2008 R2, and support for connecting to it in PHP.
|
||||
|
||||
* Internet Information Services (IIS) 7.x
|
||||
* SQL Server 2008 R2
|
||||
* PHP 5.4 (PHP 5.3.3+ also works, but we'll install with the latest PHP stable)
|
||||
* PHP 5.4 (PHP 5.3.2+ also works, but we'll install with the latest PHP stable)
|
||||
* SilverStripe 3
|
||||
* [Microsoft URL Rewrite Module 2.0](http://www.iis.net/download/URLRewrite)
|
||||
* [IIS 7 Administration Pack](http://www.iis.net/download/AdministrationPack) (ONLY required for Windows Vista or Server 2008)
|
||||
@ -154,7 +154,7 @@ Two other important folders to set the permissions on are `assets` and `silverst
|
||||
|
||||
You will need to give **Modify** permission to **IUSR** user. To do it right click the folder and choose **Properties**. Then open the security tab, press **Edit** and add the **IUSR** user to the list by clicking the **Add** button. Afterwards tick **Modify** under **Allow** for that user. Repeat these steps for each folder.
|
||||
|
||||
![](/_images/iis7-iusr-permissions.jpg)
|
||||
![](../../../_images/iis7-iusr-permissions.jpg)
|
||||
|
||||
## Install SilverStripe
|
||||
|
||||
|
@ -40,11 +40,11 @@ a beta version of the software)
|
||||
|
||||
## Screenshots
|
||||
|
||||
![](/_images/webpi-2-a-silverstripe-choice.jpg)
|
||||
![](/_images/webpi-2-b-dependencies.jpg)
|
||||
![](/_images/webpi-2-c-downloading-and-installaing.jpg)
|
||||
![](/_images/webpi-2-d-installer-questions-step1.jpg)
|
||||
![](/_images/webpi-2-e-installer-questions-step2.jpg)
|
||||
![](/_images/webpi-2-f-success-message.jpg)
|
||||
![](/_images/webpi-2-g-silverstripe-homepage.jpg)
|
||||
![](/_images/webpi-2-h-cms-interface-working.jpg)
|
||||
![](../../../_images/webpi-2-a-silverstripe-choice.jpg)
|
||||
![](../../../_images/webpi-2-b-dependencies.jpg)
|
||||
![](../../../_images/webpi-2-c-downloading-and-installaing.jpg)
|
||||
![](../../../_images/webpi-2-d-installer-questions-step1.jpg)
|
||||
![](../../../_images/webpi-2-e-installer-questions-step2.jpg)
|
||||
![](../../../_images/webpi-2-f-success-message.jpg)
|
||||
![](../../../_images/webpi-2-g-silverstripe-homepage.jpg)
|
||||
![](../../../_images/webpi-2-h-cms-interface-working.jpg)
|
||||
|
@ -86,6 +86,9 @@ But enough of the disclaimer, on to the actual configuration — typically in `n
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
include fastcgi_params;
|
||||
fastcgi_buffer_size 32k;
|
||||
fastcgi_busy_buffers_size 64k;
|
||||
fastcgi_buffers 4 32k;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ This is my `_ss_environment.php` file. I have it placed in `/var`, as each of th
|
||||
| `SS_ENVIRONMENT_TYPE`| The environment type: dev, test or live.|
|
||||
| `SS_DEFAULT_ADMIN_USERNAME`| The username of the default admin. This is a user with administrative privileges.|
|
||||
| `SS_DEFAULT_ADMIN_PASSWORD`| The password of the default admin. This will not be stored in the database.|
|
||||
| `SS_USE_BASIC_AUTH`| Protect the site with basic auth (good for test sites)|
|
||||
| `SS_USE_BASIC_AUTH`| Protect the site with basic auth (good for test sites).<br/>When using CGI/FastCGI with Apache, you will have to add the `RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]` rewrite rule to your `.htaccess` file|
|
||||
| `SS_SEND_ALL_EMAILS_TO`| If you set this define, all emails will be redirected to this address.|
|
||||
| `SS_SEND_ALL_EMAILS_FROM`| If you set this define, all emails will be send from this address.|
|
||||
| `SS_ERROR_LOG` | |
|
||||
|
@ -10,8 +10,8 @@ directories is meaningful to its logic.
|
||||
Directory | Description
|
||||
--------- | -----------
|
||||
`assets/` | Contains images and other files uploaded via the SilverStripe CMS. You can also place your own content inside it, and link to it from within the content area of the CMS.
|
||||
`cms/` | Contains all the files that form the CMS area of your site. It’s structure is similiar to the mysite/ directory, so if you find something interesting, it should be easy enough to look inside and see how it was built.
|
||||
`framework/` | The framework that builds both your own site and as the CMS that powers it. You’ll be utilizing files in this directory often, both directly and indirectly.
|
||||
`cms/` | Contains all the files that form the CMS area of your site. It’s structure is similar to the mysite/ directory, so if you find something interesting, it should be easy enough to look inside and see how it was built.
|
||||
`framework/` | The framework that builds both your own site and as the CMS that powers it. You’ll be utilising files in this directory often, both directly and indirectly.
|
||||
|
||||
## Custom Code Structure
|
||||
|
||||
@ -23,7 +23,7 @@ existing modules or the directories lists in "Core Structure".
|
||||
| `<mysite>/` | This directory contains all of your code that defines your website. |
|
||||
| `<mysite>/_config` | YAML configuration specific to your application |
|
||||
| `<mysite>/code` | PHP code for model and controller (subdirectories are optional) |
|
||||
| `<mysite>/templates` | HTML [templates](templates) with *.ss-extension |
|
||||
| `<mysite>/templates` | HTML [templates](/developer_guides/templates) with *.ss-extension |
|
||||
| `<mysite>/css ` | CSS files |
|
||||
| `<mysite>/images ` | Images used in the HTML templates |
|
||||
| `<mysite>/javascript` | Javascript and other script files
|
||||
@ -35,7 +35,7 @@ existing modules or the directories lists in "Core Structure".
|
||||
| `themes/yourtheme/` | The themes folder can contain more than one theme - here's your own |
|
||||
|
||||
|
||||
See [themes](/topics/themes)
|
||||
See [themes](/developer_guides/templates/themes)
|
||||
|
||||
## Module Structure {#module_structure}
|
||||
|
||||
@ -50,19 +50,19 @@ Example Forum:
|
||||
| `forum/code` | PHP code for model and controller (subdirectories are optional) |
|
||||
| ... | ... |
|
||||
|
||||
![](/_images/modules_folder.jpg)
|
||||
![](../_images/modules_folder.jpg)
|
||||
|
||||
### Module documentation
|
||||
|
||||
Module developers can bundle developer documentation with their code by producing
|
||||
plain text files inside a 'docs' folder located in the module folder. These files
|
||||
can be written with the Markdown syntax (See [Contributing Documentation](/misc/contributing/documentation))
|
||||
can be written with the Markdown syntax (See [Contributing Documentation](/contributing/documentation))
|
||||
and include media such as images or videos.
|
||||
|
||||
Inside the docs folder, developers should organize the markdown files into each
|
||||
Inside the docs folder, developers should organise the markdown files into each
|
||||
separate language they wish to write documentation for (usually just `en`). Inside
|
||||
each languages' subfolder, developers then have freedom to create whatever structure
|
||||
they wish for organizing the documentation they wish.
|
||||
they wish for organising the documentation they wish.
|
||||
|
||||
Example Forum Documentation:
|
||||
|
||||
@ -89,4 +89,4 @@ by using a `flush=1` query parameter. See the ["Manifests" documentation](/devel
|
||||
## Best Practices
|
||||
|
||||
### Making /assets readonly
|
||||
See [secure-development#filesystem](/topics/security#filesystem)
|
||||
See [Secure coding](/developer_guides/security/secure_coding#filesystem)
|
||||
|
@ -46,13 +46,13 @@ When designing your site you should only need to modify the *mysite*, *themes* a
|
||||
|
||||
### User Interface Basics
|
||||
|
||||
![](/_images/tutorial1_cms-basic.jpg)
|
||||
![](../_images/tutorial1_cms-basic.jpg)
|
||||
|
||||
The CMS is the area in which you can manage your site content. You can access the cms at http://localhost/your_site_name/admin (or http://yourdomain.com/admin if you are using your own domain name). You
|
||||
will be presented with a login screen. Login using the details you provided at installation. After logging in you
|
||||
should see the CMS interface with a list of the pages currently on your website (the site tree). Here you can add, delete and reorganize pages. If you need to delete, publish, or unpublish a page, first check "multi-selection" at the top. You will then be able to perform actions on any checked files using the "Actions" dropdown. Clicking on a page will open it in the page editing interface pictured below (we've entered some test content).
|
||||
|
||||
![](/_images/tutorial1_cms-numbered.jpg)
|
||||
![](../_images/tutorial1_cms-numbered.jpg)
|
||||
|
||||
1. This menu allows you to move between different sections of the CMS. There are four core sections - "Pages", "Files", "Users" and "Settings". If you have modules installed, they may have their own sections here. In this tutorial we will be focusing on the "Pages" section.
|
||||
2. The breadcrumbs on the left will show you a direct path to the page you are currently looking at. You can use this path to navigate up through a page's hierarchy. On the left there are tabs you may use to flick between different aspects of a page. By default, you should be shown three tabs: "Content", "Settings", and "History".
|
||||
@ -60,11 +60,11 @@ should see the CMS interface with a list of the pages currently on your website
|
||||
* Settings - Here you set the type of page behavior, parent page, show in search, show in menu, and who can view or edit the page.
|
||||
* History - This allows you to view previous version of your page, compare, change, and revert to previous version if need be.
|
||||
3. Within the "Pages" section (provided you are in the "Content" or "Settings" tab) you can quickly move between pages in the CMS using the site tree. To collapse and expand this sidebar, click the arrow at the bottom. If you are in the history tab, you will notice the site tree has been replaced by a list of the alterations to the current page.
|
||||
![](/_images/tutorial1_cms-numbered-3.jpg)
|
||||
![](../_images/tutorial1_cms-numbered-3.jpg)
|
||||
4. This section allows you to edit the content for the currently selected page, as well as changing other properties of the page such as the page name and URL. The content editor has full [WYSIWYG](http://en.wikipedia.org/wiki/WYSIWYG) capabilities, allowing you to change formatting and insert links, images, and tables.
|
||||
5. These buttons allow you to save your changes to the draft copy, publish your draft copy, unpublish from the live website, or remove a page from the draft website. The SilverStripe CMS workflow stores two copies of a page, a draft and a published copy. By having separate draft and published copies, we can preview draft changes on the site before publishing them to the live website. You can quickly preview your draft pages without leaving the CMS by clicking the "Preview" button.
|
||||
|
||||
![](/_images/tutorial1_cms-numbered-5.jpg)
|
||||
![](../_images/tutorial1_cms-numbered-5.jpg)
|
||||
|
||||
### Try it
|
||||
|
||||
@ -77,7 +77,7 @@ To create a new page, click the "Add New" button above the site tree.
|
||||
When you create a new page, you are given the option of setting the structure of the page ("Top level" or "Under another page") and the page type.
|
||||
The page type specifies the templates used to render the page, the fields that are able to be edited in the CMS, and page specific behavior. We will explain page types in more depth as we progress; for now, make all pages of the type "Page".
|
||||
|
||||
![](/_images/tutorial1_addpage.jpg)
|
||||
![](../_images/tutorial1_addpage.jpg)
|
||||
|
||||
**SilverStripe's friendly URLs**
|
||||
|
||||
@ -87,7 +87,7 @@ page in the database.
|
||||
|
||||
Note that if you have sub-pages, changing the Top level URL field for a page will affect the URL for all sub-pages. For example, if we changed the URL field "/about-us/" to "/about-silverstripe/" then the sub-pages URLs would now be "/about-silverstripe/URL-of-subpage/" rather than "/about-us/URL-of-subpage/".
|
||||
|
||||
![](/_images/tutorial1_url.jpg)
|
||||
![](../_images/tutorial1_url.jpg)
|
||||
|
||||
When you create a new page, SilverStripe automatically creates an appropriate URL for it. For example, *About Us* will
|
||||
become *about-us*. You are able to change it yourself so that you can make long titles more usable or descriptive. For
|
||||
@ -182,7 +182,7 @@ Then, using a loop over the page control *Menu(1)*, we add a link to the list fo
|
||||
|
||||
This creates the navigation at the top of the page:
|
||||
|
||||
![](/_images/tutorial1_menu.jpg)
|
||||
![](../_images/tutorial1_menu.jpg)
|
||||
|
||||
|
||||
|
||||
@ -219,7 +219,7 @@ You can also create the pages elsewhere on the site tree, and drag and drop the
|
||||
|
||||
Either way, your site tree should now look something like this:
|
||||
|
||||
![](/_images/tutorial1_2nd_level-cut.jpg)
|
||||
![](../_images/tutorial1_2nd_level-cut.jpg)
|
||||
|
||||
Great, we now have a hierarchical site structure! Let's look at how this is created and displayed in our template.
|
||||
|
||||
@ -289,7 +289,7 @@ to get the top level page title. In this case, we merely use it to check the exi
|
||||
|
||||
Both the top menu, and the sidebar menu should be updating and highlighting as you move from page to page. They will also mirror changes done in the SilverStripe CMS, such as renaming pages or moving them around.
|
||||
|
||||
![](/_images/tutorial1_menu-two-level.jpg)
|
||||
![](../_images/tutorial1_menu-two-level.jpg)
|
||||
|
||||
Feel free to experiment with the if and loop statements. For example, you could create a drop down style menu from the top navigation using a combination of if statements, loops, and some CSS to style it.
|
||||
|
||||
@ -358,7 +358,7 @@ After building the database, we can change the page type of the homepage in the
|
||||
|
||||
In the CMS, navigate to the "Home" page and switch to the "Settings" tab. Change "Page type" to *Home Page*, and click "Save & Publish".
|
||||
|
||||
![](/_images/tutorial1_homepage-type.jpg)
|
||||
![](../_images/tutorial1_homepage-type.jpg)
|
||||
|
||||
Our homepage is now of the page type *HomePage*. Regardless, it is still
|
||||
rendered with the *Page* template. SilverStripe does this as our homepage inherits its type from *Page*,
|
||||
@ -383,21 +383,21 @@ We'll also replace the title text with an image. Find this line:
|
||||
|
||||
:::ss
|
||||
<div id="Banner">
|
||||
<img src="http://www.silverstripe.org/themes/silverstripe/images/sslogo.png" alt="Homepage image" />
|
||||
<img src="http://www.silverstripe.org/assets/SilverStripe-200.png" alt="Homepage image" />
|
||||
</div>
|
||||
|
||||
|
||||
Your Home page should now look like this:
|
||||
|
||||
|
||||
![](/_images/tutorial1_home-template.jpg)
|
||||
![](../_images/tutorial1_home-template.jpg)
|
||||
|
||||
SilverStripe first searches for a template in the *themes/simple/templates* folder. Since there is no *HomePage.ss*,
|
||||
it will use the *Page.ss* for both *Page* and *HomePage* page types. When it comes across the *$Layout* tag, it will
|
||||
then descend into the *themes/simple/templates/Layout* folder, and will use *Page.ss* for the *Page* page type, and
|
||||
*HomePage.ss* for the *HomePage* page type. So while you could create a HomePage.ss in the *themes/simple/templates/* it is better to reuse the navigation and footer common to both our Home page and the rest of the pages on our website.
|
||||
|
||||
![](/_images/tutorial1_subtemplates-diagram.jpg)
|
||||
![](../_images/tutorial1_subtemplates-diagram.jpg)
|
||||
|
||||
|
||||
## Summary
|
||||
|
@ -14,12 +14,12 @@ We are going to work on adding two new sections to the site we built in the firs
|
||||
|
||||
The first of these new sections will be *News*, with a recent news listing on the homepage and an RSS feed:
|
||||
|
||||
![](/_images/tutorial2_newslist.jpg)
|
||||
![](../_images/tutorial2_newslist.jpg)
|
||||
|
||||
|
||||
The second will be a *Staff* section, to demonstrate more complex database structures (such as associating an image with each staff member):
|
||||
|
||||
![](/_images/tutorial2_einstein.jpg)
|
||||
![](../_images/tutorial2_einstein.jpg)
|
||||
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ Creating a new page type requires creating each of these three elements. We will
|
||||
A more in-depth introduction of Model-View-Controller can be found
|
||||
[here](http://www.slash7.com/articles/2005/02/22/mvc-the-most-vexing-conundrum).
|
||||
|
||||
![](/_images/tutorial2_pagetype-inheritance.jpg)
|
||||
![](../_images/tutorial2_pagetype-inheritance.jpg)
|
||||
|
||||
## Creating the news section page types
|
||||
|
||||
@ -184,9 +184,9 @@ Finally, we return the fields to the CMS. If we flush the cache (by adding ?flus
|
||||
|
||||
Now that we have created our page types, let's add some content. Go into the CMS and create an *ArticleHolder* page named "News", then create a few *ArticlePage*'s within it.
|
||||
|
||||
![](/_images/tutorial2_news-cms.jpg)
|
||||
![](../_images/tutorial2_news-cms.jpg)
|
||||
|
||||
## Modifing the date field
|
||||
## Modifying the date field
|
||||
|
||||
At the moment, your date field will look just like a text field.
|
||||
This makes it confusing and doesn't give the user much help when adding a date.
|
||||
@ -269,13 +269,13 @@ To access the new fields, we use *$Date* and *$Author*. In fact, all template va
|
||||
spread across several tables in the database matched by id - e.g. *Content* is in the *SiteTree* table, and *Date* and
|
||||
*Author* are in the *ArticlePage* table. SilverStripe matches this data, and collates it into a single data object.
|
||||
|
||||
![](/_images/tutorial2_data-collation.jpg)
|
||||
![](../_images/tutorial2_data-collation.jpg)
|
||||
|
||||
Rather than using *$Date* directly, we use *$Date.Nice*. If we look in the `[api:Date]` documentation, we can see
|
||||
that the *Nice* function returns the date in *dd/mm/yyyy* format, rather than the *yyyy-mm-dd* format stored in the
|
||||
database.
|
||||
|
||||
![](/_images/tutorial2_news.jpg)
|
||||
![](../_images/tutorial2_news.jpg)
|
||||
|
||||
###ArticleHolder Template
|
||||
We'll now create a template for the article holder. We want our news section to show a list of news items, each with a summary and a link to the main article (our Article Page).
|
||||
@ -303,12 +303,12 @@ We'll now create a template for the article holder. We want our news section to
|
||||
|
||||
Here we use the page control *Children*. As the name suggests, this control allows you to iterate over the children of a page. In this case, the children are our news articles. The *$Link* variable will give the address of the article which we can use to create a link, and the *FirstParagraph* function of the `[api:HTMLText]` field gives us a nice summary of the article. The function strips all tags from the paragraph extracted.
|
||||
|
||||
![](/_images/tutorial2_articleholder.jpg)
|
||||
![](../_images/tutorial2_articleholder.jpg)
|
||||
|
||||
|
||||
### Using include files in templates
|
||||
|
||||
We can make our templates more modular and easier to maintain by separating commonly-used components in to *include files*. We are already familiar with the `<% include Sidebar %>` line from looking at the menu in the [first tutorial (Building a basic site)](/tutorials/building_a_basic_site).
|
||||
We can make our templates more modular and easier to maintain by separating commonly-used components in to *include files*. We are already familiar with the `<% include Sidebar %>` line from looking at the menu in the [first tutorial (Building a basic site)](../tutorials/building_a_basic_site).
|
||||
|
||||
We'll separate the display of linked articles as we want to reuse this code later on.
|
||||
|
||||
@ -351,7 +351,7 @@ And this one to the *HomePage* class:
|
||||
|
||||
This will change the icons for the pages in the CMS.
|
||||
|
||||
![](/_images/tutorial2_icons2.jpg)
|
||||
![](../_images/tutorial2_icons2.jpg)
|
||||
|
||||
<div class="hint" markdown="1">
|
||||
Note: The `news-file` icon may not exist in a default SilverStripe installation. Try adding your own image or choosing a different one from the `treeicons` collection.
|
||||
@ -388,7 +388,7 @@ When SilverStripe comes across a variable or page control it doesn't recognize,
|
||||
|
||||
The controller for a page is only created when page is actually visited, while the data object is available when the page is referenced in other pages, e.g. by page controls. A good rule of thumb is to put all functions specific to the page currently being viewed in the controller; only if a function needs to be used in another page should you put it in the data object.
|
||||
|
||||
![](/_images/tutorial2_homepage-news.jpg)
|
||||
![](../_images/tutorial2_homepage-news.jpg)
|
||||
|
||||
|
||||
|
||||
@ -413,7 +413,7 @@ This function creates an RSS feed of all the news articles, and outputs it to th
|
||||
|
||||
Depending on your browser, you should see something like the picture below. If your browser doesn't support RSS, you will most likely see the XML output instead. For more on RSS, see `[api:RSSFeed]`
|
||||
|
||||
![](/_images/tutorial2_rss-feed.jpg)
|
||||
![](../_images/tutorial2_rss-feed.jpg)
|
||||
|
||||
Now all we need is to let the user know that our RSS feed exists. Add this function to *ArticleHolder_Controller*:
|
||||
|
||||
@ -480,12 +480,12 @@ We then add an `[api:UploadField]` in the *getCMSFields* function to the tab "Ro
|
||||
the *addFieldToTab* function will create it for us. The *UploadField* allows us to select an image or upload a new one in
|
||||
the CMS.
|
||||
|
||||
![](/_images/tutorial2_photo.jpg)
|
||||
![](../_images/tutorial2_photo.jpg)
|
||||
|
||||
Rebuild the database ([http://localhost/your_site_name/dev/build](http://localhost/your_site_name/dev/build)) and open the CMS. Create
|
||||
a new *StaffHolder* called "Staff", and create some *StaffPage*s in it.
|
||||
|
||||
![](/_images/tutorial2_create-staff.jpg)
|
||||
![](../_images/tutorial2_create-staff.jpg)
|
||||
|
||||
|
||||
### Creating the staff section templates
|
||||
@ -518,7 +518,7 @@ This template is very similar to the *ArticleHolder* template. The *SetWidth* me
|
||||
will resize the image before sending it to the browser. The resized image is cached, so the server doesn't have to
|
||||
resize the image every time the page is viewed.
|
||||
|
||||
![](/_images/tutorial2_staff-section.jpg)
|
||||
![](../_images/tutorial2_staff-section.jpg)
|
||||
|
||||
The *StaffPage* template is also very straight forward.
|
||||
|
||||
@ -539,7 +539,7 @@ The *StaffPage* template is also very straight forward.
|
||||
Here we use the *SetWidth* method to get a different sized image from the same source image. You should now have
|
||||
a complete staff section.
|
||||
|
||||
![](/_images/tutorial2_einstein.jpg)
|
||||
![](../_images/tutorial2_einstein.jpg)
|
||||
|
||||
## Summary
|
||||
|
||||
|
@ -13,7 +13,7 @@ Instead of using a custom coded form, we could use the [userforms module](http:/
|
||||
|
||||
We will create a poll on the home page that asks the user their favourite web browser, and displays a bar graph of the results.
|
||||
|
||||
![tutorial:tutorial3_pollresults.png](/_images/tutorial3_pollresults.jpg)
|
||||
![tutorial:tutorial3_pollresults.png](../_images/tutorial3_pollresults.jpg)
|
||||
|
||||
|
||||
## Creating the form
|
||||
@ -171,7 +171,7 @@ Add the following code to the existing `form.css` file:
|
||||
|
||||
All going according to plan, if you visit [http://localhost/your_site_name/home/?flush=1](http://localhost/your_site_name/home/?flush=1) it should look something like this:
|
||||
|
||||
![](/_images/tutorial3_pollform.jpg)
|
||||
![](../_images/tutorial3_pollform.jpg)
|
||||
|
||||
|
||||
## Processing the form
|
||||
@ -232,7 +232,7 @@ Change the end of the 'BrowserPollForm' function so it looks like this:
|
||||
|
||||
If we then open the homepage and attempt to submit the form without filling in the required fields errors should appear.
|
||||
|
||||
![](/_images/tutorial3_validation.jpg)
|
||||
![](../_images/tutorial3_validation.jpg)
|
||||
|
||||
|
||||
## Showing the poll results
|
||||
@ -356,7 +356,7 @@ and the poll results need to be displayed.
|
||||
|
||||
We use the normal tactic of putting the data into an unordered list and using CSS to style it, except here we use inline styles to display a bar that is sized proportionate to the number of votes the browser has received. You should now have a complete poll.
|
||||
|
||||
![](/_images/tutorial3_pollresults.jpg)
|
||||
![](../_images/tutorial3_pollresults.jpg)
|
||||
|
||||
## Summary
|
||||
|
||||
|
@ -11,7 +11,7 @@ This is a short tutorial demonstrating how to add search functionality to a Silv
|
||||
|
||||
We are going to add a search box on the top of the page. When a user types something in the box, they are taken to a results page.
|
||||
|
||||
![](/_images/tutorial4_search.jpg)
|
||||
![](../_images/tutorial4_search.jpg)
|
||||
|
||||
## Creating the search form
|
||||
|
||||
@ -46,7 +46,7 @@ To add the search form, we can add `$SearchForm` anywhere in our templates. In t
|
||||
|
||||
This displays as:
|
||||
|
||||
![](/_images/tutorial4_searchbox.jpg)
|
||||
![](../_images/tutorial4_searchbox.jpg)
|
||||
|
||||
## Showing the results
|
||||
|
||||
@ -152,7 +152,7 @@ class.
|
||||
Then finally add ?flush=1 to the URL and you should see the new template.
|
||||
|
||||
|
||||
![](/_images/tutorial4_search.jpg)
|
||||
![](../_images/tutorial4_search.jpg)
|
||||
|
||||
## Summary
|
||||
|
||||
|
@ -101,7 +101,7 @@ The restriction is enforced through the `$allowed_children` directive.
|
||||
}
|
||||
|
||||
You might have noticed that we don't specify the relationship
|
||||
to a project. That's because its already inherited from the parent implementation,
|
||||
to a project. That's because it's already inherited from the parent implementation,
|
||||
as part of the normal page hierarchy in the CMS.
|
||||
|
||||
Now that we have created our `ProjectsHolder` and `Project` page types, we'll add some content.
|
||||
@ -116,7 +116,7 @@ and collect those within a `ProjectsHolder`.
|
||||
But what about creating `Student` records?
|
||||
|
||||
Since students are related to a single project, we will
|
||||
allow editing them right the on the CMS interface in the `Project` page type.
|
||||
allow editing them right on the CMS interface in the `Project` page type.
|
||||
We do this through a powerful field called `[GridField](/reference/grid-field)`.
|
||||
All customization to fields for a page type are managed through a method called
|
||||
`getCMSFields()`, so let's add it there:
|
||||
@ -151,10 +151,10 @@ All customization to fields for a page type are managed through a method called
|
||||
}
|
||||
|
||||
This creates a tabular field, which lists related student records, one row at a time.
|
||||
Its empty by default, but you can add new students as required,
|
||||
It's empty by default, but you can add new students as required,
|
||||
or relate them to the project by typing in the box above the table.
|
||||
|
||||
In our case, want to manage those records, edit their details, and add new ones.
|
||||
In our case, we want to manage those records, edit their details, and add new ones.
|
||||
To accomplish this, we have added a specific `[api:GridFieldConfig]`.
|
||||
While we could've built the config from scratch, there's several
|
||||
preconfigured instances. The `GridFieldConfig_RecordEditor` default configures
|
||||
@ -170,24 +170,24 @@ We call `setDisplayFields()` directly on the component responsible for their ren
|
||||
using the `[ModelAdmin](reference/modeladmin)` interface instead.
|
||||
</div>
|
||||
|
||||
![tutorial:tutorial5_project_creation.jpg](/_images/tutorial5_project_creation.jpg)
|
||||
![tutorial:tutorial5_project_creation.jpg](../_images/tutorial5_project_creation.jpg)
|
||||
|
||||
Select each `Project` page you have created before,
|
||||
go in the tab panel called "Students", and add all students as required,
|
||||
by clicking on the link **Add Student** of your *GridField* table.
|
||||
|
||||
![tutorial:tutorial5_addNew.jpg](/_images/tutorial5_addNew.jpg)
|
||||
![tutorial:tutorial5_addNew.jpg](../_images/tutorial5_addNew.jpg)
|
||||
|
||||
Once you have added all the students, and selected their projects, it should look a little like this:
|
||||
|
||||
![tutorial:tutorial5_students.jpg](/_images/tutorial5_students.jpg)
|
||||
![tutorial:tutorial5_students.jpg](../_images/tutorial5_students.jpg)
|
||||
|
||||
### Many-many relationships: Mentor
|
||||
|
||||
Now we have a fairly good picture of how students relate to their projects.
|
||||
But students generally have somebody looking them over the shoulder.
|
||||
In our case, that's the "mentor". Each project can have many of them,
|
||||
and each mentor can be have one or more projects. They're busy guys!
|
||||
and each mentor can have one or more projects. They're busy guys!
|
||||
This is called a *many-many* relationship.
|
||||
|
||||
The first step is to create the `Mentor` object and set the relation with the `Project` page type.
|
||||
@ -250,13 +250,13 @@ In the CMS, open one of your `Project` pages and select the "Mentors" tab.
|
||||
Add all the mentors listed [above](#what-are-we-working-towards)
|
||||
by clicking on the **Add Mentor** button.
|
||||
|
||||
![tutorial:tutorial5_module_creation.jpg](/_images/tutorial5_module_creation.jpg)
|
||||
![tutorial:tutorial5_module_creation.jpg](../_images/tutorial5_module_creation.jpg)
|
||||
|
||||
To associate the mentor with a project, select one of the mentors, and click on the projects tab. Add all the projects a mentor is associated with (see the [list](/tutorials/dataobject_relationship_management#What_are_we_working_towards?)), by typing the name in "Find Projects by Page name" and clicking the "Link Existing" button.
|
||||
You will notice that you are able to select the same `Project` for multiple mentors.
|
||||
This is the definition of a **many-to-many** relation.
|
||||
|
||||
![tutorial:tutorial5_module_selection.jpg](/_images/tutorial5_module_selection.jpg)
|
||||
![tutorial:tutorial5_module_selection.jpg](../_images/tutorial5_module_selection.jpg)
|
||||
|
||||
|
||||
## Website Display
|
||||
@ -273,10 +273,10 @@ which lists all projects, and condenses their
|
||||
student and mentor relationships into a single line.
|
||||
You'll notice that there's no difference between
|
||||
accessing a "has-many" and "many-many" relationship
|
||||
in the template loops: To the template, its just
|
||||
in the template loops: to the template, it's just
|
||||
a named list of object.
|
||||
|
||||
![tutorial:tutorial5_projects_table.jpg](/_images/tutorial5_projects_table.jpg)
|
||||
![tutorial:tutorial5_projects_table.jpg](../_images/tutorial5_projects_table.jpg)
|
||||
|
||||
**themes/simple/templates/Layout/ProjectsHolder.ss**
|
||||
|
||||
@ -334,7 +334,7 @@ Creating the detail view for each `Project` page works in a very similar way.
|
||||
Given that we're in the context of a single project,
|
||||
we can access the "Students" and "Mentors" relationships directly in the template.
|
||||
|
||||
![tutorial:tutorial5_project.jpg](/_images/tutorial5_project.jpg)
|
||||
![tutorial:tutorial5_project.jpg](../_images/tutorial5_project.jpg)
|
||||
|
||||
**themes/simple/templates/Layout/Project.ss**
|
||||
|
||||
|
@ -5,9 +5,16 @@ introduction: The tutorials below take a step by step look at how to build a Sil
|
||||
|
||||
[CHILDREN]
|
||||
|
||||
## Video tutorials
|
||||
## Video lessons
|
||||
These include video screencasts, written tutorials and code examples to get you started working with SilverStripe websites.
|
||||
|
||||
* [How to set up a local development environment in SilverStripe](https://vimeo.com/108861537)
|
||||
* [Lesson 1: Creating your first theme](http://www.silverstripe.org/learn/lessons/lesson-1-creating-your-first-theme/)
|
||||
* [Lesson 2: Migrating static templates into your theme](http://www.silverstripe.org/learn/lessons/lesson-2-migrating-static-templates-into-your-theme/)
|
||||
* [Lesson 3: Adding dynamic content](http://www.silverstripe.org/learn/lessons/lesson-3/)
|
||||
* [Lesson 4: Working with multiple templates](http://www.silverstripe.org/learn/lessons/lesson-4-working-with-multiple-templates/)
|
||||
* [Lesson 5: The holder/page pattern](http://www.silverstripe.org/learn/lessons/lesson-5-the-holderpage-pattern/)
|
||||
|
||||
|
||||
## Help: If you get stuck
|
||||
|
||||
|
@ -118,7 +118,7 @@ Or, a better way is to use the `create` method.
|
||||
$player = Player::create();
|
||||
|
||||
<div class="notice" markdown='1'>
|
||||
Using the `create()` method provides chainability, which can create add elegance and brevity to your code, e.g. `Player::create()->write()`. More importantly, however, it will look up the class in the [Injector](../extending/injector) so that can the class can be overriden by [dependency injection](http://en.wikipedia.org/wiki/Dependency_injection).
|
||||
Using the `create()` method provides chainability, which can add elegance and brevity to your code, e.g. `Player::create()->write()`. More importantly, however, it will look up the class in the [Injector](../extending/injector) so that the class can be overriden by [dependency injection](http://en.wikipedia.org/wiki/Dependency_injection).
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@ summary: A Model-driven approach to defining your application UI.
|
||||
The ORM already has a lot of information about the data represented by a `DataObject` through its `$db` property, so
|
||||
SilverStripe will use that information to provide scaffold some interfaces. This is done though [api:FormScaffolder]
|
||||
to provide reasonable defaults based on the property type (e.g. a checkbox field for booleans). You can then further
|
||||
customize those fields as required.
|
||||
customise those fields as required.
|
||||
|
||||
## Form Fields
|
||||
|
||||
@ -32,7 +32,7 @@ An example is `DataObject`, SilverStripe will automatically create your CMS inte
|
||||
}
|
||||
}
|
||||
|
||||
To fully customize your form fields, start with an empty FieldList.
|
||||
To fully customise your form fields, start with an empty FieldList.
|
||||
|
||||
:::php
|
||||
<?php
|
||||
@ -53,11 +53,11 @@ To fully customize your form fields, start with an empty FieldList.
|
||||
|
||||
|
||||
You can also alter the fields of built-in and module `DataObject` classes through your own
|
||||
[DataExtension](../extensions), and a call to `DataExtension->updateCMSFields`.
|
||||
[DataExtension](/developer_guides/extending/extensions), and a call to `DataExtension->updateCMSFields`.
|
||||
|
||||
## Searchable Fields
|
||||
|
||||
The `$searchable_fields` property uses a mixed array format that can be used to further customize your generated admin
|
||||
The `$searchable_fields` property uses a mixed array format that can be used to further customise your generated admin
|
||||
system. The default is a set of array values listing the fields.
|
||||
|
||||
:::php
|
||||
@ -218,7 +218,7 @@ Non-textual elements (such as images and their manipulations) can also be used i
|
||||
);
|
||||
}
|
||||
|
||||
## Related Documenation
|
||||
## Related Documentation
|
||||
|
||||
* [SearchFilters](searchfilters)
|
||||
|
||||
|
@ -45,7 +45,7 @@ the Site Configuration panel (http://yoursite.com/admin/settings)
|
||||
A `theme` within SilverStripe is simply a collection of templates and other front end assets such as javascript and css.
|
||||
located within the `themes` directory.
|
||||
|
||||
![themes:basicfiles.gif](//_images/basicfiles.gif)
|
||||
![themes:basicfiles.gif](../../_images/basicfiles.gif)
|
||||
|
||||
## Submitting your theme to SilverStripe
|
||||
|
||||
|
@ -55,7 +55,7 @@ The reason it's standard practice to name the form function 'Form' is so that we
|
||||
|
||||
If you now create a ContactPage in the CMS (making sure you have rebuilt the database and flushed the templates /dev/build?flush=all) and visit the page, you will now see a contact form.
|
||||
|
||||
![](..//_images/howto_contactForm.jpg)
|
||||
![](../../../_images/howto_contactForm.jpg)
|
||||
|
||||
|
||||
Now that we have a contact form, we need some way of collecting the data submitted. We do this by creating a function on the controller with the same name as the form action. In this case, we create the function 'submit' on the ContactPage_Controller class.
|
||||
|
@ -125,15 +125,13 @@ An example using the `MyFactory` service to create instances of the `MyService`
|
||||
Injector:
|
||||
MyService:
|
||||
factory: MyFactory
|
||||
MyFactory:
|
||||
class: MyFactoryImplementation
|
||||
|
||||
**mysite/code/MyFactoryImplementation.php**
|
||||
**mysite/code/MyFactory.php**
|
||||
|
||||
:::php
|
||||
<?php
|
||||
|
||||
class MyFactoryImplementation implements SilverStripe\Framework\Injector\Factory {
|
||||
class MyFactory implements SilverStripe\Framework\Injector\Factory {
|
||||
|
||||
public function create($service, array $params = array()) {
|
||||
return new MyServiceImplementation();
|
||||
|
@ -43,7 +43,7 @@ This is the least desirable way of extending the `[api:Member]` class. It's bett
|
||||
(see below).
|
||||
</div>
|
||||
|
||||
You can defined subclasses of `[api:Member]` to add extra fields or functionality to the built-in membership system.
|
||||
You can define subclasses of `[api:Member]` to add extra fields or functionality to the built-in membership system.
|
||||
|
||||
:::php
|
||||
class MyMember extends Member {
|
||||
|
@ -8,7 +8,7 @@ site you have to figure this stuff out, and it's not entirely obvious.
|
||||
There are a number of ways to restrict access in SilverStripe. In the security tab in the CMS you can create groups
|
||||
that have access to certain parts. The options can be found on the [permissions](/reference/permission) documentation.
|
||||
|
||||
Once you have groups, you can set access for each page for a particular groups. This can be:
|
||||
Once you have groups, you can set access for each page for a particular group. This can be:
|
||||
* anyone;
|
||||
* any person who is logged in;
|
||||
* a specific group.
|
||||
|
@ -454,16 +454,20 @@ file in the assets directory. This requires PHP to be loaded as an Apache modul
|
||||
php_flag engine off
|
||||
Options -ExecCGI -Includes -Indexes
|
||||
|
||||
### Don't allow access to .yml files
|
||||
### Don't allow access to YAML files
|
||||
|
||||
Yaml files are often used to store sensitive or semi-sensitive data for use by SilverStripe framework (for instance,
|
||||
configuration and test fixtures).
|
||||
YAML files are often used to store sensitive or semi-sensitive data for use by
|
||||
SilverStripe, such as configuration files. We block access to any files
|
||||
with a `.yml` or `.yaml` extension through the default web server rewriting rules.
|
||||
If you need users to access files with this extension,
|
||||
you can bypass the rules for a specific directory.
|
||||
Here's an example for a `.htaccess` file used by the Apache web server:
|
||||
|
||||
You should therefore block access to all yaml files (extension .yml) by default, and white list only yaml files
|
||||
you need to serve directly.
|
||||
<Files *.yml>
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Files>
|
||||
|
||||
See [Apache](/installation/webserver) and [Nginx](/installation/nginx) installation documentation for details
|
||||
specific to your web server
|
||||
|
||||
### User uploaded files
|
||||
|
||||
@ -487,6 +491,7 @@ take the following precautions:
|
||||
|
||||
See [the Adobe Flash security page](http://www.adobe.com/devnet/flashplayer/security.html) for more information.
|
||||
|
||||
|
||||
ADMIN privileged users may be allowed to override the above upload restrictions if the
|
||||
`File.apply_restrictions_to_admin` config is set to false. By default this is true, which enforces these
|
||||
restrictions globally.
|
||||
|
@ -118,7 +118,7 @@ We're going to use our knowledge from the previous example to import a more soph
|
||||
|
||||
Sample CSV Content
|
||||
|
||||
"SpielerNummer","Name","Geburtsdatum","Gruppe"
|
||||
"Number","Name","Birthday","Team"
|
||||
11,"John Doe",1982-05-12,"FC Bayern"
|
||||
12,"Jane Johnson", 1982-05-12,"FC Bayern"
|
||||
13,"Jimmy Dole",,"Schalke 04"
|
||||
@ -171,11 +171,11 @@ Sample implementation of a custom loader. Assumes a CSV-file in a certain format
|
||||
public $columnMap = array(
|
||||
'Number' => 'PlayerNumber',
|
||||
'Name' => '->importFirstAndLastName',
|
||||
'Geburtsdatum' => 'Birthday',
|
||||
'Gruppe' => 'Team.Title',
|
||||
'Birthday' => 'Birthday',
|
||||
'Team' => 'Team.Title',
|
||||
);
|
||||
public $duplicateChecks = array(
|
||||
'SpielerNummer' => 'PlayerNumber'
|
||||
'Number' => 'PlayerNumber'
|
||||
);
|
||||
public $relationCallbacks = array(
|
||||
'Team.Title' => array(
|
||||
|
@ -21,19 +21,19 @@ All files, images and folders in the 'assets' directory are stored in the databa
|
||||
|
||||
If you have the CMS module installed, you can manage files, folders and images in the "Files" section of the CMS. Inside this section, you will see a list of files and folders like below:
|
||||
|
||||
![](//_images/assets.png)
|
||||
![](../../_images/assets.png)
|
||||
|
||||
You can click on any file to edit it, or click on any folder to open it. To delete a file or a folder, simply click the red 'X' symbol next to it. If you click to open a folder, you can go back up one level by clicking the 'up' arrow above the folder name (highlighted below):
|
||||
|
||||
![](//_images/assets_up.png)
|
||||
![](../../_images/assets_up.png)
|
||||
|
||||
Once you click to edit a file, you will see a form similar to the one below, in which you can edit the file's title, filename, owner, or even change which folder the file is located in:
|
||||
|
||||
![](//_images/assets_editform.png)
|
||||
![](../../_images/assets_editform.png)
|
||||
|
||||
You may also notice the 'Sync files' button (highlighted below). This button allows CMS users to 'synchronise' the database (remember, all files/folders are stored as database records) with the filesystem. This is particularly useful if someone has uploaded or removed files/folders via FTP, for example.
|
||||
|
||||
![](//_images/assets_sync.png)
|
||||
![](../../_images/assets_sync.png)
|
||||
|
||||
## Upload
|
||||
|
||||
|
@ -39,7 +39,7 @@ example, the tab panels have be applied in the CMS form before the form itself i
|
||||
avoid incorrect dimensions.
|
||||
</div>
|
||||
|
||||
![Layout variations](/_images/cms-architecture.png)
|
||||
![Layout variations](../../_images/cms-architecture.png)
|
||||
|
||||
## Layout API
|
||||
|
||||
|
@ -274,10 +274,12 @@ request](http://docs.jquery.com/Frequently_Asked_Questions#Why_do_my_events_stop
|
||||
jQuery is based around collections of DOM elements, the library functions typically handle multiple elements (where it
|
||||
makes sense). Encapsulate your code by nesting your jQuery commands inside a `jQuery().each()` call.
|
||||
|
||||
Example: ComplexTableField implements a paginated table with a pop-up for displaying
|
||||
|
||||
:::js
|
||||
$('.MyCustomField').each(function() {
|
||||
// This is the over code for the elements inside a MyCustomField.
|
||||
$(this).hover(
|
||||
$('div.ComplexTableField').each(function() {
|
||||
// This is the over code for the tr elements inside a ComplexTableField.
|
||||
$(this).find('tr').hover(
|
||||
// ...
|
||||
);
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
# How to customize the CMS tree #
|
||||
# How to customize the CMS tree
|
||||
|
||||
## Overview
|
||||
|
||||
@ -12,7 +12,7 @@ which recursively collects all nodes based on various filtering criteria.
|
||||
The node strictly just has to implement the `[api:Hierarchy]` extension,
|
||||
but in the CMS usually is a `[api:SiteTree]` object.
|
||||
|
||||
## Add status lozenges to tree nodes ##
|
||||
## Add status lozenges to tree nodes
|
||||
|
||||
A tree node in CMS could be rendered with lot of extra information but a node title, such as a
|
||||
link that wraps around the node title, a node's id which is given as id attribute of the node
|
||||
@ -41,7 +41,7 @@ code like this:
|
||||
...
|
||||
|
||||
By applying the proper style sheet, the snippet html above could produce the look of:
|
||||
![Page Node Screenshot](..//_images/tree_node.png "Page Node")
|
||||
![Page Node Screenshot](../../../_images/tree_node.png "Page Node")
|
||||
|
||||
SiteTree is a `[api:DataObject]` which is versioned by `[api:Versioned]` extension.
|
||||
Each node can optionally have publication status flags, e.g. "Removed from draft".
|
||||
@ -58,7 +58,7 @@ be used for flagging anything you like, we should keep this lozenge to show vers
|
||||
status, while let `SiteTree->CMSTreeClasses()` to deal with other customised classes, which
|
||||
will be used for the class attribute of <li> tag of the tree node.
|
||||
|
||||
### Add new flag ###
|
||||
### Add new flag
|
||||
__Example: using a subclass__
|
||||
|
||||
:::php
|
||||
@ -76,6 +76,6 @@ __Example: using a subclass__
|
||||
|
||||
The above subclass of `[api:SiteTree]` will add a new flag for indicating its
|
||||
__'Scheduled To Publish'__ status. The look of the page node will be changed
|
||||
from ![Normal Page Node](..//_images/page_node_normal.png) to ![Scheduled Page Node](..//_images/page_node_scheduled.png). The getStatusFlags has an `updateStatusFlags()`
|
||||
from ![Normal Page Node](../../../_images/page_node_normal.png) to ![Scheduled Page Node](../../../_images/page_node_scheduled.png). The getStatusFlags has an `updateStatusFlags()`
|
||||
extension point, so the flags can be modified through `DataExtension` rather than
|
||||
inheritance as well. Deleting existing flags works by simply unsetting the array key.
|
||||
|
@ -6,7 +6,7 @@ summary: Creating your own custom data or content reports.
|
||||
Reports are a useful feature in the CMS designed to provide a view of your data or content. You can access
|
||||
the site reports by clicking *Reports* in the left hand side bar and selecting the report you wish to view.
|
||||
|
||||
![](/_images/sitereport.png)
|
||||
![](../../../_images/sitereport.png)
|
||||
|
||||
|
||||
## Default reports
|
||||
|
@ -2,14 +2,13 @@ title: Cookies
|
||||
summary: A set of static methods for manipulating PHP cookies.
|
||||
|
||||
# Cookies
|
||||
## Accessing and Manipulating Cookies
|
||||
|
||||
Cookies are a mechanism for storing data in the remote browser and thus tracking or identifying return users.
|
||||
|
||||
SilverStripe uses cookies for remembering users preferences. Application code can modify a users cookies through
|
||||
the [api:Cookie] class. This class mostly follows the PHP API.
|
||||
|
||||
### set
|
||||
## set
|
||||
|
||||
Sets the value of cookie with configuration.
|
||||
|
||||
@ -18,7 +17,7 @@ Sets the value of cookie with configuration.
|
||||
|
||||
// Cookie::set('MyApplicationPreference', 'Yes');
|
||||
|
||||
### get
|
||||
## get
|
||||
|
||||
Returns the value of cookie.
|
||||
|
||||
@ -28,7 +27,7 @@ Returns the value of cookie.
|
||||
// Cookie::get('MyApplicationPreference');
|
||||
// returns 'Yes'
|
||||
|
||||
### force_expiry
|
||||
## force_expiry
|
||||
|
||||
Clears a given cookie.
|
||||
|
||||
@ -58,7 +57,7 @@ from the browser.
|
||||
|
||||
Cookie::get('cookie1');
|
||||
|
||||
### Resetting the Cookie_Backend state
|
||||
## Resetting the Cookie_Backend state
|
||||
|
||||
Assuming that your application hasn't messed around with the `$_COOKIE` superglobal, you can reset the state of your
|
||||
`Cookie_Backend` by simply unregistering the `CookieJar` service with `Injector`. Next time you access `Cookie` it'll
|
||||
@ -96,32 +95,6 @@ If you need to implement your own Cookie_Backend you can use the injector system
|
||||
|
||||
To be a valid backend your class must implement the [api:Cookie_Backend] interface.
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Sent vs Received Cookies
|
||||
|
||||
Sometimes it's useful to be able to tell if a cookie was set by the process (thus will be sent to the browser) or if it
|
||||
came from the browser as part of the request.
|
||||
|
||||
Using the `Cookie_Backend` we can do this like such:
|
||||
|
||||
:::php
|
||||
Cookie::set('CookieName', 'CookieVal');
|
||||
|
||||
Cookie::get('CookieName'); //gets the cookie as we set it
|
||||
|
||||
//will return the cookie as it was when it was sent in the request
|
||||
Cookie::get('CookieName', false);
|
||||
|
||||
|
||||
### Accessing all the cookies at once
|
||||
|
||||
One can also access all of the cookies in one go using the `Cookie_Backend`
|
||||
|
||||
:::php
|
||||
Cookie::get_inst()->getAll(); //returns all the cookies including ones set during the current process
|
||||
|
||||
Cookie::get_inst()->getAll(false); //returns all the cookies in the request
|
||||
|
||||
## API Documentation
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
# 3.1.9
|
||||
|
||||
<<<<<<< HEAD
|
||||
# Overview
|
||||
|
||||
This release replaces the 3.1.8 release, and resolves an issue where basic authentication would not work when PHP is running under CGI mode with Apache.
|
||||
@ -12,3 +13,63 @@ This release replaces the 3.1.8 release, and resolves an issue where basic authe
|
||||
|
||||
## Changelog
|
||||
|
||||
=======
|
||||
## Upgrading
|
||||
|
||||
### File permissions
|
||||
|
||||
This release makes an important change to File DataObject permissions in order to close a vulnerability in
|
||||
file modification privileges.
|
||||
|
||||
By default the minimum necessary permission required by any user to modify files has been changed
|
||||
to CMS_ACCESS_AssetAdmin. If you need unauthenticated users, or users with other rights, to edit certain
|
||||
files, then you will need to customise this.
|
||||
|
||||
E.g.
|
||||
|
||||
:::php
|
||||
<?php
|
||||
class FileSecurityExtension extends DataExtension {
|
||||
public function canEdit($member) {
|
||||
return Permission::checkMember($member, 'MyCustomPermission');
|
||||
}
|
||||
}
|
||||
|
||||
An example use case is when you want to use UploadField on the frontend, where files could be uploaded
|
||||
by non-admin users, and your above logic will need to ensure that those users can edit their own files
|
||||
after they have uploaded it.
|
||||
|
||||
## Security
|
||||
|
||||
This release includes an important security fix.
|
||||
|
||||
* 2015-01-12 [c49f164](https://github.com/silverstripe/silverstripe-framework/commit/c49f164) Fix file and uploadfield permissions [SS-2014-018](http://www.silverstripe.org/software/download/security-releases/ss-2014-018-open-file-permissions).
|
||||
|
||||
### Features and Enhancements
|
||||
|
||||
* 2014-11-21 [31b5a9d](https://github.com/silverstripe/sapphire/commit/31b5a9d) Allow CMS re-authentication to be completely disabled if necessary (Damian Mooyman)
|
||||
* 2014-12-10 [fba6880](https://github.com/silverstripe/sapphire/commit/fba6880) Additional extension points for Tiny MCE editing, for when images are regenerated and manipulating the HTML prior to a save (Gordon Anderson)
|
||||
* 2014-11-13 [d7eb275](https://github.com/silverstripe/sapphire/commit/d7eb275) Make the record count in GridFieldFooter optional (Jeremy Shipman)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* 2015-01-08 [a02adf6](https://github.com/silverstripe/sapphire/commit/a02adf6) Uneccessary class replacement (Michael Strong)
|
||||
* 2014-12-18 [5637431](https://github.com/silverstripe/sapphire/commit/5637431) The method 'name' does not exist on 'Form' (Elvinas L)
|
||||
* 2014-12-15 [6582162](https://github.com/silverstripe/sapphire/commit/6582162) How to folder on forms (Cam Findlay)
|
||||
* 2014-12-11 [b5c361a](https://github.com/silverstripe/sapphire/commit/b5c361a) GD - check file exists before getimagesize (Will Morgan)
|
||||
* 2014-12-09 [6bdd30c](https://github.com/silverstripe/sapphire/commit/6bdd30c) Fix gridfield storing duplicate data in session (Damian Mooyman)
|
||||
* 2014-12-09 [3ac705f](https://github.com/silverstripe/sapphire/commit/3ac705f) Feedback to name the fields section to "field types" to make it clearer what the section is about. (Cam Findlay)
|
||||
* 2014-12-09 [e9fd03b](https://github.com/silverstripe/sapphire/commit/e9fd03b) use GFMD code blocks to fix code formatting consistency. (Cam Findlay)
|
||||
* 2014-11-25 [01989aa](https://github.com/silverstripe/sapphire/commit/01989aa) Manifest flushing (Jonathon Menz)
|
||||
* 2014-11-24 [7384d01](https://github.com/silverstripe/sapphire/commit/7384d01) DataDifferencer was trying to compare fields, even if the fields didn't exist causing an error. (micmania1)
|
||||
* 2014-11-18 [2bdfd65](https://github.com/silverstripe/sapphire/commit/2bdfd65) Security::findAnAdministrator doesn't always find an admin (Damian Mooyman)
|
||||
* 2014-11-10 [85b4ba1](https://github.com/silverstripe/sapphire/commit/85b4ba1) DataObject::db() doesn't respect overloaded db types (fixes #3620) (Loz Calver)
|
||||
* 2014-10-03 [9d888d5](https://github.com/silverstripe/silverstripe-cms/commit/9d888d5) Fixed SearchForm not calling getTemplate() in forTemplate() (Stephen McMahon)
|
||||
* 2014-09-02 [1f4f5e6](https://github.com/silverstripe/sapphire/commit/1f4f5e6) Fix versioned Versioned is not writing Version to _version tables for subclasses of Version dataobjects which have their own DB fields - Fix disjoint of ID / RecordID (which should be the same) - Fix calculation of new record version - Fix use of empty vs !isset to check for existing version (Damian Mooyman)
|
||||
|
||||
## Changelog
|
||||
|
||||
* [framework](https://github.com/silverstripe/silverstripe-framework/releases/tag/3.1.9)
|
||||
* [cms](https://github.com/silverstripe/silverstripe-cms/releases/tag/3.1.9)
|
||||
* [installer](https://github.com/silverstripe/silverstripe-installer/releases/tag/3.1.9)
|
||||
>>>>>>> composer/3.1
|
||||
|
29
docs/en/04_Changelogs/rc/3.1.9-rc1.md
Normal file
29
docs/en/04_Changelogs/rc/3.1.9-rc1.md
Normal file
@ -0,0 +1,29 @@
|
||||
# 3.1.9-rc1
|
||||
|
||||
### Features and Enhancements
|
||||
|
||||
* 2014-11-21 [31b5a9d](https://github.com/silverstripe/sapphire/commit/31b5a9d) Allow CMS re-authentication to be completely disabled if necessary (Damian Mooyman)
|
||||
* 2014-12-10 [fba6880](https://github.com/silverstripe/sapphire/commit/fba6880) Additional extension points for Tiny MCE editing, for when images are regenerated and manipulating the HTML prior to a save (Gordon Anderson)
|
||||
* 2014-11-13 [d7eb275](https://github.com/silverstripe/sapphire/commit/d7eb275) Make the record count in GridFieldFooter optional (Jeremy Shipman)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
* 2015-01-08 [a02adf6](https://github.com/silverstripe/sapphire/commit/a02adf6) Uneccessary class replacement (Michael Strong)
|
||||
* 2014-12-18 [5637431](https://github.com/silverstripe/sapphire/commit/5637431) The method 'name' does not exist on 'Form' (Elvinas L)
|
||||
* 2014-12-15 [6582162](https://github.com/silverstripe/sapphire/commit/6582162) How to folder on forms (Cam Findlay)
|
||||
* 2014-12-11 [b5c361a](https://github.com/silverstripe/sapphire/commit/b5c361a) GD - check file exists before getimagesize (Will Morgan)
|
||||
* 2014-12-09 [6bdd30c](https://github.com/silverstripe/sapphire/commit/6bdd30c) Fix gridfield storing duplicate data in session (Damian Mooyman)
|
||||
* 2014-12-09 [3ac705f](https://github.com/silverstripe/sapphire/commit/3ac705f) Feedback to name the fields section to "field types" to make it clearer what the section is about. (Cam Findlay)
|
||||
* 2014-12-09 [e9fd03b](https://github.com/silverstripe/sapphire/commit/e9fd03b) use GFMD code blocks to fix code formatting consistency. (Cam Findlay)
|
||||
* 2014-11-25 [01989aa](https://github.com/silverstripe/sapphire/commit/01989aa) Manifest flushing (Jonathon Menz)
|
||||
* 2014-11-24 [7384d01](https://github.com/silverstripe/sapphire/commit/7384d01) DataDifferencer was trying to compare fields, even if the fields didn't exist causing an error. (micmania1)
|
||||
* 2014-11-18 [2bdfd65](https://github.com/silverstripe/sapphire/commit/2bdfd65) Security::findAnAdministrator doesn't always find an admin (Damian Mooyman)
|
||||
* 2014-11-10 [85b4ba1](https://github.com/silverstripe/sapphire/commit/85b4ba1) DataObject::db() doesn't respect overloaded db types (fixes #3620) (Loz Calver)
|
||||
* 2014-10-03 [9d888d5](https://github.com/silverstripe/silverstripe-cms/commit/9d888d5) Fixed SearchForm not calling getTemplate() in forTemplate() (Stephen McMahon)
|
||||
* 2014-09-02 [1f4f5e6](https://github.com/silverstripe/sapphire/commit/1f4f5e6) Fix versioned Versioned is not writing Version to _version tables for subclasses of Version dataobjects which have their own DB fields - Fix disjoint of ID / RecordID (which should be the same) - Fix calculation of new record version - Fix use of empty vs !isset to check for existing version (Damian Mooyman)
|
||||
|
||||
## Changelog
|
||||
|
||||
* [framework](https://github.com/silverstripe/silverstripe-framework/releases/tag/3.1.9-rc1)
|
||||
* [cms](https://github.com/silverstripe/silverstripe-cms/releases/tag/3.1.9-rc1)
|
||||
* [installer](https://github.com/silverstripe/silverstripe-installer/releases/tag/3.1.9-rc1)
|
@ -32,18 +32,10 @@ If the issue does look like a new bug:
|
||||
* Describe your environment as detailed as possible: SilverStripe version, Browser, PHP version, Operating System, any installed SilverStripe modules.
|
||||
* *(optional)* [Submit a pull request](/misc/contributing/code) which fixes the issue.
|
||||
|
||||
Ensure you give us enough information to diagnose your issue:
|
||||
|
||||
* Switch your site to "[dev mode](/developer_guides/debugging)". Paste any PHP errors with their stacktraces. A generic "Server Error" message is not enough information.
|
||||
* If you suspect a JavaScript or CSS bug, check if it appears in other browsers
|
||||
* Use the [Chrome dev tools](https://developers.google.com/chrome-developer-tools/docs/overview) or [Firefox dev tools](https://developer.mozilla.org/en-US/docs/Tools)
|
||||
* Use the JavaScript console in your browser to determine if any errors happened there, and paste the complete info into issue description.
|
||||
* Use the "Network" panel to determine if any XHR ("Ajax") requests have returned errors, and paste the HTTP headers as well as HTTP response body into the issue description.
|
||||
|
||||
Lastly, don't get your hopes up too high. Unless your issue is a blocker affecting a large
|
||||
number of users, don't expect SilverStripe developers to jump onto it right away.
|
||||
Your issue is a starting point where others with the same problem can collaborate
|
||||
with you to develop a fix.
|
||||
Lastly, don't get your hopes up too high. Unless your issue is a blocker
|
||||
affecting a large number of users, don't expect SilverStripe developers to jump
|
||||
onto it right way. Your issue is a starting point where others with the same
|
||||
problem can collaborate with you to develop a fix.
|
||||
|
||||
## Feature Requests
|
||||
|
||||
|
@ -93,13 +93,8 @@ In the event of a confirmed vulnerability in SilverStripe core, we will take the
|
||||
|
||||
* Acknowledge to the reporter that we’ve received the report and that a fix is forthcoming. We’ll give a rough
|
||||
timeline and ask the reporter to keep the issue confidential until we announce it.
|
||||
* Assign a unique identifier to the issue in the format `SS-<year>-<count>`,
|
||||
where `<count>` is a padded three digit number counting issues for the year.
|
||||
Example: `SS-2013-001` would be the first of the year `2013`.
|
||||
Additionally, [CVE](http://cve.mitre.org) numbers are accepted.
|
||||
* Halt all other development as long as is needed to develop a fix, including patches against the current and one
|
||||
previous major release (if applicable).
|
||||
* Pre-announce the upcoming security release to a private mailing list of important stakeholders (see below).
|
||||
* We will inform you about resolution and [announce](http://groups.google.com/group/silverstripe-announce) a
|
||||
[new release](http://silverstripe.org/security-releases/) publically.
|
||||
|
||||
@ -118,30 +113,3 @@ each vulnerability. The rating indicates how important an update is:
|
||||
| **Important** | Important releases should be evaluated immediately. These issues allow an attacker to compromise a site's data and should be fixed within days. *Example: SQL injection.* |
|
||||
| **Moderate** | Releases of moderate severity should be applied as soon as possible. They allow the unauthorized editing or creation of content. *Examples: Cross Site Scripting (XSS) in template helpers.* |
|
||||
| **Low** | Low risk releases fix information disclosure and read-only privilege escalation vulnerabilities. These updates should also be applied as soon as possible, but with an impact-dependent priority. *Example: Exposure of the core version number, Cross Site Scripting (XSS) limited to the admin interface.* |
|
||||
|
||||
### Pre-announce Mailinglist
|
||||
|
||||
In addition to our public disclosure process, we maintain a private mailinglist
|
||||
where upcoming security releases will be pre-announced. Members in this list will receive a security
|
||||
pre-announcement as soon as it has been sufficiently researched,
|
||||
alongside a timeline for the upcoming release. This will happen a few days before
|
||||
the announcement goes public alongside new release, and most likely before a patch has been developed.
|
||||
|
||||
Since we’ll distribute sensitive info on unpatched vulnerabilities in this list,
|
||||
the selection criteria for joining naturally has to be strict.
|
||||
Applicants should provide references within the community,
|
||||
as well as a demonstrated need for this level of information (e.g. a large website with sensitive customer data).
|
||||
You don’t need to be a client of SilverStripe Ltd to get on board,
|
||||
but we will need to perform some low-touch background checks to ensure identity.
|
||||
Please contact security@silverstripe.org for details.
|
||||
|
||||
## Quality Assurance and Testing
|
||||
|
||||
The quality of our software is important to us, and we continously test it for regressions
|
||||
through a broad suite of unit and integration tests. Most of these run on
|
||||
[Travis CI](http://travis-ci.com), and results are publicly available
|
||||
for the [framework](https://travis-ci.org/silverstripe/silverstripe-framework) and
|
||||
[cms](https://travis-ci.org/silverstripe/silverstripe-cms) modules.
|
||||
In addition, some build configurations (e.g. running on Windows) are tested
|
||||
through a [TeamCity](http://www.jetbrains.com/teamcity/) instance hosted at
|
||||
[teamcity.silverstripe.com](http://teamcity.silverstripe.com) (click "Login as guest").
|
||||
|
@ -46,13 +46,9 @@ documentation. This helps prevent our documentation from getting out of date.
|
||||
|
||||
## Repositories
|
||||
|
||||
* End-user: [userhelp.silverstripe.org](http://userhelp.silverstripe.org) - a custom SilverStripe project (not open sourced at the moment).
|
||||
* Developer Guides: [doc.silverstripe.org](http://doc.silverstripe.org) - powered by a
|
||||
SilverStripe project that uses the ["docsviewer" module](https://github.com/silverstripe/silverstripe-docsviewer)
|
||||
to convert Markdown formatted files into searchable HTML pages with index lists.
|
||||
Its contents are fetched from different releases automatically every couple of minutes.
|
||||
* Developer API Documentation: [api.silverstripe.org](http://api.silverstripe.org) - powered by a customized
|
||||
[phpDocumentor](http://www.phpdoc.org/) template, and is regenerated automatically every night.
|
||||
* End-user: [userhelp.silverstripe.org](http://github.com/silverstripe/userhelp.silverstripe.org)
|
||||
* Developer guides: [doc.silverstripe.org](http://github.com/silverstripe/doc.silverstripe.org)
|
||||
* Developer API documentation: [api.silverstripe.org](http://github.com/silverstripe/api.silverstripe.org)
|
||||
|
||||
## Source control
|
||||
|
||||
|
34
docs/en/05_Contributing/06_Core_committers.md
Normal file
34
docs/en/05_Contributing/06_Core_committers.md
Normal file
@ -0,0 +1,34 @@
|
||||
# Core Committers
|
||||
The core committers team is reviewed approximately annually, new members are added based on quality contributions to SilverStipe code and outstanding community participation.
|
||||
|
||||
## Core committer team
|
||||
* [Damian Mooyman](https://github.com/tractorcow/)
|
||||
* [Daniel Hensby](https://github.com/dhensby)
|
||||
* [Hamish Friedlander](https://github.com/hafriedlander)
|
||||
* [Ingo Schommer](https://github.com/chillu)
|
||||
* [Loz Calver](https://github.com/kinglozzer)
|
||||
* [Mateusz Uzdowski](https://github.com/mateusz/)
|
||||
* [Sam Minnée](https://github.com/sminnee)
|
||||
* [Sean Harvey](https://github.com/halkyon/)
|
||||
* [Stig Lindqvist](https://github.com/stojg)
|
||||
* [Will Morgan](https://github.com/willmorgan)
|
||||
* [Will Rossiter](https://github.com/wilr/)
|
||||
|
||||
## House rules for the core committer team
|
||||
|
||||
The "core committers" consist of everybody with write permissions to our codebase.
|
||||
With great power comes great responsibility, so we have agreed on certain expectations:
|
||||
|
||||
* Be friendly, encouraging and constructive towards other community members
|
||||
* Frequently review pull requests and new issues (in particular, respond quickly to @mentions)
|
||||
* Treat issues according to our [issue guidelines](issues_and_bugs)
|
||||
* Don't commit directly to core, raise pull requests instead (except trivial fixes)
|
||||
* Only merge code you have tested and fully understand. If in doubt, ask for a second opinion.
|
||||
* Ensure contributions have appropriate [test coverage](/topics/testing), are documented, and pass our [coding conventions](/getting_started/coding-conventions)
|
||||
* Keep the codebase "releasable" at all times (check our [release process](release_process))
|
||||
* API changes and non-trivial features should not be merged into release branches.
|
||||
* API changes on master should not be merged until they have the buy-in of at least two core committers (or better, through the [core mailing list](https://groups.google.com/forum/#!forum/silverstripe-dev))
|
||||
* Be inclusive. Ensure a wide range of SilverStripe developers can obtain an understanding of your code and docs, and you're not the only one who can maintain it.
|
||||
* Avoid `git push --force`, and be careful with your git remotes (no accidental pushes)
|
||||
* Use your own forks to create feature branches
|
||||
|
@ -120,17 +120,17 @@ class File extends DataObject {
|
||||
* Otherwise, the files will be able to be uploaded but they won't be able to be served by the
|
||||
* webserver.
|
||||
*
|
||||
* - If you are running Apahce you will need to change assets/.htaccess
|
||||
* - If you are running Apache you will need to change assets/.htaccess
|
||||
* - If you are running IIS you will need to change assets/web.config
|
||||
*
|
||||
* Instructions for the change you need to make are included in a comment in the config file.
|
||||
*/
|
||||
private static $allowed_extensions = array(
|
||||
'','ace','arc','arj','asf','au','avi','bmp','bz2','cab','cda','css','csv','dmg','doc','docx',
|
||||
'','ace','arc','arj','asf','au','avi','bmp','bz2','cab','cda','css','csv','dmg','doc','docx','dotx','dotm',
|
||||
'flv','gif','gpx','gz','hqx','ico','jar','jpeg','jpg','js','kml', 'm4a','m4v',
|
||||
'mid','midi','mkv','mov','mp3','mp4','mpa','mpeg','mpg','ogg','ogv','pages','pcx','pdf','pkg',
|
||||
'png','pps','ppt','pptx','ra','ram','rm','rtf','sit','sitx','tar','tgz','tif','tiff',
|
||||
'txt','wav','webm','wma','wmv','xls','xlsx','zip','zipx',
|
||||
'png','pps','ppt','pptx','potx','potm','ra','ram','rm','rtf','sit','sitx','tar','tgz','tif','tiff',
|
||||
'txt','wav','webm','wma','wmv','xls','xlsx','xltx','xltm','zip','zipx',
|
||||
);
|
||||
|
||||
/**
|
||||
@ -326,7 +326,7 @@ class File extends DataObject {
|
||||
$result = $this->extendedCan('canEdit', $member);
|
||||
if($result !== null) return $result;
|
||||
|
||||
return true;
|
||||
return Permission::checkMember($member, 'CMS_ACCESS_AssetAdmin');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -421,11 +421,13 @@ class File extends DataObject {
|
||||
// $uploadField,
|
||||
new TextField("Title", _t('AssetTableField.TITLE','Title')),
|
||||
new TextField("Name", _t('AssetTableField.FILENAME','Filename')),
|
||||
new DropdownField("OwnerID", _t('AssetTableField.OWNER','Owner'), Member::mapInCMSGroups()),
|
||||
$ownerField
|
||||
= new DropdownField("OwnerID", _t('AssetTableField.OWNER','Owner'), Member::mapInCMSGroups()),
|
||||
$folderTree
|
||||
)
|
||||
)
|
||||
);
|
||||
$ownerField->setHasEmptyDefault(true);
|
||||
|
||||
// Folder has its own updateCMSFields hook
|
||||
if(!($this instanceof Folder)) $this->extend('updateCMSFields', $fields);
|
||||
|
@ -41,7 +41,7 @@ class GDBackend extends Object implements Image_Backend {
|
||||
|
||||
$this->cache = SS_Cache::factory('GDBackend_Manipulations');
|
||||
|
||||
if($filename) {
|
||||
if($filename && is_readable($filename)) {
|
||||
$this->cacheKey = md5(implode('_', array($filename, filemtime($filename))));
|
||||
$this->manipulation = implode('|', $args);
|
||||
|
||||
|
@ -13,8 +13,8 @@
|
||||
*
|
||||
* public function getCMSFields() {
|
||||
* $fields = parent::getCMSFields();
|
||||
* $field = DropdownField::create('GalleryID', 'Gallery', Gallery::get()->map('ID', 'Title'));
|
||||
* $field->setEmptyString('(Select one)');
|
||||
* $field = DropdownField::create('GalleryID', 'Gallery', Gallery::get()->map('ID', 'Title'))
|
||||
* ->setEmptyString('(Select one)');
|
||||
* $fields->addFieldToTab('Root.Content', $field, 'Content');
|
||||
* </code>
|
||||
*
|
||||
@ -33,7 +33,7 @@
|
||||
*
|
||||
* Example instantiation:
|
||||
* <code>
|
||||
* new DropdownField(
|
||||
* DropdownField::create(
|
||||
* 'Country',
|
||||
* 'Country',
|
||||
* array(
|
||||
@ -59,7 +59,7 @@
|
||||
*
|
||||
* Field construction:
|
||||
* <code>
|
||||
* new DropdownField(
|
||||
* DropdownField::create(
|
||||
* 'Country',
|
||||
* 'Country',
|
||||
* singleton('MyObject')->dbObject('Country')->enumValues()
|
||||
|
@ -110,8 +110,15 @@ class HtmlEditorField extends TextareaField {
|
||||
// Add default empty title & alt attributes.
|
||||
if(!$img->getAttribute('alt')) $img->setAttribute('alt', '');
|
||||
if(!$img->getAttribute('title')) $img->setAttribute('title', '');
|
||||
|
||||
// Use this extension point to manipulate images inserted using TinyMCE, e.g. add a CSS class, change default title
|
||||
// $image is the image, $img is the DOM model
|
||||
$this->extend('processImage', $image, $img);
|
||||
}
|
||||
|
||||
// optionally manipulate the HTML after a TinyMCE edit and prior to a save
|
||||
$this->extend('processHTML', $htmlValue);
|
||||
|
||||
// Store into record
|
||||
$record->{$this->name} = $htmlValue->getContent();
|
||||
}
|
||||
|
@ -1390,6 +1390,7 @@ class UploadField_ItemHandler extends RequestHandler {
|
||||
// Check item permissions
|
||||
$item = $this->getItem();
|
||||
if(!$item) return $this->httpError(404);
|
||||
if($item instanceof Folder) return $this->httpError(403);
|
||||
if(!$item->canDelete()) return $this->httpError(403);
|
||||
|
||||
// Delete the file from the filesystem. The file will be removed
|
||||
@ -1411,6 +1412,7 @@ class UploadField_ItemHandler extends RequestHandler {
|
||||
// Check item permissions
|
||||
$item = $this->getItem();
|
||||
if(!$item) return $this->httpError(404);
|
||||
if($item instanceof Folder) return $this->httpError(403);
|
||||
if(!$item->canEdit()) return $this->httpError(403);
|
||||
|
||||
Requirements::css(FRAMEWORK_DIR . '/css/UploadField.css');
|
||||
@ -1454,6 +1456,8 @@ class UploadField_ItemHandler extends RequestHandler {
|
||||
// Check item permissions
|
||||
$item = $this->getItem();
|
||||
if(!$item) return $this->httpError(404);
|
||||
if($item instanceof Folder) return $this->httpError(403);
|
||||
if(!$item->canEdit()) return $this->httpError(403);
|
||||
|
||||
$form->saveInto($item);
|
||||
$item->write();
|
||||
|
@ -841,7 +841,7 @@ class GridField_FormAction extends FormAction {
|
||||
'args' => $this->args,
|
||||
);
|
||||
|
||||
$id = preg_replace('/[^\w]+/', '_', uniqid('', true));
|
||||
$id = md5(serialize($state));
|
||||
Session::set($id, $state);
|
||||
$actionData['StateID'] = $id;
|
||||
|
||||
|
@ -147,10 +147,8 @@ class GridFieldPrintButton implements GridField_HTMLProvider, GridField_ActionPr
|
||||
} else {
|
||||
if ($currentController->Title) {
|
||||
$title = $currentController->Title;
|
||||
} else {
|
||||
if($form->Name()){
|
||||
$title = $form->Name();
|
||||
}
|
||||
} elseif ($form->getName()) {
|
||||
$title = $form->getName();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1100,6 +1100,7 @@ ss.editorWrappers['default'] = ss.editorWrappers.tinyMCE;
|
||||
validate: function() {
|
||||
var val = this.val(), orig = val;
|
||||
|
||||
val = $.trim(val);
|
||||
val = val.replace(/^https?:\/\//i, '');
|
||||
if (orig !== val) this.val(val);
|
||||
|
||||
|
47
javascript/lang/lt.js
Normal file
47
javascript/lang/lt.js
Normal file
@ -0,0 +1,47 @@
|
||||
// This file was generated by GenerateJavaScriptI18nTask from javascript/lang/src/lt.js.
|
||||
// See https://github.com/silverstripe/silverstripe-buildtools for details
|
||||
if(typeof(ss) == 'undefined' || typeof(ss.i18n) == 'undefined') {
|
||||
if(typeof(console) != 'undefined') console.error('Class ss.i18n not defined');
|
||||
} else {
|
||||
ss.i18n.addDictionary('lt', {
|
||||
"VALIDATOR.FIELDREQUIRED": "Prašome užpildyti \"%s\", jis yra privalomas.",
|
||||
"HASMANYFILEFIELD.UPLOADING": "Įkeliama... %s",
|
||||
"TABLEFIELD.DELETECONFIRMMESSAGE": "Ar tikrai norite ištrinti šį įrašą?",
|
||||
"LOADING": "įkeliama...",
|
||||
"UNIQUEFIELD.SUGGESTED": "Pakeista reikšmė į '%s' : %s",
|
||||
"UNIQUEFIELD.ENTERNEWVALUE": "Šiam laukui jūs turėsite įvesti naują naują reikšmę",
|
||||
"UNIQUEFIELD.CANNOTLEAVEEMPTY": "Šis laukas negali būti tuščias",
|
||||
"RESTRICTEDTEXTFIELD.CHARCANTBEUSED": "Šiame lauke negalima įvesti šio simbolio '%s'",
|
||||
"UPDATEURL.CONFIRM": "Ar tikrai norite pakeisti URL dalį į:\n\n%s/\n\nSpauskite OK, jeigu norite pakeisti arba Cancel, jeigu norite palikti kaip yra:\n\n%s",
|
||||
"UPDATEURL.CONFIRMURLCHANGED": "URL dalis pakeista į:\n'%s'",
|
||||
"FILEIFRAMEFIELD.DELETEFILE": "Ištrinti bylą",
|
||||
"FILEIFRAMEFIELD.UNATTACHFILE": "Atrišti bylą",
|
||||
"FILEIFRAMEFIELD.DELETEIMAGE": "Ištrinti paveikslėlį",
|
||||
"FILEIFRAMEFIELD.CONFIRMDELETE": "Ar tikrai norite ištrinti šią bylą?",
|
||||
"LeftAndMain.IncompatBrowserWarning": "Jūsų naršyklė nesuderinama su TVS aplinka. Prašome naudoti Internet Explorer 7+, Google Chrome 10+ arba Mozilla Firefox 3.5+.",
|
||||
"GRIDFIELD.ERRORINTRANSACTION": "Įvyko klaida bandant gauto duomenis iš serverio\nBandykite vėliau.",
|
||||
"HtmlEditorField.SelectAnchor": "Pasirinkite nuorodą",
|
||||
"UploadField.ConfirmDelete": "Ar tikrai norite pašalinti šią bylą iš serverio?",
|
||||
"UploadField.PHP_MAXFILESIZE": "Byla viršija upload_max_filesize (php.ini nustatymai)",
|
||||
"UploadField.HTML_MAXFILESIZE": "Byla viršija MAX_FILE_SIZE (HTML formos nustatymai)",
|
||||
"UploadField.ONLYPARTIALUPLOADED": "Byla įkelta tik dalinai",
|
||||
"UploadField.NOFILEUPLOADED": "Jokia byla neįkelta",
|
||||
"UploadField.NOTMPFOLDER": "Nerastas laikinų bylų katalogas",
|
||||
"UploadField.WRITEFAILED": "Nepavyko įrašyti į diską",
|
||||
"UploadField.STOPEDBYEXTENSION": "Bylos įkėlimas sustabytas dėl bylos plėtinio",
|
||||
"UploadField.TOOLARGE": "Byla per didelė",
|
||||
"UploadField.TOOSMALL": "Byla per maža",
|
||||
"UploadField.INVALIDEXTENSION": "Bylos plėtinys neleidžiamas",
|
||||
"UploadField.MAXNUMBEROFFILESSIMPLE": "Viršytas bylų kiekis",
|
||||
"UploadField.UPLOADEDBYTES": "Įkeltas turinys viršijo bylos dydį",
|
||||
"UploadField.EMPTYRESULT": "Nepavyko nieko įkelti",
|
||||
"UploadField.LOADING": "Įkeliama ...",
|
||||
"UploadField.Editing": "Redaguojama ...",
|
||||
"UploadField.Uploaded": "Įkelta",
|
||||
"UploadField.OVERWRITEWARNING": "Byla su tokiu pavadinimu jau yra",
|
||||
"TreeDropdownField.ENTERTOSEARCH": "Spauskite Enter/Vykdyti",
|
||||
"TreeDropdownField.OpenLink": "Atidaryti",
|
||||
"TreeDropdownField.FieldTitle": "Pasirinkti",
|
||||
"TreeDropdownField.SearchFieldTitle": "Pasirinkti arba Ieškoti"
|
||||
});
|
||||
}
|
41
javascript/lang/src/lt.js
Normal file
41
javascript/lang/src/lt.js
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"VALIDATOR.FIELDREQUIRED": "Prašome užpildyti \"%s\", jis yra privalomas.",
|
||||
"HASMANYFILEFIELD.UPLOADING": "Įkeliama... %s",
|
||||
"TABLEFIELD.DELETECONFIRMMESSAGE": "Ar tikrai norite ištrinti šį įrašą?",
|
||||
"LOADING": "įkeliama...",
|
||||
"UNIQUEFIELD.SUGGESTED": "Pakeista reikšmė į '%s' : %s",
|
||||
"UNIQUEFIELD.ENTERNEWVALUE": "Šiam laukui jūs turėsite įvesti naują naują reikšmę",
|
||||
"UNIQUEFIELD.CANNOTLEAVEEMPTY": "Šis laukas negali būti tuščias",
|
||||
"RESTRICTEDTEXTFIELD.CHARCANTBEUSED": "Šiame lauke negalima įvesti šio simbolio '%s'",
|
||||
"UPDATEURL.CONFIRM": "Ar tikrai norite pakeisti URL dalį į:\n\n%s/\n\nSpauskite OK, jeigu norite pakeisti arba Cancel, jeigu norite palikti kaip yra:\n\n%s",
|
||||
"UPDATEURL.CONFIRMURLCHANGED": "URL dalis pakeista į:\n'%s'",
|
||||
"FILEIFRAMEFIELD.DELETEFILE": "Ištrinti bylą",
|
||||
"FILEIFRAMEFIELD.UNATTACHFILE": "Atrišti bylą",
|
||||
"FILEIFRAMEFIELD.DELETEIMAGE": "Ištrinti paveikslėlį",
|
||||
"FILEIFRAMEFIELD.CONFIRMDELETE": "Ar tikrai norite ištrinti šią bylą?",
|
||||
"LeftAndMain.IncompatBrowserWarning": "Jūsų naršyklė nesuderinama su TVS aplinka. Prašome naudoti Internet Explorer 7+, Google Chrome 10+ arba Mozilla Firefox 3.5+.",
|
||||
"GRIDFIELD.ERRORINTRANSACTION": "Įvyko klaida bandant gauto duomenis iš serverio\nBandykite vėliau.",
|
||||
"HtmlEditorField.SelectAnchor": "Pasirinkite nuorodą",
|
||||
"UploadField.ConfirmDelete": "Ar tikrai norite pašalinti šią bylą iš serverio?",
|
||||
"UploadField.PHP_MAXFILESIZE": "Byla viršija upload_max_filesize (php.ini nustatymai)",
|
||||
"UploadField.HTML_MAXFILESIZE": "Byla viršija MAX_FILE_SIZE (HTML formos nustatymai)",
|
||||
"UploadField.ONLYPARTIALUPLOADED": "Byla įkelta tik dalinai",
|
||||
"UploadField.NOFILEUPLOADED": "Jokia byla neįkelta",
|
||||
"UploadField.NOTMPFOLDER": "Nerastas laikinų bylų katalogas",
|
||||
"UploadField.WRITEFAILED": "Nepavyko įrašyti į diską",
|
||||
"UploadField.STOPEDBYEXTENSION": "Bylos įkėlimas sustabytas dėl bylos plėtinio",
|
||||
"UploadField.TOOLARGE": "Byla per didelė",
|
||||
"UploadField.TOOSMALL": "Byla per maža",
|
||||
"UploadField.INVALIDEXTENSION": "Bylos plėtinys neleidžiamas",
|
||||
"UploadField.MAXNUMBEROFFILESSIMPLE": "Viršytas bylų kiekis",
|
||||
"UploadField.UPLOADEDBYTES": "Įkeltas turinys viršijo bylos dydį",
|
||||
"UploadField.EMPTYRESULT": "Nepavyko nieko įkelti",
|
||||
"UploadField.LOADING": "Įkeliama ...",
|
||||
"UploadField.Editing": "Redaguojama ...",
|
||||
"UploadField.Uploaded": "Įkelta",
|
||||
"UploadField.OVERWRITEWARNING": "Byla su tokiu pavadinimu jau yra",
|
||||
"TreeDropdownField.ENTERTOSEARCH": "Spauskite Enter/Vykdyti",
|
||||
"TreeDropdownField.OpenLink": "Atidaryti",
|
||||
"TreeDropdownField.FieldTitle": "Pasirinkti",
|
||||
"TreeDropdownField.SearchFieldTitle": "Pasirinkti arba Ieškoti"
|
||||
}
|
@ -170,12 +170,12 @@ fi:
|
||||
ForgotPasswordEmail_ss:
|
||||
HELLO: Hei
|
||||
TEXT1: 'Tässä on sinun'
|
||||
TEXT2: 'salasanan tyhjäys -linkki'
|
||||
TEXT2: 'salasanan vaihtolinkki'
|
||||
TEXT3: henkilölle
|
||||
Form:
|
||||
CSRF_FAILED_MESSAGE: "On ilmeisesti tapahtunut tekninen virhe. Klikkaa selaimesi Takaisin-nappia, päivitä sivu painamalla F5-näppäintä ja yritä uudelleen."
|
||||
FIELDISREQUIRED: '{name} on pakollinen'
|
||||
SubmitBtnLabel: Siirrä
|
||||
SubmitBtnLabel: Siirry
|
||||
VALIDATIONCREDITNUMBER: 'Tarkista, ovatko antamasi luottokortin numerot ({number}) oikein'
|
||||
VALIDATIONNOTUNIQUE: 'Syötetty arvo ei ole yksilöllinen'
|
||||
VALIDATIONPASSWORDSDONTMATCH: 'Salasanat eivät täsmää'
|
||||
@ -236,7 +236,7 @@ fi:
|
||||
RolesAddEditLink: 'Lisää/muokkaa rooleja'
|
||||
SINGULARNAME: Ryhmä
|
||||
Sort: 'Järjestys'
|
||||
has_many_Permissions: Luvat
|
||||
has_many_Permissions: Oikeudet
|
||||
many_many_Members: Jäsenet
|
||||
GroupImportForm:
|
||||
Help1: '<p>Tuo yksi tai useampi ryhmä <em>CSV</em>-muotoisena (arvot pilkulla erotettuina). <small><a href="#" class="toggle-advanced">Näytä edistyksellinen käyttö</a></small></p>'
|
||||
|
412
lang/lt.yml
412
lang/lt.yml
@ -1,4 +1,32 @@
|
||||
lt:
|
||||
AssetAdmin:
|
||||
NEWFOLDER: Naujas kalalogas
|
||||
SHOWALLOWEDEXTS: 'Rodyti leidžiamus bylų plėtinius'
|
||||
AssetTableField:
|
||||
CREATED: 'Įkelta'
|
||||
DIM: Išmatavimai
|
||||
FILENAME: Bylos pavadinimas
|
||||
FOLDER: Katalogas
|
||||
LASTEDIT: 'Redaguota'
|
||||
OWNER: Vartotojas
|
||||
SIZE: 'Bylos dydis'
|
||||
TITLE: Pavadinimas
|
||||
TYPE: 'Bylos tipas'
|
||||
URL: URL adresas
|
||||
AssetUploadField:
|
||||
ChooseFiles: 'Pasirinkite bylas'
|
||||
DRAGFILESHERE: 'Vilkite bylas čia'
|
||||
DROPAREA: 'Įmetimo vieta'
|
||||
EDITALL: 'Redaguoti visus'
|
||||
EDITANDORGANIZE: 'Redaguoti ir tvarkyti'
|
||||
EDITINFO: 'Redaguoti bylas'
|
||||
FILES: Bylos
|
||||
FROMCOMPUTER: 'Pasirinkite bylas iš jūsų kompiuterio'
|
||||
FROMCOMPUTERINFO: 'Įkelti iš jūsų kompiuterio'
|
||||
TOTAL: Viso
|
||||
TOUPLOAD: 'Pasirinkite bylas įkėlimui...'
|
||||
UPLOADINPROGRESS: 'Prašome palaukti... vyksta įkėlimas'
|
||||
UPLOADOR: ARBA
|
||||
BBCodeParser:
|
||||
ALIGNEMENT: Lygiavimas
|
||||
ALIGNEMENTEXAMPLE: 'sulygiuota pagal dešinę'
|
||||
@ -13,23 +41,37 @@ lt:
|
||||
EMAILLINKDESCRIPTION: 'Sukurti nuorodą į e. paštą'
|
||||
IMAGE: Paveikslėlis
|
||||
IMAGEDESCRIPTION: 'Rodyti paveikslėlį mano skelbime'
|
||||
ITALIC: 'Italic tekstas'
|
||||
ITALIC: 'Pasviręs tekstas'
|
||||
ITALICEXAMPLE: Pasviręs
|
||||
LINK: 'Puslapio nuoroda'
|
||||
LINKDESCRIPTION: 'Nuoroda į kitą svetainę ar URL adresą'
|
||||
STRUCK: 'Struck-out tekstas'
|
||||
STRUCKEXAMPLE: Struck-out
|
||||
UNDERLINE: 'Pabrauktas tekstas'
|
||||
UNDERLINEEXAMPLE: Pabraukta
|
||||
UNORDERED: 'Nerūšiuotas sąrašas'
|
||||
UNORDEREDDESCRIPTION: 'Nerūšiuotas sąrašas'
|
||||
UNORDEREDEXAMPLE1: 'nerūšiuota prekė 1'
|
||||
UNORDEREDEXAMPLE1: 'nerūšiuota įrašas 1'
|
||||
BackLink_Button_ss:
|
||||
Back: Atgal
|
||||
BasicAuth:
|
||||
ENTERINFO: 'Įveskite vartotojo vardą ir slaptažodį'
|
||||
ERRORNOTADMIN: 'Vartotojas nėra administratorius'
|
||||
ERRORNOTREC: 'Toks vartotojo vardas / slaptažodis neatpažintas'
|
||||
Boolean:
|
||||
ANY: Bet koks
|
||||
CMSLoadingScreen_ss:
|
||||
LOADING: Keliama...
|
||||
REQUIREJS: 'Šiai TVS būtina įjungti JavaScript.'
|
||||
CMSMain:
|
||||
ACCESS: 'Patekti į ''{title}'' dalį'
|
||||
ACCESSALLINTERFACES: 'Patekti į visas TVS dalis'
|
||||
ACCESSALLINTERFACESHELP: 'Perrašo konkretesnes nuostatas.'
|
||||
SAVE: Išsaugoti
|
||||
CMSPageHistoryController_versions_ss:
|
||||
PREVIEW: 'Puslapio peržiūra'
|
||||
CMSProfileController:
|
||||
MENUTITLE: 'Mano profilis'
|
||||
ChangePasswordEmail_ss:
|
||||
CHANGEPASSWORDTEXT1: 'Jūs pakeitėte slaptažodį'
|
||||
CHANGEPASSWORDTEXT2: 'Nuo šiol galite naudoti šiuos prisijungimo duomenis:'
|
||||
@ -37,70 +79,206 @@ lt:
|
||||
HELLO: Sveiki
|
||||
PASSWORD: Slaptažodis
|
||||
ConfirmedPasswordField:
|
||||
ATLEAST: 'Slaptažodžiai privalo būti bent {min} simbolių ilgio.'
|
||||
BETWEEN: 'Slaptažodžiai privalo būti nuo {min} iki {max} simbolių ilgio.'
|
||||
MAXIMUM: 'Slaptažodžiai privalo būti ne ilgesni nei {max} simbolių ilgio.'
|
||||
SHOWONCLICKTITLE: 'Pakeisti slaptažodį'
|
||||
ContentController:
|
||||
NOTLOGGEDIN: 'Neprisijungęs'
|
||||
CreditCardField:
|
||||
FIRST: pirmas
|
||||
FOURTH: ketvirtas
|
||||
SECOND: antras
|
||||
THIRD: trečias
|
||||
CurrencyField:
|
||||
CURRENCYSYMBOL: €
|
||||
DataObject:
|
||||
PLURALNAME: 'Duomenų objektai'
|
||||
SINGULARNAME: 'Duomenų objektas'
|
||||
Date:
|
||||
DAY: d.
|
||||
DAYS: d.
|
||||
HOUR: val.
|
||||
HOURS: val.
|
||||
LessThanMinuteAgo: 'mažiau nei min.'
|
||||
MIN: min.
|
||||
MINS: min.
|
||||
MONTH: mėn.
|
||||
MONTHS: mėn.
|
||||
SEC: s.
|
||||
SECS: s.
|
||||
TIMEDIFFAGO: 'prieš {difference}'
|
||||
TIMEDIFFIN: 'po {difference}'
|
||||
YEAR: m.
|
||||
YEARS: m.
|
||||
DateField:
|
||||
NOTSET: 'nenustatyta'
|
||||
TODAY: šiandien
|
||||
VALIDDATEFORMAT2: 'Prašome suvesti datą reikiamu formatu ({format})'
|
||||
VALIDDATEMAXDATE: 'Data privalo būti senesnė arba lygi vėliausiai galimai datai ({date})'
|
||||
VALIDDATEMINDATE: 'Data privalo būti naujesnė arba lygi anksčiausiai galimai datai ({date})'
|
||||
DatetimeField:
|
||||
NOTSET: 'Nenurodyta'
|
||||
Director:
|
||||
INVALID_REQUEST: 'Klaidinga užklausa'
|
||||
DropdownField:
|
||||
CHOOSE: (Pasirinkti)
|
||||
CHOOSESEARCH: '(Pasirinkti arba Ieškoti)'
|
||||
EmailField:
|
||||
VALIDATION: 'Prašome suvesti el. pašto adresą'
|
||||
Enum:
|
||||
ANY: Bet koks
|
||||
File:
|
||||
AviType: 'AVI video byla'
|
||||
Content: Turinys
|
||||
CssType: 'CSS byla'
|
||||
DmgType: 'Apple disk image'
|
||||
DocType: 'Word dokumentas'
|
||||
Filename: Bylos pavadinimas
|
||||
GifType: 'GIF paveikslėlis - tinkamas grafikai'
|
||||
GzType: 'GZIP archyvas'
|
||||
HtlType: 'HTML byla'
|
||||
HtmlType: 'HTML byla'
|
||||
INVALIDEXTENSION: 'Neleidžiamas bylos plėtinys (galimi: {extensions})'
|
||||
INVALIDEXTENSIONSHORT: 'Neleidžiamas bylos plėtinys'
|
||||
IcoType: 'Icon paveikslėlis'
|
||||
JpgType: 'JPEG paveikslėlis - tinkamas nuotraukoms'
|
||||
JsType: 'Javascript byla'
|
||||
Mp3Type: 'MP3 garso byla'
|
||||
MpgType: 'MPEG video byla'
|
||||
NOFILESIZE: 'Bylos dydis 0 baitų.'
|
||||
NOVALIDUPLOAD: 'Failas netinkamas įdėjimui'
|
||||
Name: Vardas
|
||||
NOVALIDUPLOAD: 'Byla netinkama įkėlimui'
|
||||
Name: Pavadinimas
|
||||
PLURALNAME: Bylos
|
||||
PdfType: 'Adome Acrobat PDF byla'
|
||||
PngType: 'PNG paveikslėlis - geras bendro tipo formatas'
|
||||
SINGULARNAME: Byla
|
||||
TOOLARGE: 'Byla per didelė, didžiausias galimas dydis yra {size}'
|
||||
TOOLARGESHORT: 'Bylos dydis viršija {size}'
|
||||
TiffType: 'Tagged paveikslėlių formatas'
|
||||
Title: Pavadinimas
|
||||
WavType: 'WAV garso byla'
|
||||
XlsType: 'Excel skaičiuoklė'
|
||||
ZipType: 'ZIP archyvas'
|
||||
Filesystem:
|
||||
SYNCRESULTS: 'Sinchronizacija baigta: {createdcount} įrašai sukurti, {deletedcount} įrašai ištrinti'
|
||||
Folder:
|
||||
PLURALNAME: Katalogai
|
||||
SINGULARNAME: Katalogas
|
||||
ForgotPasswordEmail_ss:
|
||||
HELLO: Sveiki
|
||||
TEXT1: 'Štai Jūsų'
|
||||
TEXT1: 'Jūsų'
|
||||
TEXT2: 'slaptažodžio atstatymo nuoroda'
|
||||
TEXT3: kam
|
||||
TEXT3: svetainei
|
||||
Form:
|
||||
CSRF_FAILED_MESSAGE: "Iškilo techninė problema. Prašome paspausti mygtuką Atgal,\nperkraukite naršyklės langą ir bandykite vėl."
|
||||
FIELDISREQUIRED: '{name} yra privalomas'
|
||||
SubmitBtnLabel: Eiti
|
||||
VALIDATIONCREDITNUMBER: 'Prašome įsitikinti, ar teisingai suvedėte kreditinės kortelės numerį {number}'
|
||||
VALIDATIONNOTUNIQUE: 'Įvesta reikšmė nėra unikali'
|
||||
VALIDATIONPASSWORDSDONTMATCH: 'Nesutampa slaptažodžiai'
|
||||
VALIDATIONPASSWORDSNOTEMPTY: 'Slaptažodžiai negali būti tušti'
|
||||
VALIDATIONSTRONGPASSWORD: 'Slaptažodžiai privalo būti sudaryti panaudojant bent vieną skaitmenį ir bent vieną raidę'
|
||||
VALIDATOR: Tikrintojas
|
||||
VALIDCURRENCY: 'Prašome suvesti teisingą valiutą'
|
||||
CSRF_EXPIRED_MESSAGE: 'Jūsų prisijungimas nebegalioja. Prašome iš naujo išsaugoti duomenis.'
|
||||
FormField:
|
||||
Example: 'pvz. %s'
|
||||
NONE: niekas
|
||||
GridAction:
|
||||
DELETE_DESCRIPTION: Ištrinti
|
||||
Delete: Ištrinti
|
||||
UnlinkRelation: Atkabinti
|
||||
GridField:
|
||||
Add: 'Sukurti {name}'
|
||||
Filter: Filtras
|
||||
FilterBy: 'Filtruoti pagal '
|
||||
Find: Rasti
|
||||
LEVELUP: 'Aukštyn'
|
||||
LinkExisting: 'Pasirinkti esamą'
|
||||
NewRecord: 'Naujas %s'
|
||||
NoItemsFound: 'Įrašų nerasta'
|
||||
PRINTEDAT: 'Atspausdinta'
|
||||
PRINTEDBY: 'Atspausdino'
|
||||
PlaceHolder: 'Rasti {type}'
|
||||
PlaceHolderWithLabels: 'Rasti {type} pagal {name}'
|
||||
RelationSearch: 'Sąryšių paieška'
|
||||
ResetFilter: Atstatyti
|
||||
GridFieldAction_Delete:
|
||||
DeletePermissionsFailure: 'Nėra leidimų trynimui'
|
||||
EditPermissionsFailure: 'Nėra leidimų atjungti įrašą'
|
||||
GridFieldDetailForm:
|
||||
CancelBtn: Atšaukti
|
||||
Create: Sukurti
|
||||
Delete: Ištrinti
|
||||
DeletePermissionsFailure: 'Nėra leidimų trynimui'
|
||||
Deleted: 'Ištrinta %s %s'
|
||||
Save: Išsaugoti
|
||||
Saved: 'Išsaugota {name} {link}'
|
||||
GridFieldEditButton_ss:
|
||||
EDIT: Redaguoti
|
||||
GridFieldItemEditView:
|
||||
Go_back: 'Atgal'
|
||||
Group:
|
||||
AddRole: 'Pridėti rolę šiai grupei'
|
||||
Code: 'Grupės kodas'
|
||||
DefaultGroupTitleAdministrators: Administratoriai
|
||||
DefaultGroupTitleContentAuthors: 'Turinio autoriai'
|
||||
Description: Aprašymas
|
||||
GroupReminder: 'Jeigu pasirinksite tėvinę grupę, ši grupė perims visas jos roles'
|
||||
HierarchyPermsError: 'Nepavyko priskirti tėvinės grupės "%s" su priskirtais leidimais (būtina ADMIN prieeiga)'
|
||||
Locked: 'Užrakinta?'
|
||||
NoRoles: 'Rolių nerasta'
|
||||
PLURALNAME: Grupės
|
||||
Parent: 'Priklauso grupei'
|
||||
RolesAddEditLink: 'Tvarkyti roles'
|
||||
SINGULARNAME: Grupė
|
||||
Sort: 'Rūšiavimo tvarka'
|
||||
has_many_Permissions: Leidimai
|
||||
many_many_Members: Nariai
|
||||
GroupImportForm:
|
||||
Help1: '<p>Importuoti vieną ar kelias grupes <em>CSV</em> formatu (kableliu atskirtos reikšmės). <small><a href="#" class="toggle-advanced">Rodyti detalesnį aprašymą</a></small></p>'
|
||||
Help2: "<div class=\"advanced\">\n<h4>Detalesnis aprašymas</h4>\n<ul>\n<li>Galimi stulpeliai: <em>%s</em></li>\n<li>Esamos grupės yra surišamos su jų unikalia <em>Code</em> reikšme ir atnaujinamos duomenimis iš importuojamos bylos</li>\n<li>Grupių hierarchija gali būti sukurta naudojant <em>ParentCode</em> stulpelį.</li>\n<li>Leidimų gali būti priskirti naudojant <em>PermissionCode</em> stulpelį. Esami leidimai nebus pakeisti.</li>\n</ul>\n</div>"
|
||||
ResultCreated: 'Sukurta {count} grupių'
|
||||
ResultDeleted: 'Ištrinta %d grupių'
|
||||
ResultUpdated: 'Atnaujinta %d grupių'
|
||||
Hierarchy:
|
||||
InfiniteLoopNotAllowed: 'Rastas begalinis sąryšis "{type}" hierarchijoje. Prašome patikrinti tėvinius sąryšius'
|
||||
HtmlEditorField:
|
||||
ANCHORVALUE: Pagrindinis
|
||||
ADDURL: 'Pridėti URL'
|
||||
ADJUSTDETAILSDIMENSIONS: 'Detalesnė inf. ir matmenys'
|
||||
ANCHORVALUE: Nuoroda
|
||||
BUTTONADDURL: 'Pridėti URL'
|
||||
BUTTONINSERT: Įterpti
|
||||
BUTTONINSERTLINK: 'Įterpti nuorodą'
|
||||
BUTTONREMOVELINK: 'Pašalinti nuorodą'
|
||||
BUTTONUpdate: Atnaujinti
|
||||
CAPTIONTEXT: 'Pavadinimo tekstas'
|
||||
CSSCLASS: 'Lygiavimas / stilius'
|
||||
CSSCLASSCENTER: 'Centruotas, be nieko.'
|
||||
CSSCLASSLEFT: 'Kairėje, su tekstu aplink.'
|
||||
CSSCLASSLEFTALONE: 'Kairėje, savaiminis.'
|
||||
CSSCLASSRIGHT: 'Dešinėje, su tekstu aplink.'
|
||||
DETAILS: Detalesnė inf.
|
||||
EMAIL: 'E. pašto adresas'
|
||||
FILE: Byla
|
||||
FOLDER: Direktorija
|
||||
FOLDER: Katalogas
|
||||
FROMCMS: 'Iš TVS'
|
||||
FROMCOMPUTER: 'Iš jūsų kompiuterio'
|
||||
FROMWEB: 'Iš interneto'
|
||||
FindInFolder: 'Rasti kataloge'
|
||||
IMAGEALT: 'Alternatyvus tekstas (alt)'
|
||||
IMAGEALTTEXT: 'Alternatyvus tekstas (alt) - rodomas, jeigu nepavyko parodyti paveikslėlio'
|
||||
IMAGEALTTEXTDESC: 'Rodomas, jeigu nepavyko parodyti paveikslėlio'
|
||||
IMAGEDIMENSIONS: Matmenys
|
||||
IMAGEHEIGHTPX: Aukštis
|
||||
IMAGETITLE: 'Pavadinimo tekstas (pagalbinis tekstas) - papildomai informacijai apie paveikslėlį'
|
||||
IMAGETITLE: 'Pavadinimo tekstas (tooltip) - papildomai informacijai apie paveikslėlį'
|
||||
IMAGETITLETEXT: 'Pavadinimo tekstas (tooltip)'
|
||||
IMAGETITLETEXTDESC: 'Papildomai informacijai apie paveikslėlį'
|
||||
IMAGEWIDTHPX: Plotis
|
||||
INSERTMEDIA: 'Įterpti Media'
|
||||
LINK: 'Nuoroda'
|
||||
LINKANCHOR: 'Pagrindinis šiame puslapyje'
|
||||
LINKANCHOR: 'Nuoroda šiame puslapyje'
|
||||
LINKDESCR: 'Nuorodos aprašymas'
|
||||
LINKEMAIL: 'E. pašto adresas'
|
||||
LINKEXTERNAL: 'Kita svetainė'
|
||||
@ -110,26 +288,67 @@ lt:
|
||||
LINKTO: 'Nuoroda į'
|
||||
PAGE: Puslapis
|
||||
URL: URL adresas
|
||||
URLNOTANOEMBEDRESOURCE: 'Nepavyko URL nuorodos ''{url}'' panaudoti media turiniui.'
|
||||
UpdateMEDIA: 'Atnaujinti media'
|
||||
Image:
|
||||
PLURALNAME: Bylos
|
||||
SINGULARNAME: Byla
|
||||
Image_Cached:
|
||||
PLURALNAME: Bylos
|
||||
SINGULARNAME: Byla
|
||||
Image_iframe_ss:
|
||||
TITLE: 'Atvaizdo siuntimas iframe'
|
||||
TITLE: 'Paveikslėlio siuntimas iframe'
|
||||
LeftAndMain:
|
||||
CANT_REORGANISE: 'Jūs neturite leidimo keisti aukščiausio lygio puslapių. Jūsų pakeitimai neišsaugoti.'
|
||||
DELETED: Ištrinta.
|
||||
DropdownBatchActionsDefault: Veiksmai
|
||||
HELP: Pagalba
|
||||
PAGETYPE: 'Puslapio tipas:'
|
||||
PERMAGAIN: 'Jūs atsijungėte. Norėdami vėl prisijungti, įveskite savo duomenis į žemiau esančius laukelius.'
|
||||
PERMALREADY: 'Deja, Jūs negalite patekti į šią TVS dalį. Jeigu norite prisijungti kitu vartotoju, tai atlikite žemiau'
|
||||
PERMDEFAULT: 'Pasirinkite prisijungimo būda ir suveskite prisijungimo duomenis'
|
||||
PLEASESAVE: 'Prašome išsaugoti puslapį: Šis puslapis negali būti atnaujintas, nes jis dar nėra išsaugotas.'
|
||||
PreviewButton: Peržiūra
|
||||
REORGANISATIONSUCCESSFUL: 'Puslapių medis pertvarkytas sėkmingai.'
|
||||
SAVEDUP: Išsaugota.
|
||||
ShowAsList: 'rodyti kaip sąrašą'
|
||||
TooManyPages: 'Per daug puslapių'
|
||||
ValidationError: 'Tikrinimo klaida'
|
||||
VersionUnknown: Nežinoma
|
||||
LeftAndMain_Menu_ss:
|
||||
Hello: Sveiki
|
||||
LOGOUT: 'Atsijungti'
|
||||
LoginAttempt:
|
||||
Email: 'E. pašto adresas'
|
||||
IP: 'IP adresas'
|
||||
Status: Statusas
|
||||
PLURALNAME: 'Bandymai prisijungti'
|
||||
SINGULARNAME: 'Bandymas prisijungti'
|
||||
Status: Būsena
|
||||
Member:
|
||||
ADDGROUP: 'Pridėti grupę'
|
||||
BUTTONCHANGEPASSWORD: 'Pakeisti slaptažodį'
|
||||
BUTTONLOGIN: 'Prisijungti'
|
||||
BUTTONLOGINOTHER: 'Prisijungti kitu vardu'
|
||||
BUTTONLOSTPASSWORD: 'Pamiršau savo slaptažodį'
|
||||
CANTEDIT: 'Neturite teisių tai atlikti'
|
||||
CONFIRMNEWPASSWORD: 'Patvirtinkite naują slaptažodį'
|
||||
CONFIRMPASSWORD: 'Patvirtinkite slaptažodį'
|
||||
DATEFORMAT: 'Datos formatas'
|
||||
DefaultAdminFirstname: 'Pagrindinis administratorius'
|
||||
DefaultDateTime: pagal nutylėjimą
|
||||
EMAIL: E. paštas
|
||||
ENTEREMAIL: 'Įveskite e. pašto adresą norėdami gauti slaptažodžio atstatymo nuorodą.'
|
||||
EMPTYNEWPASSWORD: 'Naujas slaptažodis negali būti tuščias, bandykite iš naujo'
|
||||
ENTEREMAIL: 'Norėdami gauti slaptažodžio atstatymo nuorodą, įveskite e. pašto adresą.'
|
||||
ERRORLOCKEDOUT2: 'Jūsų paskyra laikinai sustabdyta dėl per didelio klaidingų bandymų prisijungti skaičiaus. Pabandykite prisijungti vėliau {count} min. laikotarpyje.'
|
||||
ERRORNEWPASSWORD: 'Nesutampa naujas slaptažodis, bandykite dar kartą'
|
||||
ERRORPASSWORDNOTMATCH: 'Nesutampa Jūsų senas slaptažodis, bandykite dar kartą'
|
||||
ERRORPASSWORDNOTMATCH: 'Blogas senas slaptažodis, bandykite dar kartą'
|
||||
ERRORWRONGCRED: 'Pateikti duomenys blogi, bandykite dar kartą.'
|
||||
FIRSTNAME: 'Vardas'
|
||||
INTERFACELANG: 'Kalba'
|
||||
INVALIDNEWPASSWORD: 'Neleidžiamas slaptažodis: {password}'
|
||||
LOGGEDINAS: 'Prisijungėte kaip {name}.'
|
||||
NEWPASSWORD: 'Naujas slaptažodis'
|
||||
NoPassword: 'Šis vartotojas neturi slaptažodžio.'
|
||||
PASSWORD: Slaptažodis
|
||||
PLURALNAME: Nariai
|
||||
REMEMBERME: 'Prisiminti jungiantis kitą kartą?'
|
||||
@ -137,10 +356,13 @@ lt:
|
||||
SUBJECTPASSWORDCHANGED: 'Jūsų slaptažodis pakeistas'
|
||||
SUBJECTPASSWORDRESET: 'Slaptažodžio atstatymo nuoroda'
|
||||
SURNAME: Pavardė
|
||||
TIMEFORMAT: 'Laiko formatas'
|
||||
VALIDATIONMEMBEREXISTS: 'Tokį e. paštą jau naudoja kitas narys.'
|
||||
ValidationIdentifierFailed: 'Nepavyko perrašyti nario #{id} su tuo pačiu atpažinimo kodu ({name} = {value}))'
|
||||
WELCOMEBACK: 'Sveiki, {firstname}'
|
||||
YOUROLDPASSWORD: 'Jūsų senas slaptažodis'
|
||||
belongs_many_many_Groups: Grupės
|
||||
db_LastVisited: 'Paskutinį kartą lankyta'
|
||||
db_LastVisited: 'Paskutinį kart lankyta'
|
||||
db_Locale: 'Vartotojo sąsajos kalba'
|
||||
db_LockedOutUntil: 'Užrakinta iki '
|
||||
db_NumVisit: 'Vizitų skaičius'
|
||||
@ -148,11 +370,98 @@ lt:
|
||||
db_PasswordExpiry: 'Slaptažodžio pabaigos data'
|
||||
MemberAuthenticator:
|
||||
TITLE: 'E-paštas ir slaptažodis'
|
||||
MemberDatetimeOptionsetField:
|
||||
AMORPM: 'AM (Ante meridiem) arba PM (Post meridiem)'
|
||||
Custom: Pasirinktinas
|
||||
DATEFORMATBAD: 'Neteisingas datos formatas'
|
||||
DAYNOLEADING: 'Mėnesio diena be nulio pradžioje'
|
||||
DIGITSDECFRACTIONSECOND: 'Vienas ar daugiau skaitmenų, rodančių trupmeninę sekundės dalį'
|
||||
FOURDIGITYEAR: 'Metai iš keturių skaitmenų'
|
||||
FULLNAMEMONTH: 'Pilnas mėnesio pavadinimas (pvz. Liepa)'
|
||||
HOURNOLEADING: 'Valanda be nulio pradžioje'
|
||||
MINUTENOLEADING: 'Minutė be nulio pradžioje'
|
||||
MONTHNOLEADING: 'Mėnesis be nulio pradžioje'
|
||||
Preview: Peržiūra
|
||||
SHORTMONTH: 'Trumpas mėnesio pavadinimas (pvz. Lie)'
|
||||
TWODIGITDAY: 'Mėnesis iš dviejų skaitmenų'
|
||||
TWODIGITHOUR: 'Valanda iš dviejų skaitmenų (nuo 00 iki 23)'
|
||||
TWODIGITMINUTE: 'Minutė iš dviejų skaitmenų (nuo 00 iki 59)'
|
||||
TWODIGITMONTH: 'Mėnesis iš dviejų skaitmenų (01 - sausis ir t.t.)'
|
||||
TWODIGITSECOND: 'Sekundė iš dviejų skaitmenų (nuo 00 iki 59)'
|
||||
TWODIGITYEAR: 'Metai iš dviejų skaitmenų'
|
||||
Toggle: 'Rodyti formatavimo aprašymą'
|
||||
MemberImportForm:
|
||||
Help1: '<p>Importuoti vartotojus <em>CSV</em> formatu (kableliu atskirtos reikšmės). <small><a href="#" class="toggle-advanced">Rodyti detalesnį aprašymą</a></small></p>'
|
||||
Help2: "<div class=\"advanced\">\n<h4>Detalesnis aprašymas</h4>\n<ul>\n<li>Galimi stulpeliai: <em>%s</em></li>\n<li>Esami vartotojai yra surišamos su jų unikalia <em>Code</em> reikšme ir atnaujinami duomenimis iš importuojamos bylos</li>\n<li>Grupės gali būti priskirtus naudojant <em>Groups</em> stulpelį. Grupės yra atpažįstamos pagal <em>Code</em> stulpelį, kelios grupės nurodomos per kablelį. Jau priskirtos grupės nebus pakeistos.</li>\n</ul>\n</div>"
|
||||
ResultCreated: 'Sukurta {count} vartotojų'
|
||||
ResultDeleted: 'Ištrinta %d vartotojų'
|
||||
ResultNone: 'Nėra jokių pakeitimų'
|
||||
ResultUpdated: 'Atnaujinta {count} vartotojų'
|
||||
MemberPassword:
|
||||
PLURALNAME: 'Vartotojų slaptažodžiai'
|
||||
SINGULARNAME: 'Vartotojo slaptažodis'
|
||||
MemberTableField:
|
||||
APPLY_FILTER: 'Vykdyti'
|
||||
ModelAdmin:
|
||||
DELETE: Ištrinti
|
||||
DELETEDRECORDS: 'Ištrinta {count} įrašų.'
|
||||
EMPTYBEFOREIMPORT: 'Perrašyti duomenis'
|
||||
IMPORT: 'Importuoti iš CSV'
|
||||
IMPORTEDRECORDS: 'Importuota {count} įrašų'
|
||||
NOCSVFILE: 'Pasirinkite CSV bylą, kurią importuotsite'
|
||||
NOIMPORT: 'Nėra ką importuoti'
|
||||
RESET: Atstatyti
|
||||
Title: 'Duomenų objektai'
|
||||
UPDATEDRECORDS: 'Atnaujinta {count} įrašų'
|
||||
ModelAdmin_ImportSpec_ss:
|
||||
IMPORTSPECFIELDS: 'Duomenų bazės stulpeliai'
|
||||
IMPORTSPECLINK: 'Rodyti %s aprašymą'
|
||||
IMPORTSPECRELATIONS: Sąryšiai
|
||||
IMPORTSPECTITLE: '%s aprašymas'
|
||||
ModelAdmin_Tools_ss:
|
||||
FILTER: Filtras
|
||||
IMPORT: Importuoti
|
||||
ModelSidebar_ss:
|
||||
IMPORT_TAB_HEADER: Importas
|
||||
SEARCHLISTINGS: Ieškoti
|
||||
MoneyField:
|
||||
FIELDLABELAMOUNT: Kiekis
|
||||
FIELDLABELCURRENCY: Valiuta
|
||||
NullableField:
|
||||
IsNullLabel: 'Tuščias'
|
||||
NumericField:
|
||||
VALIDATION: '''{value}'' nėra skaičius, prašome įvesti skaičių'
|
||||
Pagination:
|
||||
Page: Puslapis
|
||||
View: Rodoma
|
||||
PasswordValidator:
|
||||
LOWCHARSTRENGTH: 'Padarykite slaptažodį sudėtingesnį, panaudodami bent kelis simbolius iš šio sąrašo: %s'
|
||||
PREVPASSWORD: 'Jūs jau naudojote šį slaptažodį anksčiau, prašome sukurti naują'
|
||||
TOOSHORT: 'Slaptažodis yra per trumpas, jis turi būti sudarytas iš %s arba didesnio skaičiaus simbolių'
|
||||
Permission:
|
||||
AdminGroup: Administratorius
|
||||
CMS_ACCESS_CATEGORY: 'TVS Prieiga'
|
||||
FULLADMINRIGHTS: 'Pilnos administravimo teisės'
|
||||
FULLADMINRIGHTS_HELP: 'Turi ir viršija visus kitus leidimus.'
|
||||
PLURALNAME: Leidimai
|
||||
SINGULARNAME: Leidimas
|
||||
PermissionCheckboxSetField:
|
||||
AssignedTo: 'priskirta "{title}"'
|
||||
FromGroup: 'paveldėta iš grupės "{title}"'
|
||||
FromRole: 'paveldėta iš rolės "{title}"'
|
||||
FromRoleOnGroup: 'paveldėta iš rolės "%s" grupėje "%s"'
|
||||
PermissionRole:
|
||||
OnlyAdminCanApply: 'Gali priskirti tik administratorius'
|
||||
PLURALNAME: Rolės
|
||||
SINGULARNAME: Rolė
|
||||
Title: Pavadinimas
|
||||
PermissionRoleCode:
|
||||
PLURALNAME: 'Leidimų rolių kodai'
|
||||
PermsError: 'Nepavyko priskirto kodo "%s" su priskirtais leidimais (būtina ADMIN prieiga)'
|
||||
SINGULARNAME: 'Leidimų rolių kodai'
|
||||
Permissions:
|
||||
PERMISSIONS_CATEGORY: 'Rolės ir priėjimo leidimai'
|
||||
UserPermissionsIntro: 'Priskiriant grupes šiam vartotojui, keičiasi vartotojui suteiktos teisės. Norėdami susipažinti detaliau su leidimais atskiroms grupėms, eikite į grupių sąrašą.'
|
||||
PhoneNumberField:
|
||||
VALIDATION: 'Įveskite teisingą telefono numerį'
|
||||
Security:
|
||||
@ -161,21 +470,90 @@ lt:
|
||||
CHANGEPASSWORDBELOW: 'Žemiau galite pasikeisti savo slaptažodį.'
|
||||
CHANGEPASSWORDHEADER: 'Pasikeiskite savo slaptažodį'
|
||||
ENTERNEWPASSWORD: 'Įveskite naują slaptažodį.'
|
||||
ERRORPASSWORDPERMISSION: 'Norėdami keisti savo slaptažodį turite būti prisijungęs!'
|
||||
ERRORPASSWORDPERMISSION: 'Norėdami pakeisti savo slaptažodį, turite būti prisijungęs!'
|
||||
LOGGEDOUT: 'Jūs atsijungėte. Norėdami vėl prisijungti, įveskite savo duomenis į žemiau esančius laukelius.'
|
||||
LOGIN: 'Prisijungti'
|
||||
LOSTPASSWORDHEADER: 'Slaptažodžio atstatymas'
|
||||
NOTEPAGESECURED: 'Šis puslapis yra apsaugotas. Įveskite savo prisijungimo duomenis, esančius žemiau.'
|
||||
NOTERESETPASSWORD: 'Įveskite savo e. pašto adresą ir mes atsiųsime slaptažodžio atstatymui skirtą nuorodą'
|
||||
NOTERESETLINKINVALID: '<p>Neteisinga arba negaliojanti slaptažodžio atstatymo nuoroda.</p><p>Galite atsisiųsti naują <a href="{link1}">čia</a> arba pasikeisti slaptažodį po to, kai <a href="{link2}">prisijungsite</a>.</p>'
|
||||
NOTERESETPASSWORD: 'Įveskite savo e. pašto adresą ir atsiųsime slaptažodžio atstatymui skirtą nuorodą'
|
||||
PASSWORDSENTHEADER: 'Slaptažodžio atstatymo nuoroda nusiųsta į ''{email}'''
|
||||
PASSWORDSENTTEXT: 'Atstatymo nuoroda nusiųsta į ''{email}'''
|
||||
SecurityAdmin:
|
||||
ACCESS_HELP: 'Leisti peržiūrėti, sukurti ir redaguoti vartotojus, taip pat priskirti leidimus ir roles jiems.'
|
||||
APPLY_ROLES: 'Priskirti grupei roles'
|
||||
APPLY_ROLES_HELP: 'Galimybė redaguoti grupei priskirtas roles. Būtinas leidimas "Prieiti prie ''Vartotojai''"'
|
||||
EDITPERMISSIONS: 'Tvarkyti leidimus grupei'
|
||||
EDITPERMISSIONS_HELP: 'Galimybė grupei redaguoti "Priėjimą/Leidimus" ir IP adresus. Būtinas leidimas "Prieiti prie ''Saugumas''"'
|
||||
GROUPNAME: 'Grupės pavadinimas'
|
||||
IMPORTGROUPS: 'Importuoti grupes'
|
||||
IMPORTUSERS: 'Importuoti vartotojus'
|
||||
MEMBERS: Nariai
|
||||
MENUTITLE: Saugumas
|
||||
MemberListCaution: 'Dėmesio: Pašalinus vartotojus ir šio sąrašo, jie bus pašalinti iš visų grupių ir duomenų bazės.'
|
||||
NEWGROUP: 'Nauja grupė'
|
||||
PERMISSIONS: Leidimai
|
||||
ROLES: Rolės
|
||||
ROLESDESCRIPTION: 'Rolės - tai iš anksto sudarytas leidimų sąrašas, kuris gali būti priskirtas grupėms.<br />Jos yra paveldimos iš tėvinės grupės.'
|
||||
TABROLES: Rolės
|
||||
Users: Vartotojai
|
||||
SecurityAdmin_MemberImportForm:
|
||||
BtnImport: 'Importuoti iš CSV'
|
||||
FileFieldLabel: 'CSV byla <small>(Leidžiami plėtiniai: *.csv)</small>'
|
||||
SilverStripeNavigator:
|
||||
Auto: Automatiškai
|
||||
ChangeViewMode: 'Pakeisti peržiūros rėžimą'
|
||||
Desktop: Kompiuteris
|
||||
DualWindowView: 'Du langai'
|
||||
Edit: Redaguoti
|
||||
EditView: 'Redagavimo rėžimas'
|
||||
Mobile: Mob. įrenginys
|
||||
PreviewState: 'Peržiūros būsena'
|
||||
PreviewView: 'Peržiūros rėžimas'
|
||||
Responsive: Adaptyvus
|
||||
SplitView: 'Perskirtas rėžimas'
|
||||
Tablet: Planšetė
|
||||
ViewDeviceWidth: 'Pasirinkite peržiūros plotį'
|
||||
Width: plotis
|
||||
SiteTree:
|
||||
TABMAIN: Pagrindinis
|
||||
TableListField:
|
||||
CSVEXPORT: 'Ekportuoti į CSV'
|
||||
Print: Spausdinti
|
||||
TableListField_PageControls_ss:
|
||||
OF: iš
|
||||
TimeField:
|
||||
VALIDATEFORMAT: 'Prašome suvesti laiką teisingu formatu ({format})'
|
||||
ToggleField:
|
||||
LESS: mažiau
|
||||
MORE: daugiau
|
||||
UploadField:
|
||||
ATTACHFILE: 'Prisegti bylą'
|
||||
ATTACHFILES: 'Prisegti bylas'
|
||||
AttachFile: 'Prisegti bylą(-as)'
|
||||
CHOOSEANOTHERFILE: 'Pasirinkti kitą bylą'
|
||||
CHOOSEANOTHERINFO: 'Pakeisti šią bylą kita bylą iš bylų sąrašo'
|
||||
DELETE: 'Ištrinti iš bylų'
|
||||
DELETEINFO: 'Ištrinti bylą iš bylų sąrašo visam laikui'
|
||||
DOEDIT: Išsaugoti
|
||||
DROPFILE: 'Įmesti bylą'
|
||||
DROPFILES: 'Įmesti bylas'
|
||||
Dimensions: Matmenys
|
||||
EDIT: Redaguoti
|
||||
EDITINFO: 'Redaguoti šią bylą'
|
||||
FIELDNOTSET: 'Informacija apie bylą nerasta'
|
||||
FROMCOMPUTER: 'Iš jūsų kompiuterio'
|
||||
FROMCOMPUTERINFO: 'Pasirinkti iš bylų'
|
||||
FROMFILES: 'Iš bylų'
|
||||
HOTLINKINFO: 'Pastaba: Šis paveikslėlis bus su nuoroda. Prašome įsitikinti, jog turite puslapio autoriaus leidimą taip daryti.'
|
||||
MAXNUMBEROFFILES: 'Viršytas bylų kiekis {count}'
|
||||
MAXNUMBEROFFILESONE: 'Galima įkelti tik vieną bylą'
|
||||
MAXNUMBEROFFILESSHORT: 'Galima įkelti tik {count} bylų'
|
||||
OVERWRITEWARNING: 'Byla su tokiu pavadinimu jau yra'
|
||||
REMOVE: Pašalinti
|
||||
REMOVEINFO: 'Pašalinti šią bylą iš čia, bet netrinti iš bylų sąrašo.'
|
||||
STARTALL: 'Pradėti viską'
|
||||
Saved: Išsaugota
|
||||
UPLOADSINTO: 'saugo į /{path}'
|
||||
Versioned:
|
||||
has_many_Versions: Versijos
|
||||
|
@ -78,7 +78,7 @@ class DataDifferencer extends ViewableData {
|
||||
$fields = array_keys($this->toRecord->toMap());
|
||||
}
|
||||
|
||||
$hasOnes = $this->fromRecord->has_one();
|
||||
$hasOnes = array_merge($this->fromRecord->has_one(), $this->toRecord->has_one());
|
||||
|
||||
// Loop through properties
|
||||
foreach($fields as $field) {
|
||||
@ -96,8 +96,13 @@ class DataDifferencer extends ViewableData {
|
||||
foreach($hasOnes as $relName => $relSpec) {
|
||||
if(in_array($relName, $this->ignoredFields)) continue;
|
||||
|
||||
// Create the actual column name
|
||||
$relField = "{$relName}ID";
|
||||
$toTitle = '';
|
||||
if($this->toRecord->hasMethod($relName)) {
|
||||
$relObjTo = $this->toRecord->$relName();
|
||||
$toTitle = $relObjTo->hasMethod('Title') || $relObjTo->hasField('Title') ? $relObjTo->Title : '';
|
||||
}
|
||||
|
||||
if(!$this->fromRecord) {
|
||||
if($relObjTo) {
|
||||
@ -107,12 +112,16 @@ class DataDifferencer extends ViewableData {
|
||||
// not playing nice with mocked images
|
||||
$diffed->setField($relName, "<ins>" . $relObjTo->getTag() . "</ins>");
|
||||
} else {
|
||||
$diffed->setField($relField, "<ins>" . $relObjTo->Title() . "</ins>");
|
||||
$diffed->setField($relField, "<ins>" . $toTitle . "</ins>");
|
||||
}
|
||||
}
|
||||
} else if($this->fromRecord->$relField != $this->toRecord->$relField) {
|
||||
$fromTitle = '';
|
||||
if($this->fromRecord->hasMethod($relName)) {
|
||||
$relObjFrom = $this->fromRecord->$relName();
|
||||
if($relObjFrom instanceof Image) {
|
||||
$fromTitle = $relObjFrom->hasMethod('Title') || $relObjFrom->hasField('Title') ? $relObjFrom->Title : '';
|
||||
}
|
||||
if(isset($relObjFrom) && $relObjFrom instanceof Image) {
|
||||
// TODO Use CMSThumbnail (see above)
|
||||
$diffed->setField(
|
||||
// Using relation name instead of database column name, because of FileField etc.
|
||||
@ -120,9 +129,10 @@ class DataDifferencer extends ViewableData {
|
||||
Diff::compareHTML($relObjFrom->getTag(), $relObjTo->getTag())
|
||||
);
|
||||
} else {
|
||||
// Set the field.
|
||||
$diffed->setField(
|
||||
$relField,
|
||||
Diff::compareHTML($relObjFrom->getTitle(), $relObjTo->getTitle())
|
||||
Diff::compareHTML($fromTitle, $toTitle)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,14 @@ class BasicAuth {
|
||||
$isRunningTests = (class_exists('SapphireTest', false) && SapphireTest::is_running_test());
|
||||
if(!Security::database_is_ready() || (Director::is_cli() && !$isRunningTests)) return true;
|
||||
|
||||
$matches = array();
|
||||
if (isset($_SERVER['HTTP_AUTHORIZATION']) &&
|
||||
preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)) {
|
||||
list($name, $password) = explode(':', base64_decode($matches[1]));
|
||||
$_SERVER['PHP_AUTH_USER'] = strip_tags($name);
|
||||
$_SERVER['PHP_AUTH_PW'] = strip_tags($password);
|
||||
}
|
||||
|
||||
$member = null;
|
||||
if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
|
||||
$member = MemberAuthenticator::authenticate(array(
|
||||
|
@ -14,6 +14,14 @@ class CMSSecurity extends Security {
|
||||
'success'
|
||||
);
|
||||
|
||||
/**
|
||||
* Enable in-cms reauthentication
|
||||
*
|
||||
* @var boolean
|
||||
* @config
|
||||
*/
|
||||
private static $reauth_enabled = true;
|
||||
|
||||
public function init() {
|
||||
parent::init();
|
||||
|
||||
@ -140,6 +148,9 @@ PHP
|
||||
* @return bool
|
||||
*/
|
||||
public static function enabled() {
|
||||
// Disable shortcut
|
||||
if(!static::config()->reauth_enabled) return false;
|
||||
|
||||
// Count all cms-supported methods
|
||||
$authenticators = Authenticator::get_authenticators();
|
||||
foreach($authenticators as $authenticator) {
|
||||
|
@ -30,7 +30,7 @@ class Member extends DataObject implements TemplateGlobalProvider {
|
||||
private static $db = array(
|
||||
'FirstName' => 'Varchar',
|
||||
'Surname' => 'Varchar',
|
||||
'Email' => 'Varchar(256)', // See RFC 5321, Section 4.5.3.1.3.
|
||||
'Email' => 'Varchar(254)', // See RFC 5321, Section 4.5.3.1.3. (256 minus the < and > character)
|
||||
'TempIDHash' => 'Varchar(160)', // Temporary id used for cms re-authentication
|
||||
'TempIDExpired' => 'SS_Datetime', // Expiry of temp login
|
||||
'Password' => 'Varchar(160)',
|
||||
@ -456,9 +456,7 @@ class Member extends DataObject implements TemplateGlobalProvider {
|
||||
}
|
||||
|
||||
// Clear the incorrect log-in count
|
||||
if(self::config()->lock_out_after_incorrect_logins) {
|
||||
$this->FailedLoginCount = 0;
|
||||
}
|
||||
$this->registerSuccessfulLogin();
|
||||
|
||||
// Don't set column if its not built yet (the login might be precursor to a /dev/build...)
|
||||
if(array_key_exists('LockedOutUntil', DB::field_list('Member'))) {
|
||||
@ -1536,6 +1534,16 @@ class Member extends DataObject implements TemplateGlobalProvider {
|
||||
$this->write();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell this member that a successful login has been made
|
||||
*/
|
||||
public function registerSuccessfulLogin() {
|
||||
if(self::config()->lock_out_after_incorrect_logins) {
|
||||
// Forgive all past login failures
|
||||
$this->FailedLoginCount = 0;
|
||||
$this->write();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the HtmlEditorConfig for this user to be used in the CMS.
|
||||
* This is set by the group. If multiple configurations are set,
|
||||
|
@ -75,6 +75,8 @@ class MemberAuthenticator extends Authenticator {
|
||||
if(!$success) {
|
||||
if($member) $member->registerFailedLogin();
|
||||
if($form) $form->sessionMessage($result->message(), 'bad');
|
||||
} else {
|
||||
if($member) $member->registerSuccessfulLogin();
|
||||
}
|
||||
|
||||
return $member;
|
||||
|
@ -38,7 +38,7 @@
|
||||
<li><p><a href="http://doc.silverstripe.org">doc.silverstripe.org</a> Searchable developer documentation, how-tos, tutorials, and reference.</p></li>
|
||||
|
||||
<li><p><a href="http://api.silverstripe.org">api.silverstripe.org</a> API documentation for PHP classes, methods and properties.</p></li>
|
||||
<ul>
|
||||
</ul>
|
||||
<% end_if %>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -418,7 +418,7 @@ class CmsUiContext extends BehatContext {
|
||||
'named',
|
||||
array('select', $this->getSession()->getSelectorsHandler()->xpathLiteral($field))
|
||||
);
|
||||
if($nativeField) {
|
||||
if($nativeField && $nativeField->isVisible()) {
|
||||
$nativeField->selectOption($value);
|
||||
return;
|
||||
}
|
||||
|
@ -382,6 +382,30 @@ class FileTest extends SapphireTest {
|
||||
$this->assertEquals($member1->ID, $file2->OwnerID, 'Owner not overwritten on existing files');
|
||||
}
|
||||
|
||||
public function testCanEdit() {
|
||||
$file = $this->objFromFixture('File', 'gif');
|
||||
|
||||
// Test anonymous permissions
|
||||
Session::set('loggedInAs', null);
|
||||
$this->assertFalse($file->canEdit(), "Anonymous users can't edit files");
|
||||
|
||||
// Test permissionless user
|
||||
$this->objFromFixture('Member', 'frontend')->logIn();
|
||||
$this->assertFalse($file->canEdit(), "Permissionless users can't edit files");
|
||||
|
||||
// Test cms non-asset user
|
||||
$this->objFromFixture('Member', 'cms')->logIn();
|
||||
$this->assertFalse($file->canEdit(), "Basic CMS users can't edit files");
|
||||
|
||||
// Test asset-admin user
|
||||
$this->objFromFixture('Member', 'assetadmin')->logIn();
|
||||
$this->assertTrue($file->canEdit(), "Asset admin users can edit files");
|
||||
|
||||
// Test admin
|
||||
$this->objFromFixture('Member', 'admin')->logIn();
|
||||
$this->assertTrue($file->canEdit(), "Admins can edit files");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public function setUp() {
|
||||
|
@ -28,3 +28,32 @@ File:
|
||||
Filename: assets/FileTest-folder1/File1.txt
|
||||
Name: File1.txt
|
||||
ParentID: =>Folder.folder1
|
||||
Permission:
|
||||
admin:
|
||||
Code: ADMIN
|
||||
cmsmain:
|
||||
Code: CMS_ACCESS_LeftAndMain
|
||||
assetadmin:
|
||||
Code: CMS_ACCESS_AssetAdmin
|
||||
Group:
|
||||
admins:
|
||||
Title: Administrators
|
||||
Permissions: =>Permission.admin
|
||||
cmsusers:
|
||||
Title: 'CMS Users'
|
||||
Permissions: =>Permission.cmsmain
|
||||
assetusers:
|
||||
Title: 'Asset Users'
|
||||
Permissions: =>Permission.cmsmain, =>Permission.assetadmin
|
||||
Member:
|
||||
frontend:
|
||||
Email: frontend@example.com
|
||||
cms:
|
||||
Email: cms@silverstripe.com
|
||||
Groups: =>Group.cmsusers
|
||||
admin:
|
||||
Email: admin@silverstripe.com
|
||||
Groups: =>Group.admins
|
||||
assetadmin:
|
||||
Email: assetadmin@silverstripe.com
|
||||
Groups: =>Group.assetusers
|
||||
|
@ -428,7 +428,12 @@ class UploadFieldTest extends FunctionalTest {
|
||||
$this->assertFileNotExists($file4->FullPath, 'File is also removed from filesystem');
|
||||
|
||||
// Test record-based permissions
|
||||
$response = $this->mockFileDelete('ManyManyFiles/', $fileNoDelete->ID);
|
||||
$response = $this->mockFileDelete('ManyManyFiles', $fileNoDelete->ID);
|
||||
$this->assertEquals(403, $response->getStatusCode());
|
||||
|
||||
// Test that folders can't be deleted
|
||||
$folder = $this->objFromFixture('Folder', 'folder1-subfolder1');
|
||||
$response = $this->mockFileDelete('ManyManyFiles', $folder->ID);
|
||||
$this->assertEquals(403, $response->getStatusCode());
|
||||
}
|
||||
|
||||
@ -467,20 +472,13 @@ class UploadFieldTest extends FunctionalTest {
|
||||
|
||||
$record = $this->objFromFixture('UploadFieldTest_Record', 'record1');
|
||||
$file4 = $this->objFromFixture('File', 'file4');
|
||||
$file5 = $this->objFromFixture('File', 'file5');
|
||||
$fileNoEdit = $this->objFromFixture('File', 'file-noedit');
|
||||
$baseUrl = 'UploadFieldTest_Controller/Form/field/ManyManyFiles/item/' . $file4->ID;
|
||||
$folder = $this->objFromFixture('Folder', 'folder1-subfolder1');
|
||||
|
||||
$response = $this->get($baseUrl . '/edit');
|
||||
$response = $this->mockFileEditForm('ManyManyFiles', $file4->ID);
|
||||
$this->assertFalse($response->isError());
|
||||
|
||||
$response = $this->post(
|
||||
$baseUrl . '/EditForm',
|
||||
array(
|
||||
'Title' => 'File 4 modified',
|
||||
'OwnerID' => $memberID
|
||||
)
|
||||
);
|
||||
$response = $this->mockFileEdit('ManyManyFiles', $file4->ID, array('Title' => 'File 4 modified'));
|
||||
$this->assertFalse($response->isError());
|
||||
|
||||
$record = DataObject::get_by_id($record->class, $record->ID, false);
|
||||
@ -488,10 +486,17 @@ class UploadFieldTest extends FunctionalTest {
|
||||
$this->assertEquals('File 4 modified', $file4->Title);
|
||||
|
||||
// Test record-based permissions
|
||||
$response = $this->post(
|
||||
'UploadFieldTest_Controller/Form/field/ManyManyFiles/item/' . $fileNoEdit->ID . '/edit',
|
||||
array()
|
||||
);
|
||||
$response = $this->mockFileEditForm('ManyManyFiles', $fileNoEdit->ID);
|
||||
$this->assertEquals(403, $response->getStatusCode());
|
||||
|
||||
$response = $this->mockFileEdit('ManyManyFiles', $fileNoEdit->ID, array());
|
||||
$this->assertEquals(403, $response->getStatusCode());
|
||||
|
||||
// Test folder permissions
|
||||
$response = $this->mockFileEditForm('ManyManyFiles', $folder->ID);
|
||||
$this->assertEquals(403, $response->getStatusCode());
|
||||
|
||||
$response = $this->mockFileEdit('ManyManyFiles', $folder->ID, array());
|
||||
$this->assertEquals(403, $response->getStatusCode());
|
||||
}
|
||||
|
||||
@ -897,6 +902,34 @@ class UploadFieldTest extends FunctionalTest {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the edit form for the given file
|
||||
*
|
||||
* @param string $fileField Name of the field
|
||||
* @param integer $fileID ID of the file to delete
|
||||
* @return SS_HTTPResponse form response
|
||||
*/
|
||||
protected function mockFileEditForm($fileField, $fileID) {
|
||||
return $this->get(
|
||||
"UploadFieldTest_Controller/Form/field/{$fileField}/item/{$fileID}/edit"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mocks edit submissions to a file
|
||||
*
|
||||
* @param string $fileField Name of the field
|
||||
* @param integer $fileID ID of the file to delete
|
||||
* @param array $fields Fields to update
|
||||
* @return SS_HTTPResponse form response
|
||||
*/
|
||||
protected function mockFileEdit($fileField, $fileID, $fields = array()) {
|
||||
return $this->post(
|
||||
"UploadFieldTest_Controller/Form/field/{$fileField}/item/{$fileID}/EditForm",
|
||||
$fields
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates a physical file deletion
|
||||
*
|
||||
@ -906,7 +939,7 @@ class UploadFieldTest extends FunctionalTest {
|
||||
*/
|
||||
protected function mockFileDelete($fileField, $fileID) {
|
||||
return $this->post(
|
||||
"UploadFieldTest_Controller/Form/field/HasOneFile/item/{$fileID}/delete",
|
||||
"UploadFieldTest_Controller/Form/field/{$fileField}/item/{$fileID}/delete",
|
||||
array()
|
||||
);
|
||||
}
|
||||
|
@ -14,17 +14,15 @@ class BasicAuthTest extends FunctionalTest {
|
||||
parent::setUp();
|
||||
|
||||
// Fixtures assume Email is the field used to identify the log in identity
|
||||
self::$original_unique_identifier_field = Member::config()->unique_identifier_field;
|
||||
Config::nest();
|
||||
Member::config()->unique_identifier_field = 'Email';
|
||||
Security::$force_database_is_ready = true; // Prevents Member test subclasses breaking ready test
|
||||
Member::config()->lock_out_after_incorrect_logins = 10;
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
Config::unnest();
|
||||
parent::tearDown();
|
||||
|
||||
BasicAuth::protect_entire_site(false);
|
||||
Member::config()->unique_identifier_field = self::$original_unique_identifier_field;
|
||||
Security::$force_database_is_ready = null;
|
||||
}
|
||||
|
||||
public function testBasicAuthEnabledWithoutLogin() {
|
||||
@ -107,6 +105,30 @@ class BasicAuthTest extends FunctionalTest {
|
||||
$_SERVER['PHP_AUTH_PW'] = $origPw;
|
||||
}
|
||||
|
||||
public function testBasicAuthFailureIncreasesFailedLoginCount() {
|
||||
// Prior to login
|
||||
$check = Member::get()->filter('Email', 'failedlogin@test.com')->first();
|
||||
$this->assertEquals(0, $check->FailedLoginCount);
|
||||
|
||||
// First failed attempt
|
||||
$_SERVER['PHP_AUTH_USER'] = 'failedlogin@test.com';
|
||||
$_SERVER['PHP_AUTH_PW'] = 'test';
|
||||
$response = Director::test('BasicAuthTest_ControllerSecuredWithoutPermission');
|
||||
$check = Member::get()->filter('Email', 'failedlogin@test.com')->first();
|
||||
$this->assertEquals(1, $check->FailedLoginCount);
|
||||
|
||||
// Second failed attempt
|
||||
$_SERVER['PHP_AUTH_PW'] = 'testwrong';
|
||||
$response = Director::test('BasicAuthTest_ControllerSecuredWithoutPermission');
|
||||
$check = Member::get()->filter('Email', 'failedlogin@test.com')->first();
|
||||
$this->assertEquals(2, $check->FailedLoginCount);
|
||||
|
||||
// successful basic auth should reset failed login count
|
||||
$_SERVER['PHP_AUTH_PW'] = 'Password';
|
||||
$response = Director::test('BasicAuthTest_ControllerSecuredWithoutPermission');
|
||||
$check = Member::get()->filter('Email', 'failedlogin@test.com')->first();
|
||||
$this->assertEquals(0, $check->FailedLoginCount);
|
||||
}
|
||||
}
|
||||
|
||||
class BasicAuthTest_ControllerSecuredWithPermission extends Controller implements TestOnly {
|
||||
|
@ -9,6 +9,10 @@ Member:
|
||||
user-without-groups:
|
||||
Email: user-without-groups@test.com
|
||||
Password: test
|
||||
failed-login:
|
||||
Email: failedlogin@test.com
|
||||
Password: Password
|
||||
FailedLoginCount: 0
|
||||
Permission:
|
||||
mycode:
|
||||
Code: MYCODE
|
||||
|
Loading…
Reference in New Issue
Block a user