Laravel nova diffForHumans DateTime - php

I have field last_active on users, I want display time with diffForHumans or time_from_now from Moment.js. How I can do it? Now I just use:
DateTime::make('Activiy', 'last_active')
->exceptOnForms(),
When I use:
DateTime::make('Activiy', 'last_active')->diffForHumans()
->exceptOnForms(),
I get undifined method diffForHumans.

To my knowledge at the moment DateTime only supports format.
Since you want only to display, you can try Text field & display the humanise value. If your column might be null be sure to check for that otherwise you will get an error.
Text::make('Activiy', 'last_active')
->displayUsing(function($lastActive) {
if ($lastActive === null) {
return null;
}
return $lastActive->diffForHumans();
})
->exceptOnForms(),

Related

Adapt datetime field in Yii automatically to right format

I'd like to have a field inside a form, which has a format like dd.MM.yyyy HH:mm. I've done this with the date validator.
But now I have the problem, that the user always have to enter a time, not only the specified day. Is it possible automatically set the time to 00:00 when the user only enters the date?
Thanks for your help.
protected function beforeSave()
{
if ( strpos(trim(this->date_field), ' ') !== false ) {
$this->date_field = sprintf('%s 00:00', $this->date_field);
}
return parent::beforeSave();
}

Date Format issue in CGridView - YII Framework

I am trying to display created date column in CGridView, in DB its datatype is DateTime.
I have used the below code to format the date,
array( 'name'=>'created',
'header'=>'created',
'value' => 'Yii::app()->dateFormatter->format("d/M/y",strtotime($data->created))'
),
I am getting date formated column in CGridView, but null values shows sysdate in column. Please see attached image,
Please provide any solution to remove sysdate in null values column
Well, strtotime(null) will return false (Kami is apparently wrong).
The issue is in Yii date formater : Yii::app()->dateFormatter->format("d/M/y", false) will return current date.
You should simply create a getter in your model :
function getCreatedDate()
{
if ($this->created===null)
return;
return Yii::app()->dateFormatter->format("d/M/y", $this->created);
}
And in your grid view columns, you just have to use :
array('name'=>'created', 'value'=>'$data->createdDate'),
or 'createdDate'.
Use nullDisplay property of CGridView and set:
'nullDisplay'=>''

CodeIgniter: TankAuth, Check user date of birth as a callback

Ok, So I ave implemented a Date of Birth into the user registration. What I want to do now is take that date of birth and check to see if they are above a certain age (13) before they register. They way I did DOB is kinda weird, but it works. I have 3 field dob1, dob2, dob3. CodeIgniter: Tank Auth, Adding Date of Birth Issues here is how i implemented it if anyone is interested. Anyway, this is what I have been trying so far: EDIT: the syntax the user puts in is mm dd yyyy
function is_old_enough($input, $dob1, $dob2) {
$dob = $dob1.$dob2.$input;
$date = date('md').(date('Y')-13);
if ((int)$dob < (int)$date)
$this->form_validation->set_message('is_old_enough', 'You are not old enough to have an account on this site.');
return $input;
}
And here is what is inside the register() function.
$this->form_validation->set_rules('dob1', 'Date of Birth Month', 'trim|required|xss_clean|exact_length[2]');
$this->form_validation->set_rules('dob2', 'Date of Birth Day', 'trim|required|xss_clean|exact_length[2]');
$this->form_validation->set_rules('dob3', 'Date of Birth Year', 'trim|required|xss_clean|exact_length[4]|callback_is_old_enough[dob1||dob2]');
Am I close? Am i way off? Anyone help? Right now all it does is pretends like I never created this callback and puts the user in even if the user is too young. I know it is calling the function correctly as I had some issues with the variables. Help?
EDIT: Brendan's answer helped me a lot, but the main issue was a logic error. So here is how I have it working right now:
//Check if user is old enough
function is_old_enough($input) {
$dob = $this->input->post('dob3').$this->input->post('dob1').$this->input->post('dob2');
$date = (date('Y')-13).date('md');
if ((int)$dob > (int)$date) {
$this->form_validation->set_message('is_old_enough', 'You are not old enough to register on this site.');
return FALSE;
}
return TRUE;
}
$this->form_validation->set_rules('dob1', 'Date of Birth Month', 'trim|required|xss_clean|exact_length[2]');
$this->form_validation->set_rules('dob2', 'Date of Birth Day', 'trim|required|xss_clean|exact_length[2]');
$this->form_validation->set_rules('dob3', 'Date of Birth Year', 'trim|required|xss_clean|exact_length[4]|callback_is_old_enough[]');
First of all, you can only pass up to two arguments in a callback. Second, if you return a non-boolean value from a callback, whatever is returned will replace the value of the field you ran the callback on.
If you're trying to check if something is valid, the way it works (essentially) is:
function _callback_for_field($input)
{
// check if $input is valid based on your own logic
if($input == YOUR_LOGIC_HERE)
{
return TRUE;
}
return FALSE;
}
But for what you're doing, specifically:
// Birthdate rules
$this->form_validation->set_rules('birthdate-month','Birthdate Month','required|is_natural_no_zero|greater_than[0]|less_than[13]');
$this->form_validation->set_rules('birthdate-day','Birthdate Day','required|is_natural_no_zero|greater_than[0]|less_than[32]');
$this->form_validation->set_rules('birthdate-year','Birthdate Year','required|is_natural_no_zero|greater_than[1930]|less_than['.(date("Y") - 18).']');
I purposely don't go to great lengths to prevent someone that's barely under the age of 18 to register, because if they want to, they'll do it anyway. It is impossible to restrict registration based on age if the person is determined to, and since you're not checking some government database on citizens, it's not really within your scope of responsibility. A simple age check is all that's required.
I had a second thought -- If you still want to accurately check, you can reference $this->input->post() for each of the fields in your callback function. You can even run the callback function with no arguments, since you will be circumventing that restriction.

