Yii update input field with wrong date outputed - where to control it? - datetime

The user inserts a date like: 06/11/2012.
To insert into the database I use:
protected function beforeSave ()
{
if($this->date <> '')
{
list($d, $m, $y) = explode('/', $this->date);
$mk=mktime(0, 0, 0, $m, $d, $y);
$this->date = date ('Y-m-d', $mk);
}
return parent::beforeSave ();
}
Question 1) Isn't there a shorter approach ?
Anyway, it works, so I have a date in string format coming from the database date type field:
$date = '2012-11-06'
Then I use date format correctly, and I get the day and the month
yii::app()->dateFormatter->format('dd', $date);
yii::app()->dateFormatter->format('MMMM', $date);
All this seems to work fine.
However, on my update form, I get a date like this:
"20/12/1106"
On the form input field, the date should be converted to:
dd/mm/yyyy
when displayed.
On my model rules here's what I have:
array('date', 'type', 'type' => 'date', 'message' => '{attribute}: Invalid Date!', 'dateFormat' => 'dd/mm/yyyy'),
Where can we control this on Yii, so that on our input field of the date appears as dd/mm/yyyy ?
I've done this, but ofcourse if we later have other controller then update, we have to change this. This seems NOT a good approach. :(
protected function afterFind ()
{
if(Yii::app()->controller->action->id == 'update')
{
if($this->date <> '')
{
Yii::app()->dateFormatter->formatDatetime($this->date,'short');
}
return parent::afterFind ();
}
}

You can do a little workout before rendering the update form. this should work but not tested
in your action Update before $this->render(....);
$model->date = assign your required format here;
but if you need to keep this format you should avoid converting date at every place. Just save date in required format in database directly.

Related

CakePHP date parsing in patchEntity [duplicate]

I try to save data from a cakephp 3 form. All data are well saved but datetime not. I've got 2 datetime fields. Those fields are filled by jquery-ui widget.
The problem seems to happened when pacthing entity.
$intervention = $this->Interventions->patchEntity($intervention, $this->request->data);
Debug of $this->request->data :
'user_id' => '1',
'description' => 'test',
'starttime' => '2015/11/15 10:00',
'endtime' => '2015/11/15 12:10'
Debug of my object $intervention after pacthEntity :
object(App\Model\Entity\Intervention)
'id' => (int) 3,
'user_id' => (int) 1,
'description' => 'test',
'starttime' => null,
'endtime' => null
...
starttime and endtime become null and I don't understand why.
Is somebody had this pb before ?
I tried (for debuging and understanding) to force fields value afer patching
and datetime fields in mysql are ok.
$intervention->starttime = date('Y-m-d H:i:s', strtotime($this->request->data['starttime']));
$intervention->endtime = date('Y-m-d H:i:s', strtotime($this->request->data['endtime']));
Thanks for help
Date/time values are being casted/parsed in a locale aware fashion
Update: this is the default behavior with the CakePHP application template versions prior to 3.2.5. As of 3.2.5 locale parsing is not enabled by default anymore, which will make the date/time marshalling logic expect a default format of Y-m-d H:i:s instead.
In the marshalling process, values are being "casted" according to the respective column types. For DATETIME columns, this is done by the \Cake\Database\Type\DateTimeType type class.
To be exact, this is done in \Cake\Database\Type\DateTimeType::marshall().
With the default app template configuration, DateTimeType is configured to use locale aware parsing, and since no default locale format is being set, \Cake\I18n\Time::parseDateTime() will parse the values according to its default "to string format" (Time::$_toStringFormat), which defaults to the locale aware [IntlDateFormatter::SHORT, IntlDateFormatter::SHORT].
So, if for example your locale is set to en_US, then the value would be parsed with an expected format of M/d/yy, h:mm a, which your value wouldn't fit, and hence you'd finally end up with null being set for the entity property.
Make the parser use the proper format
tl;dr
In case the format for the jQuery widget is not being used everywhere in your app, you could for example either temporarily set the proper locale format, or disable locale parsing, like
// for time- or date-only comlumn types you'd use 'time' or 'date' instead of 'datetime'
$dateTimeType = Type::build('datetime')->setLocaleFormat('yyyy/MM/dd HH:mm');
// ...
$intervention = $this->Interventions->patchEntity($intervention, $this->request->data);
// ...
$dateTimeType->setLocaleFormat(null);
or
$dateTimeType = Type::build('datetime')->useLocaleParser(false);
// ...
$intervention = $this->Interventions->patchEntity($intervention, $this->request->data);
// ...
$dateTimeType->useLocaleParser(true);
It should be noted that this will affect all date/time input, not just your starttime and endtime fields!
Should the format used by the jQuery widget on the other hand be the format that you wish to use all the way through your app, then changing the default format could do it too, like
use Cake\I18n\Time;
use Cake\I18n\FrozenTime;
// To affect date-only columns you'd configure `Date` and `FrozenDate`.
// For time-only columns, see the linked SO question below.
Time::setToStringFormat('yyyy/MM/dd HH:mm');
FrozenTime::setToStringFormat('yyyy/MM/dd HH:mm');
in your bootstrap.php. Note that there's also Time/FrozenTime::setJsonEncodeFormat() and Time/FrozenTime::$niceFormat which you may want/need to modify too.
See also
Cookbook > Internationalization & Localization > Parsing Localized Datetime Data
Cookbook > Time > Setting the Default Locale and Format String
CakePHP 3 time column gets date added
Convert the input before marshalling it
Another option would be to for example convert the data to Time instances before the marshalling process. This would avoid possible problems with the previous mentioned solution that would affect all input.
In your InterventionsTable class (could also be put in a behavior or an external listener):
use Cake\Event\Event;
use Cake\I18n\Time;
...
public function beforeMarshal(Event $event, \ArrayObject $data, \ArrayObject $options)
{
foreach (['starttime', 'endtime'] as $key) {
if (isset($data[$key]) && is_string($data[$key])) {
$data[$key] = Time::parseDateTime($data[$key], 'yyyy/MM/dd HH:mm');
}
}
}
See also
Cookbook > Database Access & ORM > Saving Data > Modifying Request Data Before Building Entities

