Silverstripe Site Search for DataObjects as Pages - Part 2 tutorial - php

I made a product site at the end of last year using DataObjects as Pages - Part 2 Silverstripe, the site is live now, and I need to implement a site search function for the site.
I implemented a search function like Tutorial 4 - Site Search however this doesn't work with the product search since each product is a dataobject rather than a page.
Can anyone shed some light on how I can make the site search work for the products?
I know there is a tutorial 3 DataObject as Pages I tried it but it messed up all my existing products as well as some additional existing functions for the products. Someone suggested http://silverstripe.org/all-other-modules/show/6641?start=24 but unsuccessful so far.
Any help on how to do the search function for the products is appreciated.
Thanks.
Here is my Product.php code
<?php
class Product extends DataObject
{
static $db = array(
'Title' => 'Varchar(255)',
'Description' => 'HTMLText',
'Price' => 'Decimal(6,2)',
'URLSegment' => 'Varchar(255)'
);
//Set our defaults
static $defaults = array(
'Title' => 'New Product',
'URLSegment' => 'new-product'
);
static $has_one = array(
'Image' => 'Image',
'PDF' => 'File'
);
//Relate to the category pages
static $belongs_many_many = array(
'Categories' => 'CategoryPage'
);
//Fields to show in ModelAdmin table
static $summary_fields = array(
'Title' => 'Title',
'URLSegment' => 'URLSegment',
'Price' => 'Price (£)'
);
//Add an SQL index for the URLSegment
static $indexes = array(
"URLSegment" => true
);
//Fields to search in ModelAdmin
static $searchable_fields = array (
'Title',
'URLSegment',
'Description',
'Categories.ID' => array(
'title' => 'Category'
)
);
function getCMSFields()
{
$fields = parent::getCMSFields();
//Main Tab
$fields->addFieldToTab("Root.Main", new TextField('Title', 'Title'));
$fields->addFieldToTab("Root.Main", new TextField('URLSegment', 'URL Segment'));
$fields->addFieldToTab("Root.Main", new NumericField('Price'));
$fields->addFieldToTab("Root.Main", new HTMLEditorField('Description'));
//added below for the ordering
$Categories = DataObject::get('CategoryPage');
$map = $Categories->map('ID', 'CheckboxSummary');
asort($map);
$fields->addFieldToTab("Root.Categories", new CheckboxsetField('Categories', 'Categories', $map));
//Images
$fields->addFieldToTab("Root.Images", new ImageField('Image', 'Image', Null, Null, Null, 'Uploads/category_banners'));
$fields->addFieldToTab("Root.Files", new FileIFrameField('PDF'));
return $fields;
}
//Set URLSegment to be unique on write
function onBeforeWrite()
{
// If there is no URLSegment set, generate one from Title
if((!$this->URLSegment || $this->URLSegment == 'new-product') && $this->Title != 'New Product')
{
$this->URLSegment = SiteTree::generateURLSegment($this->Title);
}
else if($this->isChanged('URLSegment'))
{
// Make sure the URLSegment is valid for use in a URL
$segment = preg_replace('/[^A-Za-z0-9]+/','-',$this->URLSegment);
$segment = preg_replace('/-+/','-',$segment);
// If after sanitising there is no URLSegment, give it a reasonable default
if(!$segment) {
$segment = "product-$this->ID";
}
$this->URLSegment = $segment;
}
// Ensure that this object has a non-conflicting URLSegment value.
$count = 2;
while($this->LookForExistingURLSegment($this->URLSegment))
{
$this->URLSegment = preg_replace('/-[0-9]+$/', null, $this->URLSegment) . '-' . $count;
$count++;
}
parent::onBeforeWrite();
}
//Test whether the URLSegment exists already on another Product
function LookForExistingURLSegment($URLSegment)
{
return (DataObject::get_one('Product', "URLSegment = '" . $URLSegment ."' AND ID != " . $this->ID));
}
//Generate the link for this product
function Link()
{
//if we are on a category page return that
if(Director::CurrentPage()->ClassName == 'CategoryPage')
{
$Category = Director::CurrentPage();
}
//Otherwise just grab the first category this product is in
else
{
$Category = $this->Categories()->First();
}
//Check we have a category then return the link
if($Category)
{
return $Category->absoluteLink() . 'show/' . $this->URLSegment;
}
}
//Return the Title as a menu title
public function MenuTitle()
{
return $this->Title;
}
function canView() {
return true;
}
public function LinkingMode()
{
//Check that we have a controller to work with and that it is a StaffPage
if(Controller::CurrentPage() && Controller::CurrentPage()->ClassName == 'CategoryPage')
{
//check that the action is 'show' and that we have a StaffMember to work with
if(Controller::CurrentPage()->getAction() == 'show' && $Product = Controller::CurrentPage()->getCurrentProduct())
{
//If the current StaffMember is the same as this return 'current' class
return ($Product->ID == $this->ID) ? 'current' : 'link';
}
}
}
}
and here is my CategoryPage.php
<?php
class CategoryPage extends Page
{
static $has_one = array(
'CategoryBanner' => 'Image',
'Photo' => 'Image'
);
static $many_many = array(
'Products' => 'Product'
);
static $allowed_children = array(
'none' => 'none'
);
function getCMSFields()
{
$fields = parent::getCMSFields();
$fields->addFieldToTab("Root.Content.Images", new ImageField('Photo'));
//Banner Images
$fields->addFieldToTab("Root.Content.Banner", new ImageField('CategoryBanner', 'Banner', Null, Null, Null, 'Uploads/category_banners'));
return $fields;
}
//important for sidebar showing, this is sitetree stuff - relationship between categories and products 20012012
public function onBeforeDelete()
{
$CurrentVal = $this->get_enforce_strict_hierarchy();
$this->set_enforce_strict_hierarchy(false);
parent::onBeforeDelete();
$this->set_enforce_strict_hierarchy($CurrentVal);
}
public function Children(){
return $this->Products();
}
//added this on 03022011 for the parent page to show on Categories in admin
function CheckboxSummary(){
return $this->Parent()->Title . ' - ' . $this->Title;
}
}
class CategoryPage_Controller extends Page_Controller
{
static $allowed_actions = array(
'show'
);
public function init()
{
parent::init();
Requirements::css('themes/tutorial/css/products.css');
//added this to make the gallery js work 10012012
Requirements::set_write_js_to_body(false);
Requirements::javascript("mysite/javascript/jquery-1.4.2.min.js"); Requirements::javascript("mysite/javascript/jquery.cycle.lite.min.js");
Requirements::javascript("mysite/javascript/toggle_menu.js");
}
//Return the list of products for this category
public function getProductsList()
{
return $this->Products(Null, 'Price ASC');
}
//Get's the current product from the URL, if any
public function getCurrentProduct()
{
$Params = $this->getURLParams();
$URLSegment = Convert::raw2sql($Params['ID']);
if($URLSegment && $Product = DataObject::get_one('Product', "URLSegment = '" . $URLSegment . "'"))
{
return $Product;
}
}
//Shows the Product detail page
function show()
{
//Get the Product
if($Product = $this->getCurrentProduct())
{
$Data = array(
'Product' => $Product,
'MetaTitle' => $Product->Title
);
//return our $Data array to use, rendering with the ProductPage.ss template
return $this->customise($Data)->renderWith(array('ProductPage', 'Page'));
}
else //Product not found
{
return $this->httpError(404, 'Sorry that product could not be found');
}
}
//Generate out custom breadcrumbs
public function Breadcrumbs() {
//Get the default breadcrumbs
$Breadcrumbs = parent::Breadcrumbs();
if($Product = $this->getCurrentProduct())
{
//Explode them into their individual parts
$Parts = explode(SiteTree::$breadcrumbs_delimiter, $Breadcrumbs);
//Count the parts
$NumOfParts = count($Parts);
//Change the last item to a link instead of just text
$Parts[$NumOfParts-1] = ('' . $Parts[$NumOfParts-1] . '');
//Add our extra piece on the end
$Parts[$NumOfParts] = $Product->Title;
//Return the imploded array
$Breadcrumbs = implode(SiteTree::$breadcrumbs_delimiter, $Parts);
}
return $Breadcrumbs;
}
}

