Skip to content

Instantly share code, notes, and snippets.

@Zauberfisch
Last active January 15, 2020 07:16
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Zauberfisch/9460395 to your computer and use it in GitHub Desktop.
Save Zauberfisch/9460395 to your computer and use it in GitHub Desktop.
SilverStripe 3.x DataObject as Page with URLSegment
<?php
/**
* @author Zauberfisch
* @method ManyManyList Products()
*/
class ProductCategoryPage extends Page {
private static $many_many = array(
'Products' => 'Product',
);
private static $many_many_extraFields = array(
'Products' => array(
'SortOnPage' => 'Int',
),
);
private static $allowed_children = 'none';
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root', Tab::create('Products', $this->fieldLabel('ProductsTab')));
$fields->addFieldToTab('Root.Products', GridField::create(
'Products',
$this->fieldLabel('Products'),
$this->Products(),
GridFieldConfig::create()
->addComponent(new GridFieldButtonRow('before'))
->addComponent(new GridFieldAddExistingAutocompleter('buttons-before-left'))
->addComponent(new GridFieldDataColumns())
->addComponent(new GridFieldOrderableRows('SortOnPage'))
->addComponent(new GridFieldTitleHeader())
->addComponent(new GridFieldDeleteAction(true))
));
return $fields;
}
public function fieldLabels($includerelations = true) {
$return = parent::fieldLabels($includerelations);
$return['ProductsTab'] = _t('ProductCategoryPage.ProductsTab', 'Products');
$return['Products'] = _t('ProductCategoryPage.Products', 'Products');
return $return;
}
public function SubMenu() {
if ($this->isSection()) {
$menu = ArrayList::create();
foreach ($this->Products() as $item) {
$menu->push($item->customise(array(
// to allow <% if $Current %> in templace
'Current' => $item->ID == ProductCategoryPage_Controller::$current_product_id
)));
}
return $menu;
} else {
return $this->Products();
}
}
}
/**
* @author Zauberfisch
*/
class ProductCategoryPage_Controller extends Page_Controller {
public static $current_product_id;
private static $allowed_actions = array(
'product'
);
public function product(SS_HTTPRequest $r) {
$p = Product::get_by_url_segment(Convert::raw2sql($r->param('ID')));
if (!$p) {
return ErrorPage::responseFor(404);
}
static::$current_product_id = $p->ID;
return $this->customise($p)->renderWith(array('Product', 'Page'));
}
}
/**
* @author Zauberfisch
* @property Varchar Title
* @property Varchar MenuTitle
* @property HTMLText Content
* @property Varchar URLSegment
* @method ManyManyList Categories
*/
class Product extends DataObject {
private static $db = array(
'Title' => 'Varchar(255)',
'MenuTitle' => 'Varchar',
'Content' => 'HTMLText',
'URLSegment' => 'Varchar(255)',
);
private static $belongs_many_many = array(
'Categories' => 'ProductCategoryPage',
);
private static $summary_fields = array(
'Title',
'URLSegment',
);
public function getCMSFields() {
return new FieldList(array(
TextField::create('Title', $this->fieldLabel('Title')),
TextField::create('MenuTitle', $this->fieldLabel('MenuTitle')),
TextField::create('URLSegment', $this->fieldLabel('URLSegment')),
// ListboxField::create('Categories', _t('Product.Categories', 'Categories'))->setMultiple(true)->setSource(CategoryPage::get()->map('ID', 'MenuTitle')->toArray()),
HTMLEditorField::create('Content', $this->fieldLabel('Content')),
));
}
public function fieldLabels($includerelations = true) {
$return = parent::fieldLabels($includerelations);
$return['Title'] = _t('Product.Title', 'Title');
$return['MenuTitle'] = _t('Product.MenuTitle', 'Menu Title');
$return['URLSegment'] = _t('Product.URLSegment', 'URL Segment');
$return['Content'] = _t('Product.Content', 'Content');
return $return;
}
protected function onBeforeWrite() {
parent::onBeforeWrite();
if (!$this->MenuTitle) {
$this->MenuTitle = $this->Title;
}
$filter = URLSegmentFilter::create();
if (!$this->URLSegment) {
$this->URLSegment = $this->Title;
}
$this->URLSegment = $filter->filter($this->URLSegment);
if (!$this->URLSegment) {
$this->URLSegment = uniqid();
}
$count = 2;
while (static::get_by_url_segment($this->URLSegment, $this->ID)) {
// add a -n to the URLSegment if it already existed
$this->URLSegment = preg_replace('/-[0-9]+$/', null, $this->URLSegment) . '-' . $count;
$count++;
}
}
/**
* @return string
*/
public function Link() {
if ($this->isInDB()) {
$controller = Controller::curr();
if ($controller->is_a('ProductCategoryPage') &&
$controller->data() &&
$this->Categories()->byID((int)$controller->data()->ID)->exists()
) {
// this product is in this category, so lets use this category as link
$category = $controller->data();
} elseif ($this->Categories()->count()) {
$category = $this->Categories()->First();
} else {
$category = ProductCategoryPage::get()->First();
}
if ($category && $category->exists()) {
return Controller::join_links($category->Link(), 'product', $this->URLSegment);
}
}
return '';
}
/**
* @var array
*/
protected static $_cached_get_by_url = array();
/**
* @param $str
* @return Product|Boolean
*/
public static function get_by_url_segment($str, $excludeID = null) {
if (!isset(static::$_cached_get_by_url[$str])) {
$list = static::get()->filter('URLSegment', $str);
if ($excludeID) {
$list = $list->exclude('ID', $excludeID);
}
$obj = $list->First();
static::$_cached_get_by_url[$str] = ($obj && $obj->exists()) ? $obj : false;
}
return static::$_cached_get_by_url[$str];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment