I want to do an auto complete using name on a text box. however the name is split into to columns, first_name, last_name. i have the following code.
view
$this->widget('zii.widgets.jui.CJuiAutoComplete',array(
'attribute'=>'CONSULTANT',
'model'=>$invoices,
'sourceUrl'=>array('SugarContacts/InvoicesNameList'),
// additional javascript options for the autocomplete plugin
'options'=>array(
'minLength'=>'2',
'select'=>"js:function(event, ui) { $('#Invoices_CONSULTANT').val(ui.item.id); getAddress(ui.item.id,'billing');} "
),
'htmlOptions'=>array(
'style'=>'height:20px;',
'id'=>"Invoices_CONSULTANT_search",
"size"=>"50",
'name'=>"Invoices[CONSULTANT]",
),
));
ccontroller
public function actions()
{
return array(
'ProjectsNameList'=>array(
'class'=>'application.extensions.EAutoCompleteAction',
'model'=>'Projects', //My model's class name
'attribute'=>'PROJECT', //The attribute of the model i will search
),
'ProjectsAreaList'=>array(
'class'=>'application.extensions.EAutoCompleteAction',
'model'=>'Projects', //My model's class name
'attribute'=>'AREA', //The attribute of the model i will search
),
'BidsContactList'=>array(
'class'=>'application.extensions.EAutoCompleteAction',
'model'=>'SugarContacts', //My model's class name
'attribute'=>'first_name', //The attribute of the model i will search
),
'BidNoList'=>array(
'class'=>'application.extensions.EAutoCompleteAction',
'model'=>'Bids', //My model's class name
'attribute'=>'BIDNO', //The attribute of the model i will search
),
'BidsClientRefList'=>array(
'class'=>'application.extensions.EAutoCompleteAction',
'model'=>'Bids', //My model's class name
'attribute'=>'CLIENTREF', //The attribute of the model i will search
),
'BidsAreaList'=>array(
'class'=>'application.extensions.EAutoCompleteAction',
'model'=>'Bids', //My model's class name
'attribute'=>'AREA', //The attribute of the model i will search
),
'OrdersconsultantsNameList'=>array(
'class'=>'application.extensions.EAutoCompleteAction',
'model'=>'SugarContacts', //My model's class name
'attribute'=>'first_name', //The attribute of the model i will search
),
'InvoicesNameList'=>array(
'class'=>'application.extensions.EAutoCompleteAction',
'model'=>'SugarContacts', //My model's class name
'attribute'=>'name', //The attribute of the model i will search
),
);
}
model
public function getName(){
return $this->first_name . " " . $this->last_name;
}
I had to modify eautocomplete action class
public function run()
{
if(isset($this->model) && isset($this->attribute)) {
$criteria = new CDbCriteria();
$criteria->compare($this->attribute, $_GET['term'], true);
if ($this->model == "SugarContacts") {
if($this->attribute == "name"){ //used on invoices
$criteria->select = "*, CONCAT(t.first_name, ' ', t.last_name) AS name";
$criteria->condition = "(CONCAT(t.first_name, ' ' , t.last_name) LIKE :ycp0 || accounts.name LIKE :ycp0) and length(t.id)<8"; //use id length to grab nav contacts
$criteria->join = " join sugarcrm6.accounts_contacts on t.id = sugarcrm6.accounts_contacts.contact_id" .
" join sugarcrm6.accounts on sugarcrm6.accounts_contacts.account_id = sugarcrm6.accounts.id"; // join tables to include company name in search
}
else
$criteria->addSearchCondition('last_name', $_GET['term'], true,"OR");
}
$model = new $this->model;
// print_r($model);
// print_r($criteria);
//exit();
foreach($model->findAll($criteria) as $m)
{
if ($this->model == "SugarContacts") {
if($this->attribute == "name"){ //used on invoices
$this->results[] = array(
//'label'=>trim($m->{$this->attribute}),
'value'=>trim($m->{$this->attribute}) . " " . " : " . trim($m->sugarAccountsContacts1->sugarAccounts->billing_address_street),
'id'=>$m->primaryKey
);
}else{
$this->results[] = array(
//'label'=>trim($m->{$this->attribute}),
'value'=>trim($m->{$this->attribute}) . " " . trim($m->last_name) . " : " . trim($m->primary_address_street),
'id'=>$m->primaryKey
);
}
}else{
$this->results[] = array(
'value'=>trim($m->{$this->attribute}),
'id'=>$m->primaryKey
);
}
}
}
if ($this->model != "SugarContacts" && !is_a($model,"Bids")) {
$this->results = array_unique($this->results);
}
echo CJSON::encode($this->results);
}
Related
I am developing an application using Laravel, Eloquent as ORM, phpunit for unit testing. But i am not able to update data in database. Though there is no exception, warning or error. If the object of the model class checked in laravel, before update and after update, it is showing that data has been changed in the model class but when checking the database, found that data is not being changed.
Model Class
class Post extends Model
{
protected $table = "posts";
protected $fillable = [
'id',
'user_id',
'title',
'description',
'total_needed',
'total_collected',
'total_expanse',
'start_date',
'end_date',
'active',
'updated_at',
'created_at',
];
}//class
Repository Code
class Post_Repo_Impl implements Post_Repo_I
{
public function update(Post $postUpdate)
{
$raedOld = false;
$updateStatus = false;
try {
$psot_id = $postUpdate->id;
$postOrgin = Post::find($psot_id);
$raedOld = true;
} catch (Exception $e) {
error_log("Post Update : failed to read existig post.");
}
if ($raedOld) {
try {
//line 1
echo "\n" . $postOrgin->title . "\n";
$this->setPostValues($postOrgin, $postUpdate)->update();
//line 2
echo "\n" . $postOrgin->title . "\n";
$updateStatus = true;
} catch (Exception $e) {
error_log("Post Update : Failed to save updated post." . "\n\n" . $e);
}
}
return $updateStatus;
} //update
}
Line 1 and Line 2, not printing same value. Line 2 printing the changed value.
Unit Test code
class RepoPost extends TestCase
{
public function testMain()
{
echo "\n >----------- Test Main : ---------> \n";
$this->postUpdate();
} //mother test
public function postUpdate()
{
$postDummyUpdate = new Post();
$postDummyUpdate->id = '2';
$postDummyUpdate->user_id = 'Tst';
$postDummyUpdate->title = 'Post Updated Repo Test........';
$postDummyUpdate->description = 'UnitTesting of URLs';
$postDummyUpdate->total_needed = '2000';
$postDummyUpdate->total_collected = '1000';
$postDummyUpdate->total_expanse = '500';
$postDummyUpdate->start_date = '22-09-2019';
$postDummyUpdate->end_date = '22-10-2019';
$postDummyUpdate->active = '1';
$postDummyUpdate->updated_at = '2019-09-24';
$postDummyUpdate->created_at = '2019-09-22';
echo '\n----PostUpdate----\n';
$postRepoSave = $this->getRepoPostImpl();
dd($postRepoSave->update($postDummyUpdate));
if ($postRepoSave == false) {
error_log("\n\nTest : Data Save Failed.");
} else {
error_log("Saved Post ID : " . $postRepoSave);
}
}
public function getRepoPostImpl()
{
return new Post_Repo_Impl();
}
}
In the test code it is returning true.
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);
}
I have a form that will perform a search action with a drop down list of choices of category to search. The drop down list are subjects to search by. So:
Search by:
1) Invoice #
2) Tracking #
3) BL #
Then enter in the value and submit to search.
I have my form:
// src Bundle\Form\Type\SearchType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('kind', 'choice', array(
'choices' => array(
'invoice' => 'Invoice #',
'trackingno' => 'Tracking Number'
'blno' => 'BL #',
),
'label' => 'Search by: '
))
->add('value', 'text', array(
'label' => false
))
->add('Submit','submit');
}
With this function in the controller:
public function getForm() {
$form = $this->createForm(new SearchType(), array(
'action' => $this->generateUrl('search_view'),
'method' => 'POST'
) );
return $form;
}
With the action going to 'search_view' function:
/**
* #param Request $request
* #Route("/results/", name="search_view")
*/
public function searchAction(Request $request) {
$kind = $request->get('kind');
$value = $request->get('value');
$em = $this->getDoctrine()->getManager();
$findCfs = $em->getRepository("CFSBundle:Cfs")
->searchCfs($kind, $value);
return $this->render("CFSBundle:Search:index.html.twig", array(
'results' => $findCfs
));
}
My problem is I do not where to go to perform the database retrieval base on the category. This is what I have in the repository:
public function searchCfs($kind, $value) {
$query = $this->getEntityManager()
->createQuery('
SELECT
c.blno, m.ctrno, c.carrier, m.refno
FROM
CFSBundle:Cfs c
LEFT JOIN
cfs.refno m
WHERE
:kind LIKE :value
')->setParameter("kind", $kind)
->setParameter("value", $value);
try {
return $query->getResult();
} catch(\Doctrine\ORM\NoResultException $e) {
return null;
}
}
Of course this isn't working. I thought about creating different queries for each category and have the conditions submit according to its category, but I was wondering if there was one simple solution to this?
I'd advise using the QueryBuilder class when writing a query such as this, rather than writing DQL directly.
You could then do something like the following in your repository:
const KIND_INVOICE_NO = 'invoice';
const KIND_TRACKING_NO = 'tracking';
const KIND_BL_NO = 'blno';
public function searchCfs($kind, $value) {
$queryBuilder = $this->createQueryBuilder('c')
->select('c.blno, m.ctrno, c.carrier, m.refno')
->leftJoin('cfs.refno', 'm');
if ($kind === self::KIND_INVOICE_NO) {
$queryBuilder->where('c.invoiceno = :queryValue');
} elseif ($kind === self::KIND_TRACKING_NO) {
$queryBuilder->where('m.ctrno = :queryValue')
} elseif ($kind === self::KIND_BL_NO) {
$queryBuilder->where('c.blno = :queryValue')
}
$queryBuilder->setParameter('queryValue', $value);
$query = $queryBuilder->getQuery();
try {
return $query->getResult();
} catch(\Doctrine\ORM\NoResultException $e) {
return null;
}
}
I have two fields in the advanced search form(approved, reviewdate) for which I created the radiobuttons.
<div class="row">
<?php echo $form->labelEx($model,''); ?>
<?php
echo $form->radioButtonList($model,'ReviewedDate',
array('1' => 'Reviewed', '' => 'Not Reviewed'),
array(
'template'=>'{input}{label}',
'separator'=>'',
'labelOptions'=>array(
'style'=> '
padding-left:13px;
width: 60px;
float: left;
'),
'onclick' => 'this.form.submit()',
'style'=>'float:left;',
)
);
?>
<div style="clear: both;"></div>
<?php echo $form->error($model,'ReviewedDate'); ?>
</div>
<div class="row">
<?php echo $form->labelEx($model,''); ?>
<?php
echo $form->radioButtonList($model,'Approved',
array('0' => 'Rejected', '1' => 'Approved'),
array(
'template'=>'{input}{label}',
'separator'=>'',
'labelOptions'=>array(
'style'=> '
padding-left:13px;
width: 60px;
float: left;
'),
'style'=>'float:left;',
'onclick' => 'this.form.submit()',
'uncheck' => NULL,
)
);
?>
<div style="clear: both;"></div>
<?php echo $form->error($model,'Approved'); ?>
</div>
Below is the criteria I created for both the fields in model.
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->with=array('apartment');
$criteria->compare('t.Id',$this->Id);
$criteria->compare('ApartmentId',$this->ApartmentId);
$criteria->compare('Approved',$this->Approved);
$criteria->compare('CreatedDate',$this->CreatedDate,true);
$criteria->compare('EmailBody',$this->EmailBody,true);
$criteria->compare('MailSubject',$this->MailSubject,true);
$criteria->compare('MessageType',1);
$criteria->compare('Name',$this->Name,true);
// $criteria->compare('ReviewedDate',$this->ReviewedDate);
$criteria->compare('SmsText',$this->SmsText,true);
$criteria->compare('UpdatedDate',$this->UpdatedDate,true);
$criteria->compare('PostedByUserFlatId',$this->PostedByUserFlatId);
$criteria->compare('Comments',$this->Comments,true);
$criteria->compare('ModifiedBy',$this->ModifiedBy,true);
if(isset($this->ReviewedDate) )
{
$criteria->addCondition('ReviewedDate IS NOT NULL');
$criteria->addCondition('UpdatedDate > CreatedDate');
$criteria->compare('ReviewedDate','0000-00-00 00:00:00');
}
else
{
$criteria->addCondition('updateddate = createddate');
$criteria->addCondition('ReviewedDate IS NULL');
}
if ($this->Approved)
{
$criteria->addCondition("approved='" . $this->Approved . "'");
$criteria->condition = ' (updateddate > createddate) AND (revieweddate IS NOT NULL) and approved = 1 ';
}
else
{
$criteria->addCondition("approved='" . $this->Approved . "'");
$criteria->condition = ' (updateddate > createddate) AND (revieweddate IS NOT NULL) and approved = 0 ';
}
$criteria->compare('apartment.Name',$this->groupz_search, true);
$criteria->compare('apartment.SocietyCode',$this->groupz_code_search, true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
Now when I try click on the reviewed/not reviewed button, the query that should be executed when rejected is clicked gets executed.
SQL query to be executed - SELECT count(*) FROM `message_template` `t` LEFT OUTER JOIN `apartment` `apartment` ON (`t`.`ApartmentId`=`apartment`.`Id`) WHERE (((MessageType=1) AND (updateddate = createddate)) AND (ReviewedDate IS NULL);
SQL executed - SELECT * FROM `message_template` `t` LEFT OUTER JOIN `apartment` `apartment` ON (`t`.`ApartmentId`=`apartment`.`Id`) WHERE (((MessageType=1) AND (updateddate > createddate)) AND (ReviewedDate IS NULL) and (Approved=0));
Why is this happening and how can I debug.
Edit
*Controller*
<?php
class MessageTemplateController extends Controller
{
/**
* #var string the default layout for the views. Defaults to '//layouts/column2', meaning
* using two-column layout. See 'protected/views/layouts/column2.php'.
*/
public $layout='//layouts/column2';
/**
* #return array action filters
*/
public function filters()
{
return array(
'accessControl', // perform access control for CRUD operations
'postOnly + delete', // we only allow deletion via POST request
);
}
/**
* Specifies the access control rules.
* This method is used by the 'accessControl' filter.
* #return array access control rules
*/
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions'=>array('index','view'),
'users'=>array('*'),
),
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('create','update'),
'users'=>array('#'),
),
array('allow', // allow admin user to perform 'admin' and 'delete' actions
'actions'=>array('admin','delete'),
# 'users'=>array('admin'),
'users'=>array('#'),//vishnu
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}
/**
* Displays a particular model.
* #param integer $id the ID of the model to be displayed
*/
public function actionView($id)
{
// $model = MessageTemplate::model()->findByPk($id);
$model = $this->loadModel($id);
$this->render('view', array(
'model' => $model,
));
}
/**
* Creates a new model.
* If creation is successful, the browser will be redirected to the 'view' page.
*/
public function actionCreate()
{
$model=new MessageTemplate;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['MessageTemplate']))
{
$model->attributes=$_POST['MessageTemplate'];
if($model->save())
$this->redirect(array('view','id'=>$model->Id));
}
$this->render('create',array(
'model'=>$model,
)
);
}
/**
* Updates a particular model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id the ID of the model to be updated
*/
public function actionUpdate($id)
{
$model_mt=new Messagesintable;
$model_al=new AuditLogin;
$model=$this->loadModel($id);
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['MessageTemplate']) && isset($_POST['AuditLogin']))
{
$model->attributes=$_POST['MessageTemplate'];
list($name,$mobile,$email)=retrieve_persondetails($id);
if($model->save())
{
$model_al->attributes=$_POST['AuditLogin'];
if($model->Approved==1)
{
if($name!=NULL)
{
$model_mt->Address= address_xml($name, $mobile, $email);
$message=$model->SmsText;
$approved="-approved";
$model_mt->Message= message_xml($message,$approved);
$model_mt->MsgType=1;
$model_mt->Date=date('Y-m-d');
$model_mt->Time=date('H:i:s');
$model_mt->CustomData='0,0';
$model_mt->save();
}
$model_al->activity="Message Template Approved";
$model_al->moduleId=1003;
$model_al->content=$model->SmsText;
}
else
{
if($name!=NULL)
{
$model_mt->Address= address_xml($name, $mobile, $email);
$message=$model->SmsText;
$approved="-rejected";
$model_mt->Message= message_xml($message,$approved);
$model_mt->MsgType=1;
$model_mt->Date=date('Y-m-d');
$model_mt->Time=date('H:i:s');
$model_mt->CustomData='0,0';
$model_mt->save();
}
$model_al->activity="Message Template Rejected";
$model_al->moduleId=1003;
$model_al->content=$model->SmsText;
}
if ($model_al->save())
$this->redirect(array('admin','id'=>$model->Id));
}
}
$this->render('update',array(
'model'=>$model,
));
}
/**
* Deletes a particular model.
* If deletion is successful, the browser will be redirected to the 'admin' page.
* #param integer $id the ID of the model to be deleted
*/
public function actionDelete($id)
{
$this->loadModel($id)->delete();
// if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
if(!isset($_GET['ajax']))
$this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
}
/**
* Lists all models.
*/
public function actionIndex()
{
$dataProvider=new CActiveDataProvider('MessageTemplate');
$this->render('index',array(
'dataProvider'=>$dataProvider,
));
}
// Oh yeah the filter. I just copied your code.
/*
*/
/**
* Manages all models.
*/
public function actionAdmin()
{
$model=new MessageTemplate('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['MessageTemplate']))
$model->attributes=$_GET['MessageTemplate'];
$this->render('admin',array(
'model'=>$model,
));
}
/**
* Returns the data model based on the primary key given in the GET variable.
* If the data model is not found, an HTTP exception will be raised.
* #param integer $id the ID of the model to be loaded
* #return MessageTemplate the loaded model
* #throws CHttpException
*/
public function loadModel($id)
{
$model=MessageTemplate::model()->findByPk($id);
if($model===null)
throw new CHttpException(404,'The requested page does not exist.');
return $model;
}
/**
* Performs the AJAX validation.
* #param MessageTemplate $model the model to be validated
*/
protected function performAjaxValidation($model)
{
if(isset($_POST['ajax']) && $_POST['ajax']==='message-template-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
}
}
function retrieve_persondetails($id)
{
$hostname="localhost";
$username=Yii::app()->db->username;
$password=Yii::app()->db->password;
$database="apartment";
$connection = mysql_connect($hostname,$username,$password);
mysql_select_db($database);
$sql = "SELECT p.Name,p.Mobile,p.Email from person p,flat f,userflatmapping u,message_template m, society_profile s where m.id=$id and u.id=m.postedbyuserflatid and f.id=u.flatid and p.id=f.registeredpersonid and u.dontsendsmstome=0 and s.apartmentId=f.apartmentid and s.sms_enabled=1;";
$result = mysql_query($sql);
while ($row = mysql_fetch_array($result))
{
$name=$row['Name'];
$mobile=$row['Mobile'];
$email=$row['Email'];
}
if(isset($name))
return array($name,$mobile,$email);
mysql_close($connection);
}
function address_xml($name,$mobile,$email)
{
$address_xml = '<tolist><to><name>' . $name . '</name><contactpersonname>' . $name . '</contactpersonname><number>' . $mobile . '</number><email>' . $email . '</email><prefix></prefix><contactpersonprefix></contactpersonprefix></to></tolist><from><name>' . $name . '</name><number>' . $mobile . '</number></from>';
return $address_xml;
}
function message_xml($message,$approved)
{
$message_xml ='<shorttext>' . $message.''.$approved. '</shorttext>';
return $message_xml;
}
edit rules
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('ApartmentId, Approved, MessageType, PostedByUserFlatId', 'numerical', 'integerOnly'=>true),
array('Name, SmsText, Comments, ModifiedBy', 'length', 'max'=>255),
array('CreatedDate, EmailBody, MailSubject, ReviewedDate, UpdatedDate', 'safe'),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('Id, ApartmentId, Approved, CreatedDate, EmailBody, MailSubject, MessageType, Name, ReviewedDate, SmsText, UpdatedDate, PostedByUserFlatId, Comments, ModifiedBy,apartment.Name,apartment.SocietyCode,groupz_search,groupz_code_search', 'safe', 'on'=>'search'),
//array('ReviewedDate','default',
//'value'=>new CDbExpression('NOW()'),
//'setOnEmpty'=>false,'on'=>'update'),
);
}
You're using $criteria->condition = ''; after calling $criteria->addCondition();
With $criteria->condition = ''; you set a whole new condition for the CDbCriteria object, which means all your previous $criteria->addCondition(); are lost.
So change this, for example:
$criteria->addCondition("approved='" . $this->Approved . "'");
$criteria->condition = ' (updateddate > createddate) AND (revieweddate IS NOT NULL) and approved = 0 ';
To this:
$criteria->addCondition("approved='" . $this->Approved . "'");
$criteria->addCondition("(updateddate > createddate) AND (revieweddate IS NOT NULL)");
This code is almost right:
if ($this->Approved)
{
$criteria->addCondition("approved='" . $this->Approved . "'");
$criteria->condition = ' (updateddate > createddate) AND (revieweddate IS NOT NULL) and approved = 1 ';
}
else
{
$criteria->addCondition("approved='" . $this->Approved . "'");
$criteria->condition = ' (updateddate > createddate) AND (revieweddate IS NOT NULL) and approved = 0 ';
}
As "davey" says you must "clean up" your search function, and for example you might change you code like this:
if ($this->Approved)
{
//this line is unnecessary $criteria->addCondition("approved='" . $this->Approved . "'");
$criteria->addCondition(' (updateddate > createddate) AND (revieweddate IS NOT NULL) and approved = 1 ');
}
else
{
//this line is unnecessary $criteria->addCondition("approved='" . $this->Approved . "'");
$criteria->addCondition(' (updateddate > createddate) AND (revieweddate IS NOT NULL) and approved = 0 ');
//if you dont want approved = 0 then you must change above line with:
$criteria->addCondition(' (updateddate > createddate) AND (revieweddate IS NOT NULL) ');
}
To debug:
first are you sure your send the form params by GET?
<form action="/controller/action" method="get">
second for testing your values I would do something like this:
if(isset($this->Approved)){
if($this->Approved==0){
...
}elseif($this->Approved==1){
...
}else{
throw new CHttpExeption(404,'unknown approval');
}
}
so if nothing is submitted -> no criteria will be added
Hope this helps
Best regards
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.