If you are doing any serious search stuff, the built-in search functionality (based on MySQL MyISAM) is not ideal. I'd suggest to use Solr or Sphinx, integrated into SilverStripe with https://github.com/silverstripe/silverstripe-sphinx or https://github.com/nyeholt/silverstripe-solr (I'd start off with the first one). This will also index DAOs.

Related

How to create the edit form in Silverstripe 4.2 frontend?

I wish to create the edit form in Silverstripe 4.2, much like this Stack Overflow's edit function that i'm looking for.
EDITED: I want to be able to have a page that is only available to the registered member of my website that they can post their class listings on the Frontend (not in CMS) as an owner, and need to have a 'edit' click that takes you to an identical form (same ClassListingForm) that lets member owner to edit/update their own class listings that they have posted. I have everything working except the edit and submit functions which I'm stuck on at the moment.
I have a link for editing the specific class listing:
Edit class listing</div>
It does redirected to 404 page not found with this url shown:
"http://.../learners/class-listings/edit/61"
Here's the code below I have so far, the ClassListingForm is working fine, just need to get the EditListingForm and doClassListing functions to work properly, and i may be doing something wrong in these codes? or is there a better way of doing the edit form properly which i'm unable to find anywhere on the search for specific on what i need as there's not much tutorial that covers the EditForm function on the SilverStripe lessons.
<?php
class ClassListings extends DataObject {
private static $table_name = 'ClassListings';
private static $db = [
'CourseTitle' => 'Varchar(255)',
'CourseLocation' => 'Varchar(255)',
];
private static $has_one = [
'ClassListingPage' => ClassListingPage::class,
];
}
<?php
class ClassListingPageController extends PageController {
private static $allowed_actions = [
'ClassListingForm',
'ClassEditForm'
];
public function ClassListingForm() {
$id = (int)$this->urlParams['ID'];
$data = ($id)? $data = ClassListings::get()->byID($id) : false;
$form = Form::create(
$this,
__FUNCTION__,
FieldList::create(
TextField::create('CourseTitle', 'Course title:')
->setAttribute('placeholder', 'NZSL Level 1, NZSL 1A')
->setCustomValidationMessage('Please enter the course title field')
->addExtraClass('requiredField CourseTitle'),
TextField::create('CourseLocation','Region:')
->setAttribute('placeholder', 'Enter region')
->setCustomValidationMessage('Please enter the region field')
->addExtraClass('requiredField'),
HiddenField::create('ID', 'ID')->setValue($ClassListingPageID)
),
FieldList::create(
FormAction::create('handleClassListing')
->setTitle('Post your class listing')
->addExtraClass('btn btn-primary primary')
),
RequiredFields::create(
'CourseTitle',
'CourseLocation'
)
);
$form->loadDataFrom(Member::get()->byID(Member::currentUserID()));
$form->getSecurityToken()->getValue();
if ($form->hasExtension('FormSpamProtectionExtension')) {
$form->enableSpamProtection();
}
$data = $this->getRequest()->getSession()->get("FormData.{$form->getName()}.data");
return $data ? $form->loadDataFrom($data) : $form;
}
public function handleClassListing($data, $form) {
$session = $this->getRequest()->getSession();
$session->set("FormData.{$form->getName()}.data", $data);
$class = ClassListings::create($this->owner);
$class->CourseTitle = $data['CourseTitle'];
$class->CourseLocation = $data['CourseLocation'];
$class->ID = $data['ID'];
$class->ClassListingPageID = $this->ID;
$form->saveInto($class);
$class->write();
$session->clear("FormData.{$form->getName()}.data");
$form->sessionMessage('Your class listing has been posted!','good');
$session = $this->getRequest()->getSession();
return $this->redirect($this->Link());
}
public function ClassEditForm() {
$ClassListingPageID = (int)$this->urlParams['ID'];
$data = ($ClassListingPageID)? $data = ClassListings::get()->byID($ClassListingPageID) : false;
$var = $this->getRequest()->getVar('$data');
if($var){
$form = Form::create(
$this,
__FUNCTION__,
FieldList::create(
TextField::create('CourseTitle', 'Course title:')
->setAttribute('placeholder', 'NZSL Level 1, NZSL 1A')
->setCustomValidationMessage('Please enter the course title field')
->addExtraClass('requiredField CourseTitle'),
TextField::create('CourseLocation','Region:')
->setAttribute('placeholder', 'Enter region')
->setCustomValidationMessage('Please enter the region field')
->addExtraClass('requiredField'),
HiddenField::create('ID', 'ID')->setValue($ClassListingPageID)
),
FieldList::create(
FormAction::create('doClassListing')
->setTitle('Post your class listing')
->addExtraClass('btn btn-primary primary')
),
RequiredFields::create(
'CourseTitle',
'CourseLocation',
)
);
$form->loadDataFrom(ClassListings::get()->filter(['ClassListingPageID' => $var])[0]);
$form->getSecurityToken()->getValue();
if ($form->hasExtension('FormSpamProtectionExtension')) {
$form->enableSpamProtection();
}
$data = $this->getRequest()->getSession()->get("FormData.{$form->getName()}.data");
return $data ? $form->loadDataFrom($data) : $form;
}
return;
}
public function doUpdateClassListing($data, Form $form) {
$session = $this->getRequest()->getSession();
$session->set("FormData.{$form->getName()}.data", $data);
$class = ClassListings::create($this->owner);
$class->CourseTitle = $data['CourseTitle'];
$class->CourseLocation = $data['CourseLocation'];
$class->ID = $data['ID'];
$class->ClassListingPageID = $this->ID;
$form->saveInto($class);
$class->write();
$session->clear("FormData.{$form->getName()}.data");
$form->sessionMessage('Your class listing has been updated!','good');
$session = $this->getRequest()->getSession();
return $this->redirect($this->Link());
}
}
Thought i post this answer to share in case if others have the same issue i had.
Finally got it working and solved the issue now, have replaced whole the codes for both ClassEditForm and doUpdateClassListing methods, and also created another funcation called Edit:
public function Edit(HTTPRequest $request) {
$id = (int)$request->param('ID');
$class = ClassListings::get()->byID($id);
if (!$class || !$class->exists()) {
return ErrorPage::response_for(404);
}
$form = $this->ClassEditForm($class);
$return = $this->customise(array(
'Title' => 'Edit: ' . $class->CourseTitle,
'Form' => $form,
));
return $return = $return->renderWith(array('ClassListingPage_edit', 'Page'));
}
public function ClassEditForm() {
$id = (int)$this->urlParams['ID'];
$class = ClassListings::get()->byID($id);
$fields = new FieldList(
HiddenField::create('ID')->setValue($id),
TextField::create('CourseTitle', 'Course title:')
->setAttribute('placeholder', 'NZSL Level 1, NZSL 1A')
->setCustomValidationMessage('Please enter the course title field')
->addExtraClass('requiredField CourseTitle'),
TextField::create('CourseLocation','Region:')
->setAttribute('placeholder', 'Enter region')
->setCustomValidationMessage('Please enter the region field')
->addExtraClass('requiredField')
);
$actions = new FieldList(
FormAction::create('doUpdateClassListing')
->setTitle('Update your class listing')
->addExtraClass('btn btn-primary primary')
);
$validator = new RequiredFields([
'CourseTitle',
'CourseLocation'
]);
$form = Form::create($this, 'ClassEditForm', $fields, $actions, $validator);
if ($class) $form->loadDataFrom($class);
return $form;
}
public function doUpdateClassListing($data, Form $form) {
if($data['ID']){
$id = $data['ID'];
$class = ClassListings::get()->byID($id);
} else {
$class = ClassListings::create();
}
$form->saveInto($class);
$id = $class->write();
$form->sessionMessage('Your class listing has been updated!','good');
$this->redirect($this->Link() . "edit/".$id);
}

