User Friendly Date filter in Yii - yii-extensions

I have a weird problem that, i have a model and a attribute is create_time (timestamp). I have to show the timestamp as a userfriendly date (Y-M-D) format in view, but the problem is when i search for the date say using date only(23), or year only(2013), i am getting php warning instead its working when whole string is inputted.
I have done following so far:
//Controller Action:
$dataProvider = new MyModel('search');
$dataProvider -> unsetAttributes();// clear any default values
if (isset($_GET['MyModel'])) {
$dataProvider -> attributes = $_GET['MyModel'];
}
$this -> render('MyView', array('dataProvider' => $dataProvider, ));
//My View page
$this->widget('zii.widgets.grid.CGridView', array(
'id' =>'list-grid',
'dataProvider'=>$dataProvider->search(),
'filter' =>$dataProvider,
'columns'=>array(
array(
'first_name',
'last_name',
'consult_price',
'create_time'=>array('name'=>'create_time',
'header' =>'Profile Created In',
'value'=>'Components::userFriendlyDate($data->id);',// or before validate and afterFind on Model
'htmlOptions' =>array('style'=>'text-align: center'),
..................
// My Model
$criteria = new CDbCriteria;
if (!empty($this -> create_time)) {
// as i say this explodes a string with y-m-d format so i am getting an error.
list($day, $month, $year) = explode("/", $this -> create_time);
$daystart = mktime(0, 0, 0, (int)$month, (int)$day, (int)$year);
$dayend = mktime(23, 59, 59, (int)$month, (int)$day, (int)$year);
$criteria -> condition = ':s<=create_time AND create_time<=:e';
$criteria -> params = array(':s' => $daystart, ':e' => $dayend);
}
$criteria -> compare('create_time', $this -> convert($this -> create_time));
return new CActiveDataProvider($this, array('criteria' => $criteria, ));
//where convert function goes likes this:
public function convert($date) {
if ($date == NULL)
return $date;
//null shows all records
else {
list($day, $month, $year) = explode("/", $this -> create_time);
$daystart = mktime(0, 0, 0, (int)$month, (int)$day, (int)$year);
$dayend = mktime(23, 59, 59, (int)$month, (int)$day, (int)$year);
$sql = "SELECT create_time FROM MYTable WHERE create_time BETWEEN '$dayend' AND '$daystart'";
$result = Yii::app() -> db -> createCommand($sql) -> queryAll();
return $result;
}
}
Has anyone working with the timestamp field conversion on search ?? Help Needed !

The error is at list($day, $month, $year) = explode("/", $this -> create_time). This is because list($variables) expects an array with at least the same number of elements as variables to be assigned. You need to pad the date with the missing fields (day, month or year) before executing this line.
You can use a datepicker as your field to ensure that $create_time always has a day, month and year.
Alternatively:
add separate fields for the day, month and year
set them to the current day, month and year respectively if empty and
combine them to form $create_time.

Related

Trouble passing SQL data to view in codeigniter

I have a form that I am using to allow people to input data and then upload a preset picture. I want to label that picture as the form_id. I am able to run a LAST_INSERT_ID() query and display it after I insert the form in my view but I can't seem to echo that information out anywhere else. I need the query to select_last_id to run after my $update query or the ID number will be off. Could anyone assist in helping me pass just the value of the row to my view? Here is the code from my controller.
function inspection() {
if($this->input->post('submit')) {
$array = array(
'trlr_num' => $this->input->post('trlr_num'),
'seal' => $this->input->post('seal'),
'damaged' => $this->input->post('damaged'),
'truck_num' => $this->input->post('truck_num'),
'driver_name' => $this->input->post('driver_name'),
'car_code' => $this->input->post('car_code'),
'origin' => $this->input->post('origin'),
'lic_plate' => $this->input->post('lic_plate'),
'del_note' => $this->input->post('del_note'),
'live_drop' => $this->input->post('live_drop'),
'temp' => $this->input->post('temp'),
'level' => $this->input->post('level'),
'ship_num' => $this->input->post('ship_num'),
'trlr_stat' => $this->input->post('trlr_stat'),
'comment' => $this->input->post('comment')
);
$update = $this->trailer_model->insert_form($array);
$query = $this->trailer_model->select_last_id();
$result =& $query->result_array();
$this->table->set_heading('ID');
$data['table'] = $this->table->generate_table($result);
unset($query,$result);
}
$level = $this->trailer_model->select_fuel_level();
$result = $level->result_array();
$data['options'] = array();
foreach($result as $key => $row) {
$data['options'][$row['level']] = $row['level'];
}
unset($query,$result,$key,$row);
$data['label_display'] = 'Fuel Level';
$data['field_name'] = 'level';
$status = $this->trailer_model->select_trailer_type();
$result = $status->result_array();
$data['options1'] = array();
foreach($result as $key => $row) {
$data['options1'][$row['trlr_stat']] = $row['trlr_stat'];
}
unset($query,$result,$key,$row);
$data['label_display1'] = 'Trailer Status';
$data['field_name1'] = 'trlr_stat';
$data['page_title'] = 'Trailer Inspection';
$data['main_content'] = 'dlx/inspection/trailer_inspection_view';
return $this->load->view('includes/template',$data);
}
}
Anything you want to display on a view, you must pass to it.
When you're setting $data, you missed adding $query to it.
Controller:
I understand that $query = $this->trailer_model->select_last_id(); is returning just an ID, so:
$data['last_id'] = $query;
But if $query = $this->trailer_model->select_last_id(); does not return just an ID, but an array or something else, you shall include to return the ID in your model method. Actually, it'd be crucial to know what $this->trailer_model->select_last_id(); is returning.
View:
echo $last_id; -> must echo the last ID, if select_last_id() method from your model returns what it has to return.

Creating a PDF document from a filtered CGridView - Yii

I am trying to create a PDF from a filtered CGridView. The value will be passed via dropdown in Advanced search but the problem is that i am unable to filter the search by my pdf function.
Controller
public function actionPrint() {
$mPDF1 = Yii::app()->ePdf->mpdf('ar','A4','14','dejavusanscondensed');
$model=new Country('search');
$model->center_id = 1;// This value will be passed from dropdown
//and i want the report to be made on this
$model->unsetAttributes();
if(isset($_GET['Country']))
$model->attributes=$_GET['Country'];
$html = '';
$html .= $this->renderPartial('candidates', array('model'=>$model, 'enablePagination' => false),true);
$mPDF1->WriteHTML($html, false);
$mPDF1->Output('list.pdf','D');
}
View
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'country-grid',
'dataProvider'=>$model->search($enablePagination),
'summaryText' => '',
// 'enablePagination' => false,
'filter'=>$model,
'columns'=>array(
'name',
array(
'header'=>' Total Registered Candidates',
'value'=>'$data->itemsTotal',
),
),
));
echo CHtml::link(
'Save as PDF',
Yii::app()->createUrl('country/print'),
array('class'=>'btnPrint btn btn-danger','target'=>'_blank'));
Model
public function search($enablePagination = true)
{
$criteria->together= true;
$criteria->with=array('center');
$criteria->compare('center.name', $this->center_id, true);
..........
if ($enablePagination)
{
$pagination = array(
'pageSize' => 30,
);
}
else
{
$pagination = false;
}
return new CActiveDataProvider($model, array(
'criteria' => $criteria,
'pagination' => $pagination,
));
}
Since center_id is a foreign key the line
$criteria->compare('center.name', $this->center_id, true);
should read
$criteria->compare('center_id', $this->center_id);
You could also do the following but this adds a condition on the joined table and could lead to slower queries.
$criteria->compare('center.id', $this->center_id);

Yii Criteria: condition for relation

i have two tables: User and User_works (User HAS_MANY User_works).
How can I add a condition to be displayed only users with certain works
User contains fields: id | name | Other information
User_works: id | user_id | work_id
User Model:
public function relations()
{
return array(
'works'=>array(self::HAS_MANY, 'UserWorks',
'',
'on' => 'works.user_id=t.id',
'together'=>false,
),
)
}
Controller:
$criteria = new CDbCriteria();
$criteria->with = array('works');
$criteria->compare = ????
Solution:
I wanted something like that:
SQL "Select user.id from User, User_works Where User_works.user_id=User.id AND User_works.work_id=$SOMEVALUE"
User Model:
public function relations()
{
return array(
'works'=>array(self::HAS_MANY, 'UserWorks',
'',
'joinType' => 'INNER JOIN',
'on' => 'works.user_id=t.id',
'together'=>true,
),
)
}
Controller:
$criteria = new CDbCriteria();
$criteria->with = array('works'=>array('on' => 'works.user_id=t.id AND (works.work_id=$SOMEVALUE OR ...)'));
As a result, I get the users with the necessary works.
But а new problem arose. The number of pages in the Listview not correctly displays.
List view does not consider the condition of necessary works. As a result, a number of page is wrong.
Solution :
$dataProvider=new CActiveDataProvider('User', array(
'criteria'=>$criteria,
'pagination'=>array(
'pageSize'=>1,
),
));
$dataProvider->setTotalItemCount(count(User::Model()($criteria)));
or
Instead of setting the dataprovider criteria:
$dataProvider->criteria = $criteria
I set dataprovider->model criteria:
$dataProvider->model->setDbCriteria($criteria)
$criteria = new CDbCriteria();
$criteria->with = array('works');
$criteria->compare('works.theField_name' , $someThing);

Custom post type yearly/ monthly archive

I have a custom post type "news" in my Wordpress site. I am using Advanced Custom Fields plugin to add meta data to each post.
I want to create an array of news items as an archive:
[2013]
[January] => 5
[2012]
[January] => 20
[February] => 10
[2011]
[April] => 30
I managed to get this working using:
global $wpdb;
$news = $wpdb->get_results(
"SELECT wp_posts.post_date, COUNT(wp_posts.ID) as count
FROM $wpdb->posts
WHERE
wp_posts.post_type = 'news' AND
wp_posts.post_status = 'publish' AND
wp_posts.post_date <= CURDATE() AND
wp_posts.post_date >= DATE_SUB(CURDATE(), INTERVAL 3 YEAR)
GROUP BY YEAR(wp_posts.post_date), MONTH(wp_posts.post_date)
ORDER BY wp_posts.post_date DESC",
ARRAY_A);
$archive = array();
foreach ($news as $post):
$year = date('Y', strtotime($post['post_date']));
$month = date('m', strtotime($post['post_date']));
$month_name = date('F', strtotime($post['post_date']));
$post['url'] = 'NOT SURE ABOUT URL';
$archive[$year][$month_name] = $post;
endforeach;
I need to be able to link to specific years and months using http://example.com/2012/ and http://example.com/2012/10/.
As this involves a custom post type "news" I'm unsure how to make this happen?
In order to do what you require, you need to modify Wordpress rewrites to be able to capture the year/month/etc post data for a custom post type.
You may do this with the following code:
/**
* Custom post type date archives
*/
/**
* Custom post type specific rewrite rules
* #return wp_rewrite Rewrite rules handled by Wordpress
*/
function cpt_rewrite_rules($wp_rewrite) {
$rules = cpt_generate_date_archives('news', $wp_rewrite);
$wp_rewrite->rules = $rules + $wp_rewrite->rules;
return $wp_rewrite;
}
add_action('generate_rewrite_rules', 'cpt_rewrite_rules');
/**
* Generate date archive rewrite rules for a given custom post type
* #param string $cpt slug of the custom post type
* #return rules returns a set of rewrite rules for Wordpress to handle
*/
function cpt_generate_date_archives($cpt, $wp_rewrite) {
$rules = array();
$post_type = get_post_type_object($cpt);
$slug_archive = $post_type->has_archive;
if ($slug_archive === false) return $rules;
if ($slug_archive === true) {
$slug_archive = $post_type->name;
}
$dates = array(
array(
'rule' => "([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})",
'vars' => array('year', 'monthnum', 'day')),
array(
'rule' => "([0-9]{4})/([0-9]{1,2})",
'vars' => array('year', 'monthnum')),
array(
'rule' => "([0-9]{4})",
'vars' => array('year'))
);
foreach ($dates as $data) {
$query = 'index.php?post_type='.$cpt;
$rule = $slug_archive.'/'.$data['rule'];
$i = 1;
foreach ($data['vars'] as $var) {
$query.= '&'.$var.'='.$wp_rewrite->preg_index($i);
$i++;
}
$rules[$rule."/?$"] = $query;
$rules[$rule."/feed/(feed|rdf|rss|rss2|atom)/?$"] = $query."&feed=".$wp_rewrite->preg_index($i);
$rules[$rule."/(feed|rdf|rss|rss2|atom)/?$"] = $query."&feed=".$wp_rewrite->preg_index($i);
$rules[$rule."/page/([0-9]{1,})/?$"] = $query."&paged=".$wp_rewrite->preg_index($i);
}
return $rules;
}
You will notice that I have hard-coded news in to the $rules = cpt_generate_date_archives('news', $wp_rewrite); portion of the code. You can change this as needed.
With this code, you should be able to navigate to http://yoursite.com/news/2013/02/ and receive an archive listing for that specific post type for that specific time.
For completeness, I will include how to generate a monthly archive widget in order to utilize this.
/**
* Get a montlhy archive list for a custom post type
* #param string $cpt Slug of the custom post type
* #param boolean $echo Whether to echo the output
* #return array Return the output as an array to be parsed on the template level
*/
function get_cpt_archives( $cpt, $echo = false )
{
global $wpdb;
$sql = $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE post_type = %s AND post_status = 'publish' GROUP BY YEAR($wpdb->posts.post_date), MONTH($wpdb->posts.post_date) ORDER BY $wpdb->posts.post_date DESC", $cpt);
$results = $wpdb->get_results($sql);
if ( $results )
{
$archive = array();
foreach ($results as $r)
{
$year = date('Y', strtotime( $r->post_date ) );
$month = date('F', strtotime( $r->post_date ) );
$month_num = date('m', strtotime( $r->post_date ) );
$link = get_bloginfo('siteurl') . '/' . $cpt . '/' . $year . '/' . $month_num;
$this_archive = array( 'month' => $month, 'year' => $year, 'link' => $link );
array_push( $archive, $this_archive );
}
if( !$echo )
return $archive;
foreach( $archive as $a )
{
echo '<li>' . $a['month'] . ' ' . $a['year'] . '</li>';
}
}
return false;
}
To use this function just supply the slug of the custom post type, ie: get_cpt_archives( 'news' ). This will return an array of unique Year/Dates/Links, ie:
Array
(
[0] => Array
(
[month] => February
[year] => 2013
[link] => http://yoursite.com/news/2013/02
)
[1] => Array
(
[month] => January
[year] => 2013
[link] => http://yoursite.com/news/2013/01
)
)
You can loop through these with a foreach and output them however you want.
Alternatively, you can use get_cpt_archives( 'news', true ) which will automatically echo each item wrapped in an <li> linking to its specific archive.
The formatting of the output is not exactly what you wanted, so you will have to tweak it a bit to get it to display in the
Year
Month
Month
Year
Month
format that you require.
I hope this helps.
I know this is an old post, but there is a much more succinct way of doing what the OP is asking:
function cpt_add_rewrite_rules()
{
$cpt = 'news';
add_rewrite_rule($cpt.'/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})?$',
'index.php?post_type='.$cpt.'&year=$matches[1]&monthnum=$matches[2]&day=$matches[3]',
'top');
add_rewrite_rule($cpt.'/([0-9]{4})/([0-9]{1,2})?$',
'index.php?post_type='.$cpt.'&year=$matches[1]&monthnum=$matches[2]',
'top');
add_rewrite_rule($cpt.'/([0-9]{4})?$',
'index.php?post_type='.$cpt.'&year=$matches[1]',
'top');
}
add_filter('init', 'cpt_add_rewrite_rules');

Yii: searching for a date period

I've a table with 2 mysql DATE field 'validFrom' and 'validTo'.
I need to allow user to search for a period beetween validFrom and validTo (included)
search using
validFrom >= searched validFrom
and
validTo <= searched validTo
What must I change ? the search() ? .
The Gii created code tell me this (i think it's a 'LIKE %string%' search )
$criteria->compare('validFromDate',$this->validFromDate,true);
$criteria->compare('validToDate',$this->validToDate,true);
$criteria->addBetweenCondition('colName', $this->validFrom, $this->validTo);
public function search() {
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria = new CDbCriteria;
$criteria->with = array('user');
$criteria->compare('nota_id', $this->nota_id, true);
$criteria->compare('user.nume', $this->filter_nume, true);
$criteria->compare('persoana1', $this->persoana1, true);
$criteria->compare('persoana2', $this->persoana2, true);
$d = $this->getFilterDateRange($this->data_discutie);
if (!empty($d[0]) && !empty($d[1])) {
// between condition
$criteria->addBetweenCondition('data_discutie', $d[0], $d[1]);
} else if (!empty($d[0])) {
$criteria->compare('data_discutie', '>=' . $d[0]);
} else if (!empty($d[1])) {
$criteria->compare('data_discutie', '<=' . $d[1]);
}
$d = null;
//echo $this->urmatoarea_discutie;
$d = $this->getFilterDateRange($this->urmatoarea_discutie);
//print_R($d);
if (!empty($d[0]) && !empty($d[1])) {
// between condition
$criteria->addBetweenCondition('urmatoarea_discutie', $d[0], $d[1]);
} else if (!empty($d[0])) {
$criteria->compare('urmatoarea_discutie', '>=' . $d[0]);
} else if (!empty($d[1])) {
$criteria->compare('urmatoarea_discutie', '<=' . $d[1]);
}
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
'pagination' => array(
'pageSize' => '15',
),
'sort' => array(
'defaultOrder' => 'coalesce(nullif(t.urmatoarea_discutie, ""), \'zzzzzz\') ASC, t.data_discutie ASC',
'attributes' => array(
'urmatoarea_discutie',
'data_discutie',
'persoana2',
'persoana1',
'filter_nume' => array(
'asc' => 'user.nume asc',
'desc' => 'user.nume desc'
),
),
),
));
}
protected function getFilterDateRange($key) {
$ret = array(&$from, &$to);
switch ($key) {
case '-1':
// past
$to = strtotime('next hour');
break;
case '1':
// future
$from = strtotime('last hour');
break;
case '-7':
$from = strtotime('-1 week last monday midnight');
$to = strtotime('last sunday midnight');
break;
case '7':
$from = strtotime('last monday');
$to = strtotime('next sunday midnight');
break;
}
return $ret;
}
Depending on what you want to do, the search() in the model is not necessarily be the place you want to be looking. Here is a standard Yii query:
$model = WhateverModel::model()->findAll(array(
"condition" => "'.date('Y-m-d H:i:s' BETWEEN validRrom AND validTo).'",
));
You will have to give a bit more detail if you more detailed help :)