Passing extra data to yii uploader - ajax

Am creating a file uploader using the kartik uploader bu the problem is that it doesn't pass extra data
The form(view) code
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'case_description')->textArea();?>
<?php echo $form->field($evidence, 'path')->widget(FileInput::classname(), [
'options' => ['accept' => '*','multiple' => true,'name'=>'images'],
'pluginOptions' => [
'browseIcon' => '<i class="glyphicon glyphicon-camera"></i> ',
'showPreview' => true,
'showCaption' => true,
'showRemove' => true,
'showUpload' => true,
'browseLabel' => 'Insert Evidence',
'uploadUrl' => Url::to(['cases/upload']),
'maxFileCount' => 10,
'uploadExtraData' => [
'album_id' => "javascript: return $('#cases-case_description').val());",
],
],
]
);?>
The $evidence ,path is a table related to the models table
The controller that I have tested with (code)
public function actionUpload(){
$ann = empty($_POST['album_id']) ? '' : $_POST['album_id'];
var_dump($ann)
}
This returns null showing that the album_id is not passed to the controller and yet the $model->case_description is the field above the upload widget
The new controller
public function actionUpload(){
$images = $_FILES['evidence'];
$success = null;
$paths= ['uploads'];
// get file names
$filenames = $images['name'];
// loop and process files
for($i=0; $i < count($filenames); $i++){
//$ext = explode('.', basename($filenames[$i]));
$target = "uploads/cases/evidence".DIRECTORY_SEPARATOR . md5(uniqid()); //. "." . array_pop($ext);
if(move_uploaded_file($images['name'], $target)) {
$success = true;
$paths[] = $target;
} else {
$success = false;
break;
}
echo $success;
}
// check and process based on successful status
if ($success === true) {
$output = [];
} elseif ($success === false) {
$output = ['error'=>'Error while uploading images. Contact the system administrator'];
foreach ($paths as $file) {
unlink($file);
}
} else {
$output = ['error'=>'No files were processed.'];
}
// return a json encoded response for plugin to process successfully
echo json_encode($output);

Due the problem with dinamic/variable assign to extraData i suggest a simple solution based on POST / submit method (eventually set the proper action in your form)
use kartik\widgets\FileInput
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'case_description')->textArea();?>
<?php echo $form->field($evidence, 'path')->widget(FileInput::classname(), [
'options' => ['accept' => '*','multiple' => true,'name'=>'images'],
'pluginOptions' => [
'browseIcon' => '<i class="glyphicon glyphicon-camera"></i> ',
'showPreview' => true,
'showCaption' => true,
'showRemove' => true,
'showUpload' => true,
'browseLabel' => 'Insert Evidence',
'uploadUrl' => Url::to(['cases/upload']),
'maxFileCount' => 10,
],
]
);
echo Html::submitButton($model->isNewRecord ? 'Upload' : 'Update', [
'class'=>$model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']
);
ActiveForm::end();
?>

Related

Create category on the front-end with Ajax in WordPress

I'm having difficulty getting this to create a category on the front-end with Ajax. It's 99% working.
Here is my form:
<form id="new_idea" name="new_idea" method="POST">
<ul>
<li>
<label>Idea name</label>
<input type="text" name="idea_name" required />
</li>
<li class="full">
<label>Description</label>
<input type="text" name="idea_description" />
</li>
</ul>
</form>
Here is my function (in functions.php):
add_action( 'wp_ajax_add_new_idea', 'add_new_idea' );
add_action( 'wp_ajax_nopriv_add_new_idea', 'add_new_idea' );
function ajax_scripts() {
$parameters = array(
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('inputs')
);
wp_enqueue_script('my-ajax', get_template_directory_uri().'/js/ajax.js', array('jquery'), null, true);
wp_localize_script('my-ajax', 'inputs', $parameters );
}
add_action('wp_enqueue_scripts', 'ajax_scripts');
function ajaxStatus($status, $message, $data = NULL) {
$response = array (
'status' => $status,
'message' => $message,
'data' => $data
);
$output = json_encode($response);
exit($output);
}
// New Idea
function add_new_idea() {
if(isset($_POST["new_idea_form"])) {
ajaxStatus('error', 'No need to update anything.');
} else {
$nonce = $_POST['nonce'];
if(wp_verify_nonce($nonce, 'inputs') !== false) {
require_once(ABSPATH . 'wp-admin/includes/taxonomy.php');
$idea_name = $_POST['idea_name'];
$idea_description = $_POST['idea_description'];
$idea_slug = sanitize_title_with_dashes($idea_name);
$idea = array(
'cat_name' => $idea_name,
'category_parent' => '',
'category_nicename' => $idea_slug,
'category_description' => $idea_description,
'taxonomy' => 'ideas'
);
wp_insert_category( $idea );
//print_r($idea);
//die;
// Success message
ajaxStatus('success', 'Added new idea');
} else {
// No nonce!
ajaxStatus('error', 'Nonce failed!');
}
}
}
...and this is my ajax.js:
$('#new_idea').on('submit', function(e) {
e.preventDefault();
$.post( inputs.ajaxurl, {
action : 'add_new_idea',
nonce : inputs.nonce,
post : $(this).serialize()
},
function(response) {
console.log(response);
ResponseSuccess(response);
});
return false;
});
As for troubleshooting, if I hardcode values into the $idea array like this and submit the form...
$idea = array(
'cat_name' => 'cool idea',
'category_parent' => '',
'category_nicename' => 'cool-dea',
'category_description' => 'a description of my cool idea',
'taxonomy' => 'ideas'
);
...it actually works and my category gets created.
So from what I can tell, the real problem is that it is not getting the $_POST[] values that were submitted, although I can't see why.
Any help would be awesome.
Try this code.
function add_new_idea() {
$params = array();
parse_str($_POST["post"], $params);
if(isset($_POST["post"])) {
ajaxStatus('error', 'No need to update anything.');
} else {
$nonce = $_POST['nonce'];
if(wp_verify_nonce($nonce, 'inputs') !== false) {
require_once(ABSPATH . 'wp-admin/includes/taxonomy.php');
$idea_name = $params['idea_name'];
$idea_description = $params['idea_description'];
$idea_slug = sanitize_title_with_dashes($idea_name);
$idea = array(
'cat_name' => $idea_name,
'category_parent' => '',
'category_nicename' => $idea_slug,
'category_description' => $idea_description,
'taxonomy' => 'ideas'
);
wp_insert_category( $idea );
//print_r($idea);
//die;
// Success message
ajaxStatus('success', 'Added new idea');
} else {
// No nonce!
ajaxStatus('error', 'Nonce failed!');
}
}
}
Read This
you need to use parse_str for serlize object.
Retrieving serialize data in a PHP file called using AJAX

How to define $.get url using enablePrettyUrl=>true

Following code will do its job as intended, if enablePrettyUrl will be set to false:
<?php
$script = <<< JS
$('#zip_code').change(function(){
var zipId=$(this).val();
$.get('index.php?r=locations/get-city-province',{zipId:zipId},function(data){
var data=$.parseJSON(data);
alert(data.city+" liegt in "+data.province+"! Die Id ist "+zipId);
$('#customers-city').attr('value',data.city);
$('#customers-province').attr('value',data.province);
});
});
JS;
$this->registerJS($script);
?>
Following code won't, if enablePrettyUrl will be set true:
$.get('locations/get-city-province',{zipId:zipId},function(data){
Here are rules of UrlManager:
'urlManager' => [
'class' => 'yii\web\UrlManager',
'enablePrettyUrl' => true,
'showScriptName' => true,
'enableStrictParsing' => true,
'rules' => [
'locations' => 'locations/index',
'locations_create' => 'locations/create',
'locations_delete' => 'locations/delete',
'locations_update' => 'locations/update',
'locations_SaveAsNew' => 'locations/save-as-new',
'locations_pdf' => 'locations/pdf',
'locations_view' => 'locations/view',
// ...
],
],
Any ideas, how to code $.get in correct way?
Here is method of Controller:
public function actionGetCityProvince($zipId) {
$location = Locations::findOne($zipId);
echo Json::encode($location);
}
Use Url::to() or Url::toRoute()
<?php
$url = yii\helpers\Url::to(['locations/get-city-province']);
$script = <<< JS
$('#zip_code').change(function(){
var zipId = $(this).val();
$.get('$url', {zipId:zipId}, function(data){
var data = $.parseJSON(data);
alert(data.city+" liegt in "+data.province+"! Die Id ist "+zipId);
$('#customers-city').attr('value',data.city);
$('#customers-province').attr('value',data.province);
});
});
JS;
$this->registerJS($script);
?>

Yii2 compare date in model with function

I have model with below rules
public function rules()
{
return [
['student_dob',
function ($attr) {
$curr_date = date('d-m-Y');
if(empty($this->student_adm_date)) {
//$this->addError('student_dob',"Select Admission date first");
return true;
}
else {
$dob = date('Y-m-d',strtotime($this->$attr));
$adm = date('Y-m-d',strtotime($this->student_adm_date));
$diff = $adm-$dob;
if($diff <= 14) {
$this->addError('student_dob', "Birth date must be less than Admission date.");
return false;
}
else
return true;
}
},
]
];
}
This rule works good but error message don't appear on view page and my form view is below
<?php $form = ActiveForm::begin([
'layout' => 'horizontal',
'fieldConfig' => [
'template' => "{label}\n{beginWrapper}\n{input}\n{error}\n{endWrapper}",
'horizontalCssClasses' => [
'label' => 'col-sm-4',
'offset' => 'col-sm-offset-4',
'wrapper' => 'col-sm-8',
'error' => '',
'hint' => '',
],
],
]);
?>
<div class="row-left">
<?= $form->field($info, 'student_dob', ['template' => "{label} {input} <span class='status'> </span> {error}"])->widget(yii\jui\DatePicker::className(),
[
'model'=>$info,
'attribute'=>'student_dob',
'value'=>'',
'clientOptions' =>[
'dateFormat' => 'dd-mm-yyyy',
'changeMonth'=> true,
'changeYear'=> true,
'autoSize'=>true,
'showOn'=> "button",
'yearRange'=>'1900:'.(date('Y')+1),
'buttonImage'=> Yii::$app->homeUrl."images/calendar.png",
'htmlOptions'=>[
'style'=>'width:250px;',
'class'=>'form-control',
]]]); ?>
</div>
<?php ActiveForm::end(); ?>
I want to compare student_dob and student_adm_date with student_dob < student_adm_date rule validation, also error appear on form view page.
Solution
Just remove horizontalCssClasses and change template value like,
<?php $form = ActiveForm::begin([
'layout' => 'horizontal',
'fieldConfig' => [
'template' => "{label}\n{input}\n{error}",
],
]);
?>
You are subtracting one sting from another, I am not sure that works
$diff = $adm - $dob;
Try
if(strtotime($this->$attr) <= strtotime($this->student_adm_date))
Or change it to calcualte 14 days... altough not sure what you can register somebody 14 days after their birth.
You can calculate
if(strtotime($this->$attr) - strtotime($this->student_adm_date) > 60 * 60 * 24 * 14)
One more thing, in the validation functions you do not need return false; or return true; Try removing these, I personally do not know if they do anything.

Validation is always firing rule message

My validation for my image upload is always firing the message related with the allowed size for the file to be uploaded, after I copied the code to the top of the validation array where previouslly was the is_valid rule, which was being always triggered as well, even when the file size is lower than the limit and even when the file is uploaded successfully. My is_unique rule is working as expected but the rest seem to be always triggered even when the files obey the rules .What is triggering this behaviour?
I am using CakePHP 2.4.4.
Controller
public function admin_upload_image(){
$this->set('title_for_layout', 'Inserir Fotografias');
if(!$this->Session->check('User')) {
$this->Session->setFlash('Está a aceder a uma zona restrita. Por favor faça Login.');
$this->redirect(array(
'controller' => 'users',
'action' => 'login'));
}
$this->layout = 'admin_index';
if($this->request->is('post') || $this->request->is('put')) {
/* $file = $this->request->data['gallery_images']['path']['name'];*/
//debug($this->request->data['gallery_images']['path']['name']);
//die;
$file = array(
'GalleryImage' => array(
'path' => $this->request->data['gallery_images']['path']['name']
)
);
move_uploaded_file($this->data['gallery_images']['path']['tmp_name'], $_SERVER['DOCUMENT_ROOT'] . '/html/PushUp/app/webroot/img/gallery/' . $this->data['gallery_images']['path']['name']);
$this->loadModel('GalleryImage');
$this->GalleryImage->create();
//debug($file);
//die;
if($this->GalleryImage->save($file)){
$validationErrors = $this->GalleryImage->invalidFields();
$this->Session->setFlash($validationErrors['path']); // named key of the rule
$this->Session->setFlash('Fotografia guardada com sucesso.', 'default', array('class'=>'alert alert-success'));
}
//else{
//debug($this->GalleryImage->invalidFields());
//die;
//$error = $this->Notification->validationErrors;
//$this->set('error', $error);
//$this->Session->setFlash(__($error), 'Flash/warning');
//}
}
}
Model
<?php
App::uses('AppModel', 'Model');
class GalleryImage extends AppModel{
public $displayField ='path';
public $useTable = 'gallery_images';
//public $actsAs = array('MultipleDisplayFields' => array('fields' => array('path', 'id')));
var $name = 'GalleryImage';
var $validate= array(
'path' => array(
'size' => array(
'rule' => array('fileSize','<=','1.5MB'),
'message' => 'O ficheiro deve ter um tamanho igual ou inferior a 1.5MB.',
//'last' => true,
'required'=> true),
'is_valid' => array(
'rule' => 'fileSelected',
'message' => 'Seleccione uma fotografia por favor.',
//'last' => true,
'required'=> true),
'extension' => array(
'rule' => array('extension', array('gif','jpeg','png','jpg')),
'message'=> 'A imagem deve estar num formato gif, jpeg, png ou jpg.',
//'last' => true,
'required'=> true),
'is_unique' => array(
'rule' => 'isUnique',
'message' => 'Uma fotografia com este nome já existe.',
'required'=> true
)
)
);
/*public function isUploadedFile($params) {
$val = array_shift($params);
if ((isset($val['error']) && $val['error'] == 0) || (!empty( $val['tmp_name']) && $val['tmp_name'] != 'none')) {
return is_uploaded_file($val['tmp_name']);
}
return false;
}*/
public function fileSelected($file) {
if(is_array($file) && array_key_exists('path', $file) && !empty($file['path'])) {
// Seems like a file was set
return true;
}
// No file set, doesn't validate!
return false;
}
}
?>
View
<style>
.alert-warning{
width:100%;
}
.error-message{
}
.col-lg-4{
width:100%;
}
</style>
<h2>Apagar Fotografia</h2>
<?php echo $this->Session->flash();?>
<br>
<table border="1" bordercolor="#e2e2e2" width="720" style="word-wrap: break-word" cellpadding="5px" class="">
<tr>
<?php
$i=0;
foreach( $gallery_images as $gallery_image ):?>
<?php
echo "<td style=text-align: justify>";
//echo $gallery_image['GalleryImage']['path'];
echo $this->Form->postLink('Apagar', array('controller'=>'Galleries', 'action'=>'admin_del_image', $gallery_image['GalleryImage']['id']/*,'prefix'=>'admin'*/), array('class'=>'foto_del btn btn-danger', 'title'=>'Apagar Fotografia'), __('Tem a certeza que quer apagar esta Fotografia?'));
echo "</td>";
echo "<td>";
//$src3 =$this->webroot. 'img/gallery/' .$gallery_image['GalleryImage']['path'];
echo $this->Html->image('gallery/' . $gallery_image['GalleryImage']['path'] , array('width' => '200px', 'height' => '133px', 'alt' => $gallery_image['GalleryImage']['path'] ));
echo "</td>";
$i++;
if($i==4){
echo "</tr><tr>";
$i=0;
}
?>
<?php endforeach ?>
</tr>
</table>
You are passing the $file variable to be save
$this->GalleryImage->save($file)
and you are setting this variable value manually
$file = array(
'GalleryImage' => array(
'path' => $this->request->data['gallery_images']['path']['name']
)
);
so you are not passing file information to your model. you have to pass $this->request->data['gallery_images']['path'] to your save method

Why aren't validation errors being displayed in CakePHP?

I'm trying to perform validation in the login page for the name,email and password fields. If the input fails validation,the error message should be displayed.
But here,when I fill in the details and submit, it is redirected to the next page. Only the value is not saved in the database.
Why is the message not displayed?
This is my model:
class User extends AppModel {
var $name = 'User';
var $validate = array(
'name' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => true,
'message' => 'Alphabets and numbers only'
),
'between' => array(
'rule' => array('between', 5, 15),
'message' => 'Between 5 to 15 characters'
)
),
'password' => array(
'rule' => array('minLength', '8'),
'message' => 'Mimimum 8 characters long'
),
'email_id' => 'email'
);
function loginUser($data) {
$this->data['User']['email_id'] = $data['User']['email_id'];
$this->data['User']['password'] = $data['User']['password'];
$login = $this->find('all');
foreach ($login as $form):
if ($this->data['User']['email_id'] == $form['User']['email_id'] && $this->data['User']['password'] == $form['User']['password']) {
$this->data['User']['id'] = $this->find('all',
array(
'fields' => array('User.id'),
'conditions' => array(
'User.email_id' => $this->data['User']['email_id'],
'User.password'=>$this->data['User']['password']
)
)
);
$userId=$this->data['User']['id'][0]['User']['id'];
return $userId;
}
endforeach;
}
function registerUser($data) {
if (!empty($data)) {
$this->data['User']['name'] = $data['User']['name'];
$this->data['User']['email_id'] = $data['User']['email_id'];
$this->data['User']['password'] = $data['User']['password'];
if($this->save($this->data)) {
$this->data['User']['id']= $this->find('all', array(
'fields' => array('User.id'),
'order' => 'User.id DESC'
));
$userId=$this->data['User']['id'][0]['User']['id'];
return $userId;
}
}
}
}
This is my controller:
class UsersController extends AppController {
var $name = 'Users';
var $uses=array('Form','User','Attribute','Result');
var $helpers=array('Html','Ajax','Javascript','Form');
function login() {
$userId = $this->User->loginUser($this->data);
if($userId>0) {
$this->Session->setFlash('Login Successful.');
$this->redirect('/forms/homepage/'.$userId);
break;
} else {
$this->flash('Login Unsuccessful.','/forms');
}
}
function register() {
$userId=$this->User->registerUser($this->data);
$this->Session->setFlash('You have been registered.');
$this->redirect('/forms/homepage/'.$userId);
}
}
EDIT
Why is the message,example,"Minimum 8 characters long", is not being displayed when give less than 8 characters in the password field?
<!--My view file File: /app/views/forms/index.ctp -->
<?php
echo $javascript->link('prototype.js');
echo $javascript->link('scriptaculous.js');
echo $html->css('main.css');
?>
<div id="appTitle">
<h2> formBuildr </h2>
</div>
<div id="register">
<h3>Register</h3>
<?php
echo $form->create('User',array('action'=>'register'));
echo $form->input('User.name');
echo $form->error('User.name','Name not found');
echo $form->input('User.email_id');
echo $form->error('User.email_id','Email does not match');
echo $form->input('User.password');
echo $form->end('Register');
?>
</div>
<div id="login">
<h3>Login</h3>
<?php
echo $form->create('User',array('action'=>'login'));
echo $form->input('User.email_id');
echo $form->input('User.password');
echo $form->end('Login');
?>
</div>
Your validation seems correct
How about trying the following:
Make sure set your $form->create to the appropriate function
Make sure there is no $this->Model->read() before issuing Model->save();
Edit
Did you have the following?:
function register()
{
//do not put any $this->User->read or find() here or before saving pls.
if ($this->User->save($this->data))
{
//...
}
}
Edit2
IF you're doing a read() or find() before saving the Model then that will reset the fields. You should be passing the variable as type=hidden in the form. I hope i am making sense.
Edit3
I think you need to move your registerUser() into your controller because having that function in the model doesn't provide you a false return. it's always going to be true even if it has validation errors.
Comment out the redirect line and set the debug to 2 in config/core.php. Then look at the sql that is being generated to see if your insert is working. If the errors are not being displayed, maybe in the view, you are using $form->text or $form->select instead of the $form->input functions. Only the $form->input functions will automatically display the error messages.

Resources