Zend_Form set and validate field value manually

I have a Zend_Form with a dropdown field.
When the user sets a value in the url this one should be selected as default value in this dropdown.
So what i do at the moment is this:
$parlang = $this->getRequest()->getParam('lang');
if($parlang){
$this->view->filterForm->getElement('ddLanguage')->setValue($parlang);
}
if ($this->getRequest()->isPost()) {
if($this->view->filterForm->isValid($_POST)){
...
...
...
No i want to check if the value of the variable is even a valid value for the dropdown? How can i check this in coorporation with the form validation. Yes i can check the variable against a array or so but this seems to be "fighting against the framework".
So what is the Zend way to do such a thing?
Edit:
My final solution for all who are interested, is:
$parlang = $this->getRequest()->getParam('lang');
if($parlang){
$ddLanguage = $this->view->filterForm->ddLanguage;
if($ddLanguage->isValid($parlang)){
$ddLanguage->setValue($parlang);
$language = $parlang;
}
}
I ran a quick test and it looks like one method you can use is Zend_Form_Element_Select::getMultiOption() to check if the language exists in the select values.
<?php
$parlang = $this->getRequest()->getParam('lang');
if ($parlang) {
$el = $this->view->filterForm->getElement('ddLanguage');
// attempt to get the option
// Returns null if no such option exists, otherwise returns a
// string with the display value for the option
if ($el->getMultiOption($parlang) !== null) {
$el->setValue($parlang);
}
}
If your Multiselect element contains a list of country, I would just populate a default in your element value according to the one in the URL.
In order to do so, you could create a custom Zend_Form_Element as follow:
class My_Form_Element_SelectCountry extends Zend_Form_Element_Select
{
protected $_translatorDisabled = true;
public function init()
{
$locale = Zend_Registry::get('Zend_Locale');
if (!$locale) {
throw new Exception('No locale set in registry');
}
$countries = Zend_Locale::getTranslationList('territory', $locale, 2);
unset($countries['ZZ']);
// fetch lang parameter and set US if there is no param
$request = Zend_Controller_Front::getInstance()->getRequest();
$lang = $request->getParam('lang', 'US');
// sort your country list
$oldLocale = setlocale(LC_COLLATE, '0');
setlocale(LC_COLLATE, 'en_US');
asort($countries, SORT_LOCALE_STRING);
setlocale(LC_COLLATE, $oldLocale);
// check weither the lang parameter is valid or not and add it to the list
if (isset($countries[$lang])) {
$paramLang = array($lang => $countries[$lang]);
$countries = array_merge($paramLang, $countries);
}
$this->setMultiOptions($countries);
}
}
You get the idea from this custom form.
If what you're trying to do isn't a Multiselect field filled by a country list but a list of language instead, then the logic is the same, you just need to change the call to the static method Zend_Locale::getTranslationList()and grab whatever information you need.
One more thing, if you just want a single element in your Multiselect element, then go for a Zend_Form_Element_Hidden.
It's a lot of "if" but I can't understand how looks like your Multiselect element exactly from your question.
Now let's take a look on the validation side, when you're using a Multiselect element, Zend_Framework automatically adds an InArray validator, which means that you don't have anything to do to check weither the data sent are correct or not. isValid is going to do it for you.
Weither a user let the default parameter and everything will be fine, or he modifies/deletes this parameter and the default parameter (en_US in this case, see code above) is going to be set as a default value for the Multiselect field.
To answer your last question, no it's not against the framework to check a variable set by a user and compare it with an array (from getTranslationList()for example). I would say it's even the recommended way to do things.

Magento backend customer account DOB update issue

I am trying to update the DOB of a customer from the backend of magneto. The year of DOB I am going to set is 1967. Ok, Well, The record is updated successfully but when I go inside the database table and see the DOB it contains the year 2067. I am surprised how this happened.
I again go in to the backend and set it to 1971 and update the customer record. But this time DOB is ok in the database table. It is 1971.
I reached at the conclusion that the DOB less than 1970 is stored wrongly in the database.
Is it magento bug or something wrong with my magento copy.
Thanks
This is a bug in Magento, and there's some chance that this bug will be fixed in next release 1.5.0.0. But I'd not rely on that.
Currently there's no easy way to cope with it, as logic for this is hidden and separated across abstract EAV and Customer attributes models. The basic approach is to
1) Show date in backend in medium format with YYYY instead of YY
and then either
2) Write your custom input validation filter that will validate date in medium format for DOB
3) Change input validation filter from default 'date' to yours (it's done in table customer_eav_attribute)
or
2) write code to set _dateFilterFormat of 'dob' attribute to medium
As of 1.5.1 this still applies. Andrey may be correct but does not provide any details on how to implement that. I've tried to do it and since I can't comment on his answer yet I'll post it here:
In app\code\core\Mage\Adminhtml\Block\Widget\Form.php _setFieldset where it says "FORMAT_TYPE_MEDIUM" add afterwards
if($attribute->getName() == 'dob') $element->setFormat(Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM));
In app\code\core\Mage\Customer\Model\Attribute\Data\Abstract.php _dateFilterFormat after is_null($format)
$a = $this->getAttribute();
if(!empty($a) && $a->getName() == 'dob') {
$this->_dateFilterFormat = Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM;
return Mage::app()->getLocale()->getDateFormat($this->_dateFilterFormat);
}
Changing app\code\core\Mage\Customer\Block\Widget\Dob.php getDateFormat to FORMAT_TYPE_MEDIUM doesn't really help. The JavaScript will still accept two number years because the validation replaces the date pattern's "y" ignoring case and uses "new Date()" which interprets a two number year just the same. The year sanity check then works on the interpreted year which will be at least 1901.
If you want hard coded four number years just uncomment (in 1.5.1) the part in js\varien\js.js in DateElement.validate where it says year<1900 and throw out the !this.validateData. Or if you want to make sure you only affect DOB use this:
Varien.DOB = Class.create();
Varien.DOB.prototype = {
initialize: function(selector, required, format) {
var el = $$(selector)[0];
var container = {};
container.day = Element.select(el, '.dob-day input')[0];
container.month = Element.select(el, '.dob-month input')[0];
container.year = Element.select(el, '.dob-year input')[0];
container.full = Element.select(el, '.dob-full input')[0];
container.advice = Element.select(el, '.validation-advice')[0];
this.child = new Varien.DateElement('container', container, required, format);
container.day.validate = this.validate.bind(this);
container.month.validate = this.validate.bind(this);
container.year.validate = this.validate.bind(this);
},
validate: function() {
if(this.child.validate()) {
var year = parseInt(this.child.year.value, 10);
if (!isNaN(year) && (year<1900 || year>this.child.curyear) ) {
errorType = this.child.validateDataErrorType;
valueError = this.child.validateDataErrorText;
error = valueError;
try {
error = Translator.translate(error);
}
catch (e) {}
this.child.advice.innerHTML = this.child.errorTextModifier(error);
this.child.advice.show();
return false;
}
return true;
}
return false;
},
};
Finally Magento will still not be able to output a DOB smaller than 13th December 1901 in the frontend because it overflows the return value of strtotime. So you'll have to change app\code\core\Mage\Customer\Block\Widget\Dob.php functions:
public function setDate($date)
{
$this->setTime($date ? strtotime($date) : false);
$this->setData('date', $date);
try {
$this->setDateTime(new DateTime($date));
}catch(Exception $e){}
return $this;
}
public function getDay()
{
return $this->getTime() ? date('d', $this->getTime()) : ($this->getDateTime() ? $this->getDateTime()->format('d') : '');
}
public function getMonth()
{
return $this->getTime() ? date('m', $this->getTime()) : ($this->getDateTime() ? $this->getDateTime()->format('m') : '');
}
public function getYear()
{
return $this->getTime() ? date('Y', $this->getTime()) : ($this->getDateTime() ? $this->getDateTime()->format('Y') : '');
}
I hope I got everything... though it still isn't a very clean way to do this ;).

Categories