SilverStripe 3.6.2 - Sorting Paginated Data Objects by Dropdown selection triggers 404 error

A couple years ago, I setup a paginated list of News Article Pages that were sorted by year based on a dropdown field selection: SilverStripe - Create pagination based on dropdown selection
I'm now trying to do the same thing but this time, the News Articles are data objects. Otherwise, everything else is the same.
The problem is I cannot get it to work this time and I'm not sure why. I'm following the same steps but when I select a year from the dropdown, I am taken to a 404 page on my site, and, in the Network tab in Chrome, there is a 404 status for the url:
I can see that the year value is not getting passed to the page's code for processing, but I'm not sure why as it did work -- and still works -- on the other SilverStripe site I was working on from the old post I linked to.
Here is the code that I have right now:
;(function($) {
$(function(){
// hide form actions, as we want to trigger form submittal
var newsYearFilterForm = $("#Form_YearFilterForm");
// automatically when dropdown changes
newsYearFilterForm.find(".Actions").hide();
// bind a change event on the dropdown to automatically submit
newsYearFilterForm.on("change", 'select[name="Year"]', function(e){
newsYearFilterForm.submit();
});
// handle pagination clicks
$("body").on("click", "a.pagination", function (e) {
e.preventDefault();
// $("#ArticleList").addClass("loading");
$.get(
$(this).attr("href"),
function(data, status, xhr){
$("#ArticleList").replaceWith($(data));
}
);
return false;
});
});
})(jQuery);
NewsLandingPage.php
<?php
class NewsLandingPage extends Page
{
private static $description = 'News Landing page.';
private static $db = array();
private static $has_one = array();
}
class NewsLandingPage_Controller extends Page_Controller
{
private static $allowed_actions = array(
'renderNewsItem',
'YearFilterForm',
'year',
);
public function init()
{
parent::init();
}
private static $url_handlers = array(
'$NewsItem!' => 'renderNewsItem',
);
public function getAllNews()
{
$newsList = NewsItem::get()->sort('NewsDate', 'DESC');
return new PaginatedList($newsList, $this->getRequest());
}
public function renderNewsItem(SS_HTTPRequest $request)
{
$newsItemName = $request->param('NewsItem');
if ($newsItemName != "") {
$newsItem = NewsItem::get()->filterAny(array(
'NewsItemSlug' => $newsItemName
))->first();
if ($newsItem) {
$arrayData = array(
'NewsItem' => $newsItem,
);
return $this->renderWith(array('NewsArticle', 'Page'), new ArrayData($arrayData));
} else {
return $this->httpError(404);
}
}
}
public function handleYearRequest(SS_HTTPRequest $request)
{
$year = $request->param('ID');
$data = array(
'Year' => $year,
'PaginatedReleases' => $this->PaginatedReleases($year)
);
if ($request->isAjax()) {
// in case of an ajax request, render only the partial template
return $this->renderWith('ArticleList', $data);
} else {
// returning an array will cause the page to render normally
return $data;
}
}
//creates a form to filter through news releases by year
public function YearFilterForm()
{
// get an array of all distinct years
$list = SQLSelect::create()
->addFrom('NewsItem')
->selectField('YEAR("NewsDate")', 'Year')
->setOrderBy('Year', 'DESC')
->execute()->column('Year');
// create an associative array with years as keys & values
$values = array_combine($list, $list);
// our fields just contain the dropdown, which uses the year values
$fields = FieldList::create(array(
DropdownField::create(
'Year',
'',
$values,
$this->getRequest()->param('ID')
)->setHasEmptyDefault(true)
->setEmptyString('Show all')
->setAttribute('data-urlpattern', $this->Link('year') . '/YYYY')
));
$actions = new FieldList(
FormAction::create('doFilter', 'Submit')
);
return Form::create($this, 'YearFilterForm', $fields, $actions);
}
public function year()
{
return $this->handleYearRequest($this->request);
}
public function index()
{
return $this->handleYearRequest($this->request);
}
//redirects to the proper url depending on which year is selected for sorting news
public function doFilter($data, $form)
{
if (empty($data['Year'])) {
return $this->redirect($this->Link());
} else {
return $this->redirect($this->Link('year/' . $data['Year']));
}
}
//created a paginated list of news released by year
public function PaginatedReleases($year = null)
{
$list = NewsItem::get()->sort('NewsDate', 'DESC');
if ($year) {
$list = $list->where(array('YEAR("NewsDate") = ?' => $year));
}
return PaginatedList::create($list, $this->getRequest())->setLimitItems(10);
}
}
NewsItem.php
class NewsItem extends DataObject{
private static $db = array(
'NewsName' => 'Varchar(255)',
'NewsItemSlug' => 'Varchar(250)',
'NewsDate' => 'SS_Datetime',
'NewsLocation' => 'Varchar(255)',
'NewsArticle' => 'HTMLText',
'NewsArticleSummary' => 'HTMLText',
'SortOrder' => 'Int',
);
private static $summary_fields = array(
'NewsName',
'NewsDate',
'NewsItemSlug',
);
private static $has_one = array(
'NewsImage' => 'Image',
'NewsUrlForHomePage' => 'SiteTree',
'Page' => 'Page'
);
public function onBeforeWrite() {
parent::onBeforeWrite();
if ($this->NewsItemSlug == ""){
$linkName = $this::getLinkName();
if ($linkName == ""){
$linkName = str_replace(array(" ",":","%","$","#","#","!","^","&","*","(",")","'",";","<",">","/","?","[","]","{","}","\\","|","`","~","=","+","’",",","."),"-",strtolower(str_replace("&","and",str_replace(".","",$this->NewsName))));
}
$this->NewsItemSlug = $linkName;
} else {
$this->NewsItemSlug = str_replace(array(" ",":","%","$","#","#","!","^","&","*","(",")","'",";","<",">","/","?","[","]","{","}","\\","|","`","~","=","+","’",",","."),"-",strtolower(str_replace("&","and",str_replace(".","",$this->NewsItemSlug))));
}
}
public function getLinkName() {
if ($this->NewsItemSlug != "" && !is_null($this->NewsItemSlug)){
return $this->NewsItemSlug;
}
return str_replace(" ","-",strtolower(str_replace("&","and",$this->NewsName)));
}
public function LinkingMode() {
return Controller::curr()->getRequest()->param('ID') == $this::getLinkName() ? 'current' : 'link';
}
public function Link() {
$newsLandingPage = NewsLandingPage::get()->first();
$linkName = $this::getLinkName();
if ($linkName){
return $newsLandingPage->Link($linkName);
} else {
return false;
}
}
public function canView($member = null){
return true;
}
public function canEdit($member = null) {
return true;
}
public function canCreate($member = null) {
return true;
}
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->removeFieldFromTab("Root.Main","PageID");
return $fields;
}
}
class NewsItemAdmin extends ModelAdmin {
private static $managed_models = array(
'NewsItem',
);
private static $url_segment = 'NewsItems';
private static $menu_title = 'News';
}
NewsLandingPage.ss
<% include BreadCrumbs %>
<div class="container container-intro-copy" style="background-color:#fff;opacity:1.0;">
<h1 class="intro-copy h1">$H1</h1>
<div class="intro-copy">$Content</div>
$YearFilterForm
<% include NewsList %>
</div>
NewsList.ss
<div id="ArticleList" class="container careers-list">
<div class="row">
<% loop $PaginatedReleases %>
<div class="career-item col-lg-10 col-lg-offset-1 col-md-10 col-md-offset-1 col-sm-10 col-sm-offset-1 col-xs-12 item bio-detail aos-init aos-animate" data-aos="fade-up" data-aos-delay="200" style="margin-top:30px;">
<div class="box-for-resources top-box-style">
<div class="box-resources-left"><img src="$NewsImage.URL" class="image-resources-cmmm"></div>
<div class="box-resources-right">
<h3 class="name left" style="color:#002f65 !important; float: left; clear: both;">$NewsName</h3>
<p class="box-resource-copy text-date"><em>$NewsDate.FormatI18N('%B %d, %Y') ($NewsLocation)</em></p><br />
<div class="careers-copy">$NewsArticleSummary</div><br />
Read Article
</div>
</div>
</div>
<% end_loop %>
</div>
</div>
The news page successfully loads all the articles by default and the links to each article work properly. The dropdown form has the correct list of years based on the range the articles have.
I think you have a conflict with your url_handlers and the actions you're calling on the controller.
'$NewsItem!' => 'renderNewsItem',
The above line matches all actions to renderNewsItem. Eg. yoursite.test/controller/YearFilterForm will also be matched by this…
You should add some static part to your handler that displays a news item. So your url_handlers would be:
'show/$NewsItem!' => 'renderNewsItem',
Then you'd have to adjust your NewsItem->Link method accordingly.
I also suggest you use the URLSegmentFilter to create your slugs… eg.
public function onBeforeWrite() {
parent::onBeforeWrite();
// only rebuild the slug when news-name has changed
if ($this->isChanged('NewsName', DataObject::CHANGE_VALUE)) {
$filter = URLSegmentFilter::create();
$t = $filter->filter($this->NewsName);
// Fallback to generic name if path is empty (= no valid, convertable characters)
if (!$t || $t == '-' || $t == '-1') {
$t = "news-{$this->ID}";
}
$this->NewsItemSlug = $t;
}
}