wordpress wpdb->update strange error by converting single quote to html entity

Update Julu 2018:
I find out problem is something else. The print error method will always print out a encoded html message like the one below. If the message is not showing any extra piece of information means the SQL query is fine.
Original Question:
I tried to update the invite_code by using the $wpdb->update method, but it return strange error, it seems like WordPress convert the single quote to html entity - &#39
Please help me if anyone knows why it will convert the single quote to HTML entity automatically.
I am not able to do use any WordPress built-in method to update the query because the problem seems to happen at the prepared statement which will use in every built-in method.
WordPress database error: UPDATE exhibitor_invite SET invite_code =
&#039 ;8j8mxfkkubd0kppi082p&#039 ; WHERE id = 10
function createCode() {
$length = 20;
$inviteCode = "";
$characters = "0123456789abcdefghijklmnopqrstuvwxyz";
for ($p = 0; $p < $length; $p++) {
$inviteCode .= $characters[mt_rand(0, strlen($characters))];
}
return $inviteCode;
}
function updateCode($id) {
global $wpdb;
$wpdb->show_errors();
$prefix = $wpdb->prefix;
$invite_code = createCode() ;
// I tried to esc the string, but it doesn't work
// $invite_code = $wpdb->esc_like($invite_code);
// I also tried to use normal query, but it return the same error
// $affected_rows = $wpdb->query( $wpdb->prepare(
// " UPDATE {$wpdb->prefix}exhibitor_invite SET invite_code = %s WHERE id = %d", $invite_code, $id ));
$affected_rows = $wpdb->update( $prefix.'exhibitor_invite',
array('invite_code' => $invite_code),
array('id' => $id),
'%s',
'%d' );
$wpdb->print_error();
if(!is_bool($affected_rows)) {
return $affected_rows > 0;
}
return $affected_rows;
}
Perhaps way too late, but in case not I had the exact same problem and spent hours looking for a solution.
It seems that the WordPress property 'update' of wpdb object is where the problem occurs.
One solution that I found to work is to store the entire SQL string in a variable and then before using it, pass the variable through a PHP function of mysqli_real_escape_string().
PHP manual states:
This function is used to create a legal SQL string that you can use in an SQL statement. The given string is encoded to an escaped SQL string, taking into account the current character set of the connection.
Your solution may look something like this (untested).
$sql_string =
"
UPDATE ${prefix}exhibitor_invite
SET invite_code = %s
WHERE id = %d
";
//procedural style
mysqli_real_escape_string( $your_conn_to_server, $sql_string );
//update
$wpdb->update( $wpdb->prepare(
$sql_string,
array(
$invite_code,
$id
)
), OBJECT );

