I want to add some fields by default using Userforms plugin in Silverstripe 3.2
I think i found the function which adds fields when the 'Add Field' button is pressed in Gridfield, but i`m not sure and i don't know how to adda formfield type (Date input) by calling a simple function.
Here is the full function:
public function getFieldEditorGrid() {
Requirements::javascript(USERFORMS_DIR . '/javascript/FieldEditor.js');
$fields = $this->owner->Fields();
$this->createInitialFormStep(true);
$editableColumns = new GridFieldEditableColumns();
$fieldClasses = singleton('EditableFormField')->getEditableFieldClasses();
$editableColumns->setDisplayFields(array(
'ClassName' => function($record, $column, $grid) use ($fieldClasses) {
if($record instanceof EditableFormField) {
return $record->getInlineClassnameField($column, $fieldClasses);
}
},
'Title' => function($record, $column, $grid) {
if($record instanceof EditableFormField) {
return $record->getInlineTitleField($column);
}
}
));
$config = GridFieldConfig::create()
->addComponents(
$editableColumns,
new GridFieldButtonRow(),
GridFieldAddClassesButton::create('EditableTextField')
->setButtonName(_t('UserFormFieldEditorExtension.ADD_FIELD', 'Add Field'))
->setButtonClass('ss-ui-action-constructive'),
GridFieldAddClassesButton::create('EditableFormStep')
->setButtonName(_t('UserFormFieldEditorExtension.ADD_PAGE_BREAK', 'Add Page Break')),
GridFieldAddClassesButton::create(array('EditableFieldGroup', 'EditableFieldGroupEnd'))
->setButtonName(_t('UserFormFieldEditorExtension.ADD_FIELD_GROUP', 'Add Field Group')),
new GridFieldEditButton(),
new GridFieldDeleteAction(),
new GridFieldToolbarHeader(),
new GridFieldOrderableRows('Sort'),
new GridFieldDetailForm()
);
$fieldEditor = GridField::create(
'Fields',
_t('UserDefinedForm.FIELDS', 'Fields'),
$fields,
$config
)->addExtraClass('uf-field-editor');
return $fieldEditor;
}
We can call onAfterWrite to set default fields after the page is saved for the first time.
class CustomFormPage extends UserDefinedForm {
public function onAfterWrite() {
if (!$this->Fields() || !$this->Fields()->exists()) {
$nameField = new EditableTextField();
$nameField->Name = 'Name';
$nameField->Title = 'Name';
$nameField->ParentID = $this->ID;
$nameField->Required = true;
$nameField->CustomErrorMessage = 'Please enter your name.';
$nameField->write();
$dateField = new EditableDateField();
$dateField->Name = 'Date';
$dateField->Title = 'Date';
$dateField->ParentID = $this->ID;
$dateField->Required = true;
$dateField->CustomErrorMessage = 'Please enter this date.';
$dateField->write();
}
parent::onAfterWrite();
}
}
Related
public function insertclients(Request $request)
{
$client = new Clients();
$client->client_name = $request->input('client_name');
$client->client_society = $request->input('client_society');
$client->client_email = $request->input('client_email');
$client->client_address = $request->input('client_address');
$client->client_phone = $request->input('client_phone');
$client->client_fix = $request->input('client_fix');
if ($this->nameclient($request->input('client_name')) < 1) {
$client->save();
return response()->json($client);
} else {
return response()->json('error', 'Client name already exists'); }
// return redirect('clients')->with('flash_message', 'Client Addedd!');
}
public function nameclient(Request $request)
{
//check count of client name
$count = Clients::where('client_name', $request->input('client_name'))->get();
$clicount = $count->count();
return $clicount;
}
I have this method for add new client but i wanna check if the name don't repeat so i create other function who check the name of client and i call it in the ferst but doesn't work.
You are already sending the input with $this->nameclient($request->input('client_name')
so change your method to accept a string variable
public function nameclient($clientName)
{
return Clients::where('client_name', $clientName)->count();
}
Bonus:
Maybe this way it would be more readable
public function insertclients(Request $request)
{
if ($this->nameclient($request->input('client_name')) {
return response()->json('error', 'Client name already exists');
}
$client = new Clients();
$client->client_name = $request->input('client_name');
$client->client_society = $request->input('client_society');
$client->client_email = $request->input('client_email');
$client->client_address = $request->input('client_address');
$client->client_phone = $request->input('client_phone');
$client->client_fix = $request->input('client_fix');
$client->save();
return response()->json($client);
// return redirect('clients')->with('flash_message', 'Client Addedd!');
}
You can also use laravel Validation instead of using the method nameclient and add the other validation rules in it like required fields and such.
public function insertclients(Request $request)
{
$request->validate([
'client_name' => 'required|unique:clients|max:255',
]);
$client = new Clients();
$client->client_name = $request->input('client_name');
$client->client_society = $request->input('client_society');
$client->client_email = $request->input('client_email');
$client->client_address = $request->input('client_address');
$client->client_phone = $request->input('client_phone');
$client->client_fix = $request->input('client_fix');
$client->save();
return response()->json($client);
// return redirect('clients')->with('flash_message', 'Client Addedd!');
}
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);
}
In the below code the captcha is coming and after proving we are not robot nothing happened. I have added both public and private key too.
Also, the captcha tool is coming above the header in it if adding any hidden field an error occur.
<html>
<head>
<script src='https://www.g**le.com/recaptcha/api.js'></script>
</head>
<body>
<?php
class ContactPage extends Page
{
private static $db = array(
'TelCustomerSupport' => 'Varchar',
'TelProjectSupport' => 'Varchar',
'OfficeName' => 'Text',
'OfficeStreetAddress' => 'Text',
'OfficeAddressLocality' => 'Text',
'OfficePostalCode' => 'Varchar',
'OfficeMapLink' => 'Text',
'OfficeLatitude' => 'Text',
'OfficeLongitude' => 'Text',
);
public function getCMSFields()
{
$fields = parent::getCMSFields();
// Add extra fields
$fields->addFieldToTab("Root.Main", new TextField('TelCustomerSupport', 'Phone - Customer, Trade & Retail Support'), "Content");
$fields->addFieldToTab("Root.Main", new TextField('TelProjectSupport', 'Phone - Project Support'), "Content");
$fields->addFieldToTab("Root.Main", new TextField('OfficeName'), "Content");
$fields->addFieldToTab("Root.Main", new TextField('OfficeStreetAddress'), "Content");
$fields->addFieldToTab("Root.Main", new TextField('OfficeAddressLocality'), "Content");
$fields->addFieldToTab("Root.Main", new TextField('OfficePostalCode'), "Content");
$fields->addFieldToTab("Root.Main", new TextField('OfficeMapLink'), "Content");
$fields->addFieldToTab("Root.Main", new TextField('OfficeLatitude'), "Content");
$fields->addFieldToTab("Root.Main", new TextField('OfficeLongitude'), "Content");
return $fields;
}
}
class ContactPage_Controller extends NetSuitePage_Controller
{
private static $allowed_actions = array('ContactForm');
// Generate the form
public function ContactForm()
{
// Create fields
$fields = new FieldList(
TextField::create("FirstName")->setTitle(_t('Contact.FIRSTNAME')),
TextField::create("LastName")->setTitle(_t('Contact.LASTNAME')),
EmailField::create("Email")->setTitle(_t('Contact.EMAILADDRESS')),
TextField::create("Phone")->setTitle(_t('Contact.PHONENUMBER')),
DropdownField::create('Iam', _t('Contact.IAMA'), $this->translateNetsuiteConfigArray('Contact', 'Iam')),
TextField::create("SendSubject")->setTitle(_t('Contact.SUBJECT')),
HoneyPotField::create("Subject2")->setTitle('Subject2'),
TextareaField::create("Message")->setTitle(_t('Contact.MESSAGE'))->setColumns(30)->setRows(10)
);
// Create actions
$submitbutton = new FormAction('doContactForm', _t('Contact.SEND'));
$submitbutton->addExtraClass('btn btn-black');
$actions = new FieldList(
$submitbutton
);
$validator = ZenValidator::create();
$validator->addRequiredFields(array('FirstName', 'LastName', 'Email', 'Phone', 'Iam', 'SendSubject', 'Message'));
$validator->setConstraint('FirstName', Constraint_length::create('max', 32));
$validator->setConstraint('LastName', Constraint_length::create('max', 32));
$validator->setConstraint('Phone', Constraint_length::create('min', 7));
$validator->setConstraint('Email', Constraint_type::create('email'));
$validator->setConstraint('Phone', Constraint_type::create('digits'));
print"<div class=\"g-recaptcha\" data-sitekey=\"6LdCAxEUAAAAAHSWL1xulOjZLv-6PPHTSQJdjpEu\"></div>"
$form = new Form($this, 'ContactForm', $fields, $actions, $validator);
$form->addExtraClass('contact-form');
$form->setFormMethod('POST', true);
return $form;
}
// Deal with form submission
public function doContactForm($data, $form)
{
$submission = new ContactFormSubmission();
$form->saveInto($submission);
$submission->write();
$data['path'] = print_r($this->refererTracker->retrieveAll(), true);
$email = new Email();
$email->setTemplate('ContactFormEmail');
$email->populateTemplate($data);
$email->setTo($this->getNetsuiteConfig('Contact', 'Emails'));
$email->setFrom("no-reply#warmup.co.uk");
$email->setSubject('[warmup.co.uk] New contact from the website');
$email->populateTemplate($data);
$email->send();
$post = $this->getNetsuiteConfig('Contact');
$post->firstname = $data['FirstName'];
$post->lastname = $data['LastName'];
$post->email = $data['Email'];
$post->phone = $data['Phone'];
$post->custentity116 = $data['Iam'];
$post->custentitysubject_contact_us = $data['SendSubject'];
$post->custentitymessage_contact_us = $data['Message'];
if(isset($_POST['g-recaptcha-response'])&& $_POST['g-recaptcha-response']){
var_dump($_POST);
$secret = " 6LdCAxEUAAAAAIss47kbDqOWVaf3H2ruMkgddKTa";
$ip = $_SERVER['REMOTE_ADDR'];
$captcha = $_POST['g-recaptcha-response'];
$rsp = file_get_contents("https://www.***.com/recaptcha/api/siteverify?secret=$secret&response=$captcha&remoteip$ip");
var_dump($rsp);
$arr = json_decode($rsp,TRUE);
if($arr['success'])
{
// Check for success
if ($this->queueNetSuitePost($post)) {
return $this->redirect(Director::get_current_page()->Link()."?success=1");
}
}
else{
// Redirect back with form data and error message
Session::set('FormInfo.' . $form->FormName() . '.data', $data);
Session::set('FormInfo.'.$form->FormName().'.errors', array());
$form->sessionMessage("Netsuite error", 'bad');
return $this->redirectBack();
}
}
}
// Returns true if form submitted successfully
public function Success()
{
return isset($_REQUEST['success']) && $_REQUEST['success'] == "1";
}
public function getCurrentSubsite()
{
$subsite = Subsite::currentSubsite();
if($subsite) {
return $subsite->Title;
}
return $subsite;
}
}
"print" or "echo" will render immediately. The rest of your code/template won't render until later. If you want to insert html you are better off adding a LiteralField to your form.
What might be even better is using a module which provides recaptcha in an easy to use form field, e.g. https://github.com/Level51/silverstripe-recaptcha
is there a way to pass a URL variable to a form action? I've got it working on a user details form, but when I'm trying to do it with a user file upload it won't work.
As you will see below, I have a form and a save action for saving user details. That works fine.
When I try to pass the URL variable to the User File Upload form, it doesn't work. It says that I'm trying to get a value of a non-object.
// Get Client ID from URL Parameters
public function getUser() {
if( isset($this->urlParams['ID']) && is_numeric($this->urlParams['ID']) ) {
return $user = Member::get()->byID($this->urlParams['ID']);
} else {
return $user = $this->request->postVars();
}
}
// Edit/Save a User's details
public function EditUserDetails() {
//Include JS for updating details
Requirements::javascript('module-memberprofiles/javascript/MemberProfileUpdate.js');
Requirements::set_force_js_to_bottom(true);
$fields = new FieldList(
$leftCol = CompositeField::create(
TextField::create('FirstName', 'First Name')
->setFieldHolderTemplate('UserDetails_FieldHolder'),
TextField::create('Surname', 'Surname')
->setFieldHolderTemplate('UserDetails_FieldHolder'),
CompositeField::create(
TextField::create('Address', ''),
TextField::create('Suburb', ''),
CompositeField::create(
DropdownField::create('State', '', singleton('Member')->dbObject('State')->enumValues())->setFieldHolderTemplate('UserDetails_StatePostCode'),
TextField::create('PostCode', '')->setFieldHolderTemplate('UserDetails_StatePostCode')
)->addExtraClass('row')
)
->addExtraClass('userdetails-address wrap')
->setFieldHolderTemplate('UserDetails_AddressHolder'),
TextField::create('Phone', 'Phone')
->setFieldHolderTemplate('UserDetails_FieldHolder'),
TextField::create('Email', 'Email')
->setFieldHolderTemplate('UserDetails_FieldHolder')
)->setFieldHolderTemplate('UserDetails_CompositeField')
);
$actions = new FieldList(new FormAction('SaveUserDetails', 'Save Profile'));
$validation = new RequiredFields(array('FirstName','Surname','Email'));
$form = new Form ( $this, 'EditUserDetails', $fields, $actions, $validation);
$form->loadDataFrom($this->getUser());
$form->setTemplate('MemberProfilePage_UserDetailsForm');
return $form;
}
public function SaveUserDetails($data, $form) {
$table = Member::get()->byID($this->getUser());
$members = Member::get();
$emailExists = $members->filter(array(
'Email' => $data['Email'],
'ID:not' => $table->ID
));
if( $emailExists->count() > 0 ) {
$form->sessionMessage('Sorry, that email address already exists. Please try again','bad');
return $this->redirectBack();
} else {
$form->sessionMessage('You have successfully updated this user\'s details.','good');
}
$form->saveInto($table);
$table->write();
$this->redirectBack();
return $this;
}
//User file upload function
public function UploadUserFile() {
$fields = FieldList::create(
FileField::create('UserFiles', 'Upload files')
);
$actions = FieldList::create(FormAction::create('SaveUserFile', 'Upload files'));
$form = Form::create($this, __FUNCTION__, $fields, $actions, null);
$form->loadDataFrom($this->getUser());
return $form;
}
//Refresh files function
public function SaveUserFile($data, $form) {
$up = new Upload();
$file = Object::create('File');
$file->setFileName('newname');
$up->loadIntoFile($data['UserFiles'], $file, 'User-Files');
if($up->isError()) {
//handle error here
//var_dump($up->getErrors());
}else {
//file uploaded
//$file->OwnerID = 3;
//$file->write();
//$this->redirectBack();
return $this;
}
}
OK, I managed to figure this one out...
I had to set a form action to direct the upload function to the correct URL. It appears that the ID was being removed from the URL when I clicked submit, so the "getUser" function couldn't see the value.
Here's the working code for the Upload Form function:
public function UploadUserFile() {
$fields = FieldList::create(
FileField::create('UserFiles', 'Upload files'),
HiddenField::create('ID','',$this->getUser()->ID)
);
$actions = FieldList::create(
FormAction::create('SaveUserFile', 'Upload files')
->addExtraClass('button rounded solid')
);
$form = Form::create($this, 'UploadUserFile', $fields, $actions);
$form->setFormAction($this->Link().'UploadUserFile/'.$this->getUser()->ID);
return $form;
}
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.