Prestashop tab creation, specific page for each tabs

Somehow, I have to create admin pages of my module. And this is how I am creating tabs
private function createTab()
{
$data = array(
'id_tab' => '',
'id_parent' => 0,
'class_name' => 'AdminSomeMenu',
'module' => $this->name,
'position' => 1, 'active' => 1
);
$res = Db::getInstance()->insert('tab', $data);
$id_tab = Db::getInstance()->Insert_ID();
$lang = (int)Configuration::get('PS_LANG_DEFAULT');
//Define tab multi language data
$data_lang = array(
'id_tab' => $id_tab,
'id_lang' => $lang,
'name' => $this->name
);
// Now insert the tab lang data
$res &= Db::getInstance()->insert('tab_lang', $data_lang);
$arrayTabs = array('TAB1','TAB2','TAB3');
foreach ($arrayTabs as $requiredTabs)
{
$tab = new Tab();
// Need a foreach for the language
$tab->name[$lang] = $this->l($requiredTabs);
$tab->class_name = 'Admin'.$requiredTabs;
$tab->id_parent = $id_tab;
$tab->module = $this->name;
$tab->add();
}
return true;
}
I hope I am going fine.
Once the tabs are created am trying linking with the following code.
<?php
class AdminMenuController extends ModuleAdminController
{
public function __construct()
{
$module = "mymodulename"
Tools::redirectAdmin('index.php?controller=AdminModules&configure='.$module.'&token='.Tools::getAdminTokenLite('AdminModules'));
}
}
This way the controller not found was gone. But I can create only the configure page through such link.
How should I go to achieve personalized page for each tabs.
Ah ! That was a missing parent::__construct(); in controllers causing the problem for not letting tabs behave the way they should.
<?php
class AdminTAB1Controller extends ModuleAdminController
{
public function __construct()
{
parent::__construct();
/* Tools::redirectAdmin('index.php?controller=AdminModules&configure='.$module.'&token='.Tools::getAdminTokenLite('AdminModules')); */
echo "Support page";
/* or further function can be called to load tpl files from views/templates/admin/ */
}
}
Now I have different pages for my tabs in both PS 1.6 and 1.7 !

Why is my custom SS3.1 report returning an error "[Notice] Object of class GridState_Data could not be converted to int"

As an exercise to help me learn about writing custom reports, I've written a very simple custom report to list pages by their page type. I wrote the code based on the standard report cms/code/reports/BrokenLinksReport.php (included as part of the CMS) but am getting an error:
[Notice] Object of class GridState_Data could not be converted to int
I dumped the contents of $data to ensure it was as expected, and it was. What might be causing the problem?
My code is as follows:
class PageListByType extends SS_Report {
function title() {
return "Page List by Type";
}
function description() {
return "List all the pages in the site, along with their page type";
}
public function sourceRecords($params = array(), $sort = null, $limit = null) {
$data = Page::get()->sort($sort);
$returnSet = new ArrayList();
if ($data) foreach ($data as $record) {
$returnSet->push($record);
}
return $returnSet;
}
public function columns() {
return array(
array(
'title'=>_t('PageListByTypeReport.PageName', 'Page name')
),
array(
'className'=>_t('PageListByTypeReport.ClassName', 'Page type')
)
);
}
}
There error is the two dimensional array in the columns function is not being set correctly. The variable name is missing and in the incorrect place for each column.
Either you can set the columns like this:
public function columns() {
return array(
'Title' => array(
'title'=>_t('PageListByTypeReport.PageName', 'Page name')
),
'ClassName' => array(
'title'=>_t('PageListByTypeReport.ClassName', 'Page type')
)
);
}
Or even simpler like this:
public function columns() {
return array(
'Title' => _t('PageListByTypeReport.PageName', 'Page name'),
'ClassName' => _t('PageListByTypeReport.ClassName', 'Page type')
);
}
The current sourceRecords function will work, although we can make this much simpler by just returning the results of Page::get() like this:
public function sourceRecords($params = array(), $sort = null, $limit = null) {
$pages = Page::get()->sort($sort);
return $pages;
}
Here is a working and simplified version of the Report code:
class PageListByType extends SS_Report {
function title() {
return 'Page List by Type';
}
function description() {
return 'List all the pages in the site, along with their page type';
}
public function sourceRecords($params = array(), $sort = null, $limit = null) {
$pages = Page::get()->sort($sort);
return $pages;
}
public function columns() {
return array(
'Title' => _t('PageListByTypeReport.PageName', 'Page name'),
'ClassName' => _t('PageListByTypeReport.ClassName', 'Page type')
);
}
}

