Below, anyone is welcome to add ideas for a Silvestripe Cheat Sheet. If you dont want to add anything directly, but you suggest we remove / change / rethink something then please add a comment at the bottom. Please do not delete or alter anything substantial that has been added by someone else so that we can hear all voices before making a final cheat sheet.
For now, dont worry too much about the formatting and sorting of this page. At some stage, we will go through the whole page and standardise formats and group, sort, and merge items.
Having said that, the key is brevity. Dont explain things, just give people keywords for quick reference.
to swith between Page and Page_Live and the like:
if(Versioned::current_stage() == "Live") { $extension = "_Live"; }
class ClassA extends DataObject { static $many_many = array( 'ClassBs' => 'ClassB'); function getMyClassBs() { return $this->getManyManyComponents('ClassBs'); } function ManyIDs $components = $this->owner->getManyManyComponents('ClassBs'); if($components && $components->count()) { return $components->column("ID"); } else { return array(); } } } class ClassB extends DataObject { static $belongs_many= array('ClassAs' => 'ClassA'); function getClassAs() { return $this->ClassAs(); } }
OR
class MyObject extends DataObject { ... static $many_many = array( "Pages" => "SiteTree" ); ... function getActualPages() { $combos = $this->Pages(); if($combos) { $idArray = array(); foreach($combos as $combo) { $idArray[$combos->SiteTreeID] = $combos->SiteTreeID; } if(count($idArray)) { return DataObject::get("SiteTree", "`SiteTree`.`ID` IN (".implode(",", $idArray).")")); } } } ... }
$sqlQuery = new SQLQuery( $select = "SiteTree.ParentID, Count(SiteTree.ID) ", $from = array('SiteTree INNER JOIN SiteTree AS ParentTable On ParentTable.ID = SiteTree.ParentID'), $where = "SiteTree.ID > 10", $orderby = "Sort DESC", $groupby = "SiteTree.ParentID", $having = "", $limit = "" ); $results = $sqlQuery->execute();
$myUsefullField = DBField::create($className = "Currency", $value = 1111.11); $formattedField = $myUsefullField->Nice();
The following functions can be added to a DataObject:
function validate: function validate() { return new ValidationResult(false, "Dont you dare to change my dataObject"); }
function onBeforeWrite: dont forget to run parent onBeforeWrite(), if this function returns true, it does not save the dataobject [to do CHECK THIS]function onAfterWrite function onAfterWrite() { parent::onAfterWrite(); $fields = $this->getChangedFields(); if (isset ($fields['MyField']['before'])) { die("My field used to be: ".$fields['MyField']['before']); } }
function requireDefaultRecords:: do not forget to call parent::requireDefaultRecords()function populateDefaults:: do not forget to call parent::populateDefaults()class Team extends DataObject { static $many_many = array("Categories" => "Category"); function addCategories($additionalCategories) { $existingCategories = $this->Categories(); // method 1: Add many by iteration foreach($additionalCategories as $category) { $existingCategories->add($category); } // method 2: Add many by ID-List $existingCategories->addMany(array(1,2,45,745)); } }
save:
$page->writeToStage('Stage'); $page->Publish('Stage', 'Live'); $page->Status = "Published"; $page->flushCache();
delete:
$id = $page->ID; $stageRecord = Versioned::get_one_by_stage('SiteTree', 'Stage', "SiteTree.ID = $id"); if ($stageRecord) $stageRecord->delete(); $liveRecord = Versioned::get_one_by_stage('SiteTree', 'Live', "SiteTree_Live.ID = $id"); if ($liveRecord) $liveRecord->delete(); $page->flushCache();
change classname:
$dos = DataObject::get("OldClassName"); if($dos) { foreach($dos as $page) { $page->setClassName("OldClassName"); //not sure if we need this... $page = $page->newClassInstance("NewClassName"); $page->writeToStage("Stage"); $page->publish("Stage", "Live"); DB::alteration_message("Moving: ".$page->Title, "created"); } }
class Carrot extends DataObject { //database public static $db = array("Name" => "Varchar(255)"); public static $has_one = array("Pixie" => "Image", "Parent" => "Page"); public static $has_many = array(); public static $many_many = array(); public static $belongs_many_many = array(); public static $many_many_extraFields = array(); //database related settings static $indexes = array( "SearchFields" => "fulltext (Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords)", "TitleSearchFields" => "fulltext (Title)", "Sort" => true, "Uniques" => "Unique('URLSegment')", ); //formatting public static $casting = array(); //adds computed fields that can also have a type (e.g. public static $searchable_fields = array("Name" => "PartialMatchFilter"); public static $field_labels = array("Name" => "Carrot Name"); public static $summary_fields = array("Name" => "Name", "Parent.Title", "TinyThumbPhoto" => "Pixie"); //note no => for relational fields public static $singular_name = "Carrot"; public static $plural_name = "Carrots"; //CRUD settings static $can_create = Boolean; public function canCreate($member = null) {return false;} public function canView($member = null) {return false;} public function canEdit($member = null) {return false;} public function canDelete($member = null) {return false;} //defaults public static $default_sort = "Sort ASC, Name ASC"; public static $defaults = array();//use fieldName => Default Value public function populateDefaults() { parent::populateDefaults(); } public function TinyThumbPhoto() { return $this->Pixie()->CroppedImage(100,100); } }
class MyModelAdmin extends ModelAdmin { public static $managed_models = array("Carrot"); public static $url_segment = 'carrots'; public static $menu_title = 'Your Carrots'; public static $collection_controller_class = 'MyModelAdmin_CollectionController'; public static $record_controller_class = 'MyModelAdmin_RecordController'; public $showImportForm = false; } class MyModelAdmin_CollectionController extends ModelAdmin_CollectionController{ //manages everything to do with overall control (e.g. search form, import, etc...) public function SearchForm() { $form = parent::SearchForm(); return $form; } } class MyModelAdmin_RecordController extends ModelAdmin_RecordController { //manages everything to do with individual record public function EditForm() { $form = parent::EditForm(); $form->Actions()->removeByName('Delete'); return $form; } }
class MyPage extends Page {
class MyPage extends Page { //appearance static $icon = "mymodule/images/treeicons/MyPage"; static $breadcrumbs_delimiter = "»"; //parents and children in sitetree static $allowed_children = array("Blog"); //can also be "none"; static $default_child = "Blog"; static $default_parent = "blogs-and-more"; // *URLSegment* of default parent node. static $can_be_root = false; //default is true //parents and children in classes static $hide_ancestor = "MyUselessPage"; // //CRUD settings static $can_create = Boolean; public function canCreate() {return false;} public function canView() {return false;} public function canEdit() {return false;} public function canDelete() {return false;} //database - use "fieldName" => "FieldClass" static $db = array(); static $has_one = array(); static $has_many = array(); static $many_many = array(); static $belongs_many_many = array(); static $many_many_extraFields = array(); static $casting = array(); //adds computed fields that can also have a type (e.g. Currency) //database related settings static $indexes = array( "SearchFields" => "fulltext (Title, MenuTitle, Content, MetaTitle, MetaDescription, MetaKeywords)", "TitleSearchFields" => "fulltext (Title)", "Sort" => true, "Uniques" => "Unique('URLSegment')", ); //defaults static $default_sort = "Sort ASC, Name ASC"; static $defaults = array();//use fieldName => Default Value //fields function getCMSFields() { $fields = parent::getCMSFields(); return $fields; } } class MyPage extends Page_Controller{ function init() { parent::init(); } }
public function extraStatics() { return array ( 'db' => array( 'SomeField' => 'Varchar' ), 'has_many' => array( 'MyProp' => 'RelatedClass' ) ); }
Other useful functions:
function augmentSQL(SQLQuery &$query) {} function augmentDatabase() {} function augmentWrite(&$manipulation) {} function onBeforeWrite() {} function onAfterWrite() {} function onBeforeDelete() {} function onAfterDelete() {} function requireDefaultRecords() {} function populateDefaults() {} function can($member) {} function canEdit($member) {} function canDelete($member) {} function canCreate($member) {} function extraStatics() {} function updateCMSFields(FieldSet &$fields) {} function updateFrontEndFields(FieldSet &$fields) {} function updateCMSActions(FieldSet &$actions) {} function updateSummaryFields(&$fields){} function updateFieldLabels(&$lables){} function flushCache() {}
To check if an extension exists, use $object→hasExtension (e.g. $MyPage→hasExtension(“MyObjectDecorator”);
add to _config.php
Object::add_extension("SiteConfig", "SiteConfigExtras");
create a new file: SiteConfigExtras.php (here are some example tricks):
class SiteConfigExtras extends DataObjectDecorator { function extraStatics(){ return array( 'many_many' => array( "TopMenuItems" => "SiteTree", ), ); } function updateCMSFields(FieldSet &$fields) { $sourceObjectName = "SiteTree"; $fields->addFieldToTab("Root.Menus", new TreeMultiselectField($name = "TopMenuItems", $title = "Top Menu Items", $sourceObjectName)); return $fields; } }
add the following to Page.php
class Page_Controller extends ContentController { function TopMenuItems() { $siteConfig = $this->getSiteConfig(); if($siteConfig){ return $siteConfig->TopMenuItems(); } } }
and add the following to your Template file (e.g. TopMenuItems.ss):
<ul> <% control TopMenuItems %> <li>$Title , $Link</li> <% end_control %> </ul>
getting a dropdown of assets folders:
$folder = new TreeDropdownField( 'FieldWithIDHere', 'Title here', 'Folder' ); $folder->setFilterFunction( create_function( '$obj', 'return $obj->class == "Folder";' ) );
usage:
$newValue = Convert::$functionName($oldValue);
, examples are: raw2att, raw2xml, raw2json, raw2sql, json2obj, json2array, linkIfMatch
Here are some examples
function dosomething(SS_HTTPRequest $request){ $var = $request->getVars(); $var = $request->postVars(); $var = $request->requestVars(); $var = $request->requestVar($name = "Inputter"); $var = $request->getURL(); $var = $request->allParams(); $var = $request->param($name = "Test"); }
Get logged in member:
Formatting:
Basic security concept:
granting permissions
class MyPage extends Page { ............. public function canView() { if(Permission::check("MY_SPECIAL_CODE_HERE")) { return true; } Security::permissionFailure($this, 'You must login before you can view these entries'); } public function runupdate() { if(Permission::check('ADMIN')) { $this->updateEntries() } else { Security::permissionFailure($this, 'You must login before you can update these entries'); } } public function requireDefaultRecords() { parent::requireDefaultRecords(); $bt = defined('DB::USE_ANSI_SQL') ? "\"" : "`"; $gp = DataObject::get_one("Group", "Code = '".self::$news_editor_group_code."'"); if(!$gp) { $gp = new Group(); $gp->Code ="MY_SPECIAL_GROUP"; $gp->Title = "My Group"; $gp->write(); } if($gp) { if(DB::query(" SELECT {$bt}ID{$bt} FROM Permission WHERE {$bt}GroupID{$bt} = '".$gp->ID."' AND {$bt}Code{$bt} = 'MY_SPECIAL_CODE_HERE'" )->numRecords() == 0 ) { Permission::grant($gp->ID, "MY_SPECIAL_CODE_HERE"); } } } .............. }
class NewsPage extends Page { protected static $news_editor_group_name = "News Items Editor Group"; protected static $news_editor_group_code = "NEWS_ITEMS_EDITORS"; public static $news_editor_permission_code = "NEWS_ITEMS_EDITORS_PERMISSION"; public function canEdit($member = null) { if(Permission::check(self::$news_editor_permission_code)) { return true; } Security::permissionFailure($this, 'You must login before you can view these entries'); } public function canCreate($member = null) { return $this->canEdit($member); } public function canDelete($member = null) { return $this->canEdit($member); } public function requireDefaultRecords() { parent::requireDefaultRecords(); $bt = defined('DB::USE_ANSI_SQL') ? "\"" : "`"; $gp = DataObject::get_one("Group", "Code LIKE '".self::$news_editor_group_code."'"); if(!$gp) { $gp = new Group(); $gp->Code = self::$news_editor_group_code; $gp->Title = self::$news_editor_group_name; $gp->write(); } if($gp) { if(DB::query(" SELECT {$bt}ID{$bt} FROM Permission WHERE {$bt}GroupID{$bt} = '".$gp->ID."' AND {$bt}Code{$bt} LIKE '".self::$news_editor_permission_code."'" )->numRecords() == 0 ) { Permission::grant($gp->ID, self::$news_editor_permission_code); } if(DB::query(" SELECT {$bt}ID{$bt} FROM Permission WHERE {$bt}GroupID{$bt} = '".$gp->ID."' AND {$bt}Code{$bt} LIKE 'CMS_ACCESS_CMSMain'" )->numRecords() == 0 ) { Permission::grant($gp->ID, "CMS_ACCESS_CMSMain"); } } } } class NewsPage_Controller extends Page_Controller implements PermissionProvider { function providePermissions() { $perms["NEWS_ITEMS_EDITORS_PERMISSION"] = array( 'name' => "edit news items in CMS", 'category' => "Content Editors", 'help' => 'Editing news items in Pages section of CMS', 'sort' => -100 ); return $perms; } }
HomePage.php
class HomePage extends Page { public function canAddChildren($member = null) { if(Permission::check(NewsPage::$news_editor_permission_code)) { return true; } Security::permissionFailure($this, 'You must login before you can view these entries'); } }
Page.php
class Page extends SiteTree { public function canEdit($member = null) { if(parent::canEdit()) { return Permission::check("ADMIN"); } return false; } public function canAddChildren($member = null) { return $this->canEdit($member); } public function canCreate($member = null) { return $this->canEdit($member); } public function canDelete($member = null) { return $this->canEdit($member); } }
Common sapphire related options for your mysite/_config.php file:
SSViewer::set_theme('mytheme'); Geoip::$default_country_code = "NZ"; GD::set_default_quality(80); /* Setting email defaults */ Email::setAdminEmail("example@best.com"); Debug::sendLiveErrorsTo('example2@best.com'); //debug option: Email::send_all_emails_to("example@best.com"); /* Changing the breadcrumbs delimiter */ SiteTree::$breadcrumbs_delimiter = " > "; /* Enabling moderation for comments */ PageComment::enableModeration(); /* enables basic math anti spam question field on comments */ MathSpamProtection::setEnabled() /* Manually setting default admin */ Security::setDefaultAdmin('admin', 'password'); /* Add wysiwyg (TinyMCE) editor to blog rather then default BBCode */ BlogEntry::allow_wysiwyg_editing(); /* ADD RULES */ // double forward-slash: consumed by rule system // used by controller // The ! after a variable name means that the variable is required, and the rule wont match unless the variable is specified. Director::addRules(50, array( 'processes//!$Action/$ID/$Batch' => 'BatchProcess_Controller', ));
Main buttons:
Adding CMS fields
public function getCMSFields() { $fields = parent::getCMSFields(); $fields->addFieldToTab('Root.Content.News', new TextField("NewsHeading", "News Heading")); return $fields }
function updateCMSFields(FieldSet &$fields) { $fields->addFieldToTab('Root.Content.News', new TextField("NewsHeading", "News Heading")); return $fields; }
Copy template files from /cms/templates/ to /themes/mytheme_cms/templates and change as needed.
$e = new Email($from, $to, $subject, $body, $bounceHandlerURL, $cc, $bcc); $e->send(); //OR $e->sendPlain();
function MyCustomForm() { $fields = new FieldSet( new EmailField("Email"), new EncryptField("Password") ); $actions = new FieldSet(new FormAction("login", "Log in")); return new Form($this, "MyCustomForm", $fields, $actions); }
new DropdownField( $name = 'DataObjectID', $title = 'do the dropdown', $source = Dataobject::get("DataObject")->toDropdownMap("ID", "Title",$emptyString = "--select--", $sortByTitle = true), $value = 1, );
$treeField = new TreeMultiselectField("Parent", "Shown on the following pages", "SiteTree"); $callback = create_function('$obj', 'return $obj->class == "HomePage";'); $treeField->setFilterFunction ( $callback ); $fields->addFieldToTab("Root.Main",$treeField);
new DropdownField('Method','Payment Method',singleton($this->ClassName)->dbObject('MyEnumField')->enumValues());
$fields->replaceField("EmailSent", $fields->dataFieldByName("EmailSent")->performReadonlyTransformation());
HtmlEditorConfig::get('cms')->setOption('theme_advanced_blockformats','p,h1'); HtmlEditorConfig::get('cms')->setButtonsForLine(1,'undo, redo, separator, cut, copy, pastetext, separator, ssimage, sslink, unlink, separator, fullscreen, advcode, formatselect'); HtmlEditorConfig::get('cms')->setButtonsForLine(2); HtmlEditorConfig::get('cms')->setButtonsForLine(3);
class OneFolderImageField extends ImageField { function __construct($name, $title, $value = null, $form = null, $rightTitle = null, $folderName = null) { $folder = Folder::findOrMake($folderName); $this->folderName = $folderName; parent::__construct($name, $title, $value = null, $form = null, $rightTitle = null, $folder->Name); } public function EditFileForm() { $filter = create_function( '$item', ' $folder = Folder::findOrMake(\''.$this->folderName.'\'); return (in_array("Image", ClassInfo::ancestry($item->ClassName)) && $item->ParentID == $folder->ID) || (in_array("Folder", ClassInfo::ancestry($item->ClassName)) && $item->ID == $folder->ID) ;'); $form = parent::EditFileForm(); $form->dataFieldByName('ExistingFile')->setFilterFunction($filter); return $form; } }
$orders = DataObject::get('Order'); $table = new ComplexTableField( $controller = $this, $name = 'PreviousOrders', $sourceClass = 'Order', $fieldList = array( "Total" => "Value", "Created" => "Created", "Link" => "Actions" ), $detailFormFields = new FieldSet(), $sourceFilter = "StandingOrderID = ".$this->ID, $sourceSort = "Created DESC", $sourceJoin = "" ); $table->setFieldCasting(array( 'Created' => 'Date->Long', 'Total' => 'Currency->Nice' )); $table->setFieldFormatting(array( 'Link' => '<a href=\"OrderReportWithLog_Popup/invoice/$ID\" class=\"makeIntoPopUp\">View</a>' )); $table->setShowPagination(false); $table->setAddTitle('Example Table'); $table->setPermissions(array("export")); return $table;
add thumbnail to DataObject:
public function Thumbnail() { if($this->ImageID) return $this->Image()->CMSThumbnail(); }
$this->resetField("Country", self::$fixed_country_code);
$this->fields->replaceField("OldFieldName", New TextField("NewField"));
$form->unsetActionByName($name);
adding widgets to non-blog pages:
<% require css(cms/css/TreeSelector.css) %> <% require themedCSS(TreeSelector) %> <% require javascript(cms/javascript/LeftAndMain.js) %>