Why are date/time values interpreted incorrectly when patching/saving?

I try to save data from a cakephp 3 form. All data are well saved but datetime not. I've got 2 datetime fields. Those fields are filled by jquery-ui widget.
The problem seems to happened when pacthing entity.
$intervention = $this->Interventions->patchEntity($intervention, $this->request->data);
Debug of $this->request->data :
'user_id' => '1',
'description' => 'test',
'starttime' => '2015/11/15 10:00',
'endtime' => '2015/11/15 12:10'
Debug of my object $intervention after pacthEntity :
object(App\Model\Entity\Intervention)
'id' => (int) 3,
'user_id' => (int) 1,
'description' => 'test',
'starttime' => null,
'endtime' => null
...
starttime and endtime become null and I don't understand why.
Is somebody had this pb before ?
I tried (for debuging and understanding) to force fields value afer patching
and datetime fields in mysql are ok.
$intervention->starttime = date('Y-m-d H:i:s', strtotime($this->request->data['starttime']));
$intervention->endtime = date('Y-m-d H:i:s', strtotime($this->request->data['endtime']));
Thanks for help
Date/time values are being casted/parsed in a locale aware fashion
Update: this is the default behavior with the CakePHP application template versions prior to 3.2.5. As of 3.2.5 locale parsing is not enabled by default anymore, which will make the date/time marshalling logic expect a default format of Y-m-d H:i:s instead.
In the marshalling process, values are being "casted" according to the respective column types. For DATETIME columns, this is done by the \Cake\Database\Type\DateTimeType type class.
To be exact, this is done in \Cake\Database\Type\DateTimeType::marshall().
With the default app template configuration, DateTimeType is configured to use locale aware parsing, and since no default locale format is being set, \Cake\I18n\Time::parseDateTime() will parse the values according to its default "to string format" (Time::$_toStringFormat), which defaults to the locale aware [IntlDateFormatter::SHORT, IntlDateFormatter::SHORT].
So, if for example your locale is set to en_US, then the value would be parsed with an expected format of M/d/yy, h:mm a, which your value wouldn't fit, and hence you'd finally end up with null being set for the entity property.
Make the parser use the proper format
tl;dr
In case the format for the jQuery widget is not being used everywhere in your app, you could for example either temporarily set the proper locale format, or disable locale parsing, like
// for time- or date-only comlumn types you'd use 'time' or 'date' instead of 'datetime'
$dateTimeType = Type::build('datetime')->setLocaleFormat('yyyy/MM/dd HH:mm');
// ...
$intervention = $this->Interventions->patchEntity($intervention, $this->request->data);
// ...
$dateTimeType->setLocaleFormat(null);
or
$dateTimeType = Type::build('datetime')->useLocaleParser(false);
// ...
$intervention = $this->Interventions->patchEntity($intervention, $this->request->data);
// ...
$dateTimeType->useLocaleParser(true);
It should be noted that this will affect all date/time input, not just your starttime and endtime fields!
Should the format used by the jQuery widget on the other hand be the format that you wish to use all the way through your app, then changing the default format could do it too, like
use Cake\I18n\Time;
use Cake\I18n\FrozenTime;
// To affect date-only columns you'd configure `Date` and `FrozenDate`.
// For time-only columns, see the linked SO question below.
Time::setToStringFormat('yyyy/MM/dd HH:mm');
FrozenTime::setToStringFormat('yyyy/MM/dd HH:mm');
in your bootstrap.php. Note that there's also Time/FrozenTime::setJsonEncodeFormat() and Time/FrozenTime::$niceFormat which you may want/need to modify too.
See also
Cookbook > Internationalization & Localization > Parsing Localized Datetime Data
Cookbook > Time > Setting the Default Locale and Format String
CakePHP 3 time column gets date added
Convert the input before marshalling it
Another option would be to for example convert the data to Time instances before the marshalling process. This would avoid possible problems with the previous mentioned solution that would affect all input.
In your InterventionsTable class (could also be put in a behavior or an external listener):
use Cake\Event\Event;
use Cake\I18n\Time;
...
public function beforeMarshal(Event $event, \ArrayObject $data, \ArrayObject $options)
{
foreach (['starttime', 'endtime'] as $key) {
if (isset($data[$key]) && is_string($data[$key])) {
$data[$key] = Time::parseDateTime($data[$key], 'yyyy/MM/dd HH:mm');
}
}
}
See also
Cookbook > Database Access & ORM > Saving Data > Modifying Request Data Before Building Entities

Create ACF repeater field from front end

I'm trying to create a form users can use to post from the front end of a wordpress site.
I'm having trouble with creating repeater fields though. I've tried a couple of methods, but nothing seems to work:
$periods = $_POST['periods'];
// for each perdiod, save the start/end date and notes
for ($p = 1; $p <= $periods; $p++) {
update_sub_field( array('date', $p, 'start-date'), $_POST['p'.$p.'-start-date'] );
update_sub_field( array('date', $p, 'end-date'), $_POST['p'.$p.'-start-date'] );
update_sub_field( array('date', $p, 'notes'), $_POST['p'.$p.'-start-date'] );
} // end periods loop
and
// for each perdiod, save the start/end date and notes
for ($p = 1; $p <= $periods; $p++) {
add_post_meta($post_id, 'date_'.$p.'_start-date', $_POST['p'.$p.'-start-date']);
add_post_meta($post_id, 'date_'.$p.'_end-date', $_POST['p'.$p.'-end-date']);
add_post_meta($post_id, 'date_'.$p.'_notes', $_POST['p'.$p.'-notes']);
} // end periods loop
But these do nothing to the post itself.
The repeater is set up like this:
Date (repeater) ->
start-date (field)
end-date (field)
notes (field)
There's also another repeater field in there (repeater within a repeater), but I want to get this one working first!
Any ideas?
To create a post, you'll need to use the actual field keys for each field. You can't use the field name, because the db record hasn't yet been created. Check out Elliot's documentation here for that info.
Here's how some code might look to do this:
$event_field_key = 'field_534d3f17f3ca2';
// for each perdiod, save the start/end date and notes
for ($p = 1; $p <= $periods; $p++) {
$events[] = array(
'_start-date' => $_POST['p'.$p.'-start-date'],
'_end-date' => $_POST['p'.$p.'-end-date'],
'date' => $_POST['p'.$p.'-notes']
);
} // end periods loop
update_field($event_field_key, $events, $post_id);
You will have to get the field key for that field in order for this to work correctly. To do that, go to your custom fields screen and look for screen options in the top right corner. Check the box that says show field keys. Your field keys should now show up to the right of the field name in the custom fields list. Use that to add the field.
Here's Elliot's instructions if mine didn't make sense.

can't insert event starting on a defined date into fullCalendar

I'm working on a codeIgniter project.I use fullCalendar to insert events. The concept that I want to implement is similar to google Calendar. When a user clicks on a day in the calendar, he inserts an event starting on the date of the clicked day.
I did an ajax call from my view and post the date to the controller.Once in the controller, all what I want to do is to set the start date with this value and to insert the event in the calendar. Here is my code (controller)
function add_event()
{
$click_date = $this->input->post('date');
$date= explode(" ", "$click_date ");
$month= (int)$date[1];
$day= (int)$date[2];
$year= (int)$date[3];
$date_start = $this->unix_timestamp($year.'-'.$month.'-'.$day);
$this->load->library('gcal');
$date_end = $this->unix_timestamp('2012-08-15');
$params = array(
'calendarId' => 'my Google calendar id',
'allday' => true,
'start' => $date_start,
'end' => $date_end,
'summary' => 'event',
'description' => "My first event"
);
$response = $this->gcal->eventInsert($params);
if($response)
{
echo "true";
}
}
Here is my unix_timestamp function :
function unix_timestamp($date)
{
$date = str_replace(array(' ', ':'), '-', $date);
$c = explode('-', $date);
$c = array_pad($c, 6, 0);
array_walk($c, 'intval');
return mktime($c[3], $c[4], $c[5], $c[1], $c[2], $c[0]);
}
On the calendar, the event is inserted but not on the right starting date. It starts on 2012-01-01 which is the default date I guess. I don't understand why my starting date isn't set correctly.
What I am doing wrong? Could someone please help me?
I found the answer. I should convert the fullCalendar date format into string before posting it to the controller. One line was missing :
date_format = $.fullCalendar.formatDate(date,"yyyy-MM-dd HH:mm:ss");`
Hope that it would help people who have the same problem
`

Resources