Magento Save And Next

For my company I'm working on a custom translation module for Magento.
On the form for translating an existing string, I would like to change the behaviour of the "Save And Continue"-button to a "Save And Next"-button.
With which I mean that instead of still editing thesame string, you get the next one in line.
I have tried to edit the link that is called for the Save And Continue:
Original:
[save-link] + "/back/edit/"
To:
[save-link] + "/back/edit/id/[id]/"
But to no avail. I'm hoping someone can set me in the right direction.
The unchanged code of the edit-form:
<?php
class Phpro_Advancedtranslate_Block_Adminhtml_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
{
public function __construct()
{
parent::__construct();
$this->_objectId = 'id';
$this->_blockGroup = 'advancedtranslate';
$this->_controller = 'adminhtml';
$this->_updateButton('save', 'label', Mage::helper('advancedtranslate')->__('Save Item'));
$this->_updateButton('delete', 'label', Mage::helper('advancedtranslate')->__('Delete Item'));
$this->_addButton('saveandcontinue', array(
'label' => Mage::helper('adminhtml')->__('Save And Next'),
'onclick' => 'saveAndContinueEdit()',
'class' => 'save',
), -100);
$currentId = Mage::getSIngleton('adminhtml/session')->getTranslateId();
$strings = Mage::getModel("advancedtranslate/advancedtranslate")->getCollection();
foreach ($strings as $string) {
$id = $string->getId();
if ($id != $currentId && $id < $nextId) {
$nextId = $id;
}
}
$this->_formScripts[] = "
function toggleEditor() {
if (tinyMCE.getInstanceById('advancedtranslate_content') == null) {
tinyMCE.execCommand('mceAddControl', false, 'advancedtranslate_content');
} else {
tinyMCE.execCommand('mceRemoveControl', false, 'advancedtranslate_content');
}
}
function saveAndContinueEdit(){
editForm.submit($('edit_form').action+'back/edit/');
}
";
}
public function getHeaderText()
{
return Mage::helper('advancedtranslate')->__("Edit Item '%s'", 'test');
}
}
This functionality has to happen in the controller that handles the Post. Set the _redirect to redirect to the next item.

Categories