Why my json_encode get corrupted - yii

$model = new XUploadForm;
$model->file = CUploadedFile::getInstance( $model, 'file' );
//We check that the file was successfully uploaded
if( $model->file !== null ) {
//Grab some data
$model->mime_type = $model->file->getType( );
$model->size = $model->file->getSize( );
$model->name = $model->file->getName( );
$file_extention = $model->file->getExtensionName( );
//(optional) Generate a random name for our file
$file_tem_name = md5(Yii::app( )->user->id.microtime( ).$model->name);
$file_thumb_name = $file_tem_name.'_thumb.'.$file_extention;
$file_image_name = $file_tem_name.".".$file_extention;
if( $model->validate( ) ) {
//Move our file to our temporary dir
$model->file->saveAs( $path.$file_image_name );
if(chmod($path.$file_image_name, 0777 )){
// Yii::import("ext.EPhpThumb.EPhpThumb");
// $thumb_=new EPhpThumb();
// $thumb_->init();
// $thumb_->create($path.$file_image_name)
// ->resize(110,80)
// ->save($path.$file_thumb_name);
}
//here you can also generate the image versions you need
//using something like PHPThumb
//Now we need to save this path to the user's session
if( Yii::app( )->user->hasState( 'images' ) ) {
$userImages = Yii::app( )->user->getState( 'images' );
} else {
$userImages = array();
}
$userImages[] = array(
"filename" => $file_image_name,
'size' => $model->size,
'mime' => $model->mime_type,
"path" => $path.$file_image_name,
// "thumb" => $path.$file_thumb_name,
);
Yii::app( )->user->setState('images', $userImages);
//Now we need to tell our widget that the upload was succesfull
//We do so, using the json structure defined in
// https://github.com/blueimp/jQuery-File-Upload/wiki/Setup
echo json_encode( array( array(
"type" => $model->mime_type,
"size" => $model->size,
"url" => $publicPath.$file_image_name,
//"thumbnail_url" => $publicPath.$file_thumb_name,
//"thumbnail_url" => $publicPath."thumbs/$filename",
"delete_url" => $this->createUrl( "upload", array(
"_method" => "delete",
"file" => $file_image_name
) ),
"delete_type" => "POST"
) ) );
Above code give me correct response,
[{"type":"image/jpeg","size":2266,"url":"/uploads/tmp/0b00cbaee07c6410241428c74aae1dca.jpeg","delete_url":"/api/imageUpload/upload?_method=delete&file=0b00cbaee07c6410241428c74aae1dca.jpeg","delete_type":"POST"}]
but if I uncomment the following
// Yii::import("ext.EPhpThumb.EPhpThumb");
// $thumb_=new EPhpThumb();
// $thumb_->init();
// $thumb_->create($path.$file_image_name)
// ->resize(110,80)
// ->save($path.$file_thumb_name);
it gave me corrupted response:
Mac OS X 2��ATTR�dA��Y�Ycom.apple.quarantine0001;50655994;Google\x20Chrome.app;2599ECF9-69C5-4386-B3D9-9F5CC7E0EE1D|com.google.ChromeThis resource fork intentionally left blank ��[{"type":"image/jpeg","size":1941,"url":"/uploads/tmp/409c5921c6d20944e1a81f32b12fc380.jpeg","delete_url":"/api/imageUpload/upload?_method=delete&file=409c5921c6d20944e1a81f32b12fc380.jpeg","delete_type":"POST"}]

I'm guessing MacOS has quarantined your download of ext.EPhpTHumb.EPhpThumb or one of its libraries.
If you know where the plugin is installed, try xattr -d com.apple.quarantine <filename> from a terminal to remove it, or google remove mac os x quarantine status for alternate ways to do it.

Related

Prestashop 1.7.7 - HelperForm in a Multistore Context

I'm testing a first simple version for a Multistore-compatible module. It has just two settings, which have to be saved differently depending on the current shop Context (a single shop mainly).
Now, I know that from 1.7.8 there are additional checkbox for each setting in the BO Form, but I have to manage to get it work also for 1.7.7.
Now, both Configuration::updateValue() and Configuration::get() should be multistore-ready, meaning that they update or retrieve the value only for the current context, so it should be fine.
The weird thing is that, after installing the test module, if I go to the configuration page, it automatically redirects to an All-Shop context and, if I try to manually switch (from the dropdown in the top right), it shows a blank page. Same thing happens if I try to deactivate the bottom checkbox "Activate this module in the context of: all shops".
Here is my code:
class TestModule extends Module
{
public function __construct()
{
$this->name = 'testmodule';
$this->tab = 'front_office_features';
$this->version = '1.0.0';
$this->author = 'Test';
$this->need_instance = 1;
$this->ps_versions_compliancy = [
'min' => '1.7.0.0',
'max' => '1.7.8.0',
];
$this->bootstrap = true;
parent::__construct();
$this->displayName = $this->l("Test Module");
$this->description = $this->l('Collection of custom test extensions');
$this->confirmUninstall = $this->l('Are you sure you want to uninstall?');
if (!Configuration::get('TESTM_v')) {
$this->warning = $this->l('No version provided');
}
}
public function install()
{
if (Shop::isFeatureActive()) {
Shop::setContext(Shop::CONTEXT_ALL);
}
return (
parent::install()
&& $this->registerHook('header')
&& $this->registerHook('backOfficeHeader')
&& Configuration::updateValue('TESTM_v', $this->version)
);
}
public function uninstall()
{
if (Shop::isFeatureActive()) {
Shop::setContext(Shop::CONTEXT_ALL);
}
return (
parent::uninstall()
&& $this->unregisterHook('header')
&& $this->unregisterHook('backOfficeHeader')
&& Configuration::deleteByName('TESTM_v')
);
}
public function getContent()
{
// this part is executed only when the form is submitted
if (Tools::isSubmit('submit' . $this->name)) {
// retrieve the value set by the user
$configValue1 = (string) Tools::getValue('TESTM_CONFIG_1');
$configValue2 = (string) Tools::getValue('TESTM_CONFIG_2');
// check that the value 1 is valid
if (empty($configValue1)) {
// invalid value, show an error
$output = $this->displayError($this->l('Invalid Configuration value'));
} else {
// value is ok, update it and display a confirmation message
Configuration::updateValue('TESTM_CONFIG_1', $configValue1);
$output = $this->displayConfirmation($this->l('Settings updated'));
}
// check that the value 2 is valid
Configuration::updateValue('TESTM_CONFIG_2', $configValue2);
$output = $this->displayConfirmation($this->l('Settings updated'));
}
// display any message, then the form
return $output . $this->displayForm();
}
public function displayForm()
{
// Init Fields form array
$form = [
'form' => [
'legend' => [
'title' => $this->l('Settings'),
],
'input' => [
[
'type' => 'text',
'label' => $this->l('Custom CSS file-name.'),
'name' => 'TESTM_CONFIG_1',
'size' => 20,
'required' => true,
],
[
'type' => 'switch',
'label' => $this->l('Enable custom CSS loading.'),
'name' => 'TESTM_CONFIG_2',
'is_bool' => true,
'desc' => $this->l('required'),
'values' => array(
array(
'id' => 'sw1_on',
'value' => 1,
'label' => $this->l('Enabled')
),
array(
'id' => 'sw1_off',
'value' => 0,
'label' => $this->l('Disabled')
)
)
],
],
'submit' => [
'title' => $this->l('Save'),
'class' => 'btn btn-default pull-right',
],
],
];
$helper = new HelperForm();
// Module, token and currentIndex
$helper->table = $this->table;
$helper->name_controller = $this->name;
$helper->token = Tools::getAdminTokenLite('AdminModules');
$helper->currentIndex = AdminController::$currentIndex . '&' . http_build_query(['configure' => $this->name]);
$helper->submit_action = 'submit' . $this->name;
// Default language
$helper->default_form_language = (int) Configuration::get('PS_LANG_DEFAULT');
// Load current value into the form or take default
$helper->fields_value['TESTM_CONFIG_1'] = Tools::getValue('TESTM_CONFIG_1', Configuration::get('TESTM_CONFIG_1'));
$helper->fields_value['TESTM_CONFIG_2'] = Tools::getValue('TESTM_CONFIG_2', Configuration::get('TESTM_CONFIG_2'));
return $helper->generateForm([$form]);
}
/**
* Custom CSS & JavaScript Hook for FO
*/
public function hookHeader()
{
//$this->context->controller->addJS($this->_path.'/views/js/front.js');
if (Configuration::get('TESTM_CONFIG_2') == 1) {
$this->context->controller->addCSS($this->_path.'/views/css/'.((string)Configuration::get('TESTM_CONFIG_1')));
} else {
$this->context->controller->removeCSS($this->_path.'/views/css/'.((string)Configuration::get('TESTM_CONFIG_1')));
}
}
}
As you can see it's a pretty simple setting: just load a custom CSS file and choose if loading it or not. I've red official PS Docs per Multistore handling and searched online, but cannot find an answer to this specific problem.
I've also tried to add:
if (Shop::isFeatureActive()) {
$currentIdShop = Shop::getContextShopID();
Shop::setContext(Shop::CONTEXT_SHOP, $currentIdShop);
}
To the 'displayForm()' function, but without results.
Thank you in advance.
It seemsit was a caching error.
After trying many variations, I can confirm that the first solution I've tried was the correct one, meaning that:
if (Shop::isFeatureActive()) {
$currentIdShop = Shop::getContextShopID();
Shop::setContext(Shop::CONTEXT_SHOP, $currentIdShop);
}
needs to be added ad the beginning of the "displayForm()" function for it to work when selecting a single shop. Values are now correctly saved in the database. With a little bit extra logic it can be arranged to behave differently (if needed) when saving for "All shops" context.

Module Prestashop 1.7 : Custom image upload always replaced

My file_url field is always erased in Database if I don't select it. (even if an image is already integrated)
If I click Save in this situation, the field PC Image is deleted.
Here is my postImage() method in my AdminCustomController
protected function postImage($id)
{
$file = isset($_FILES['file_url']) ? $_FILES['file_url'] : false;
if ($file && is_uploaded_file($file['tmp_name'])) {
$path = _PS_MODULE_DIR_ . 'custom/img/';
$tmp_arr = explode('.', $file['name']);
$filename = $file['name'];
if (!Tools::copy($file['tmp_name'], $path . $filename)) {
$errors[] = Tools::displayError('Failed to load image');
}
}
}
And here is the renderForm()
public function renderForm()
{
$image_url = '';
if($this->object->file_url) {
$image_url = ImageManager::thumbnail(
_PS_MODULE_DIR_ . 'homecase/img/' . $this->object->file_url,
$this->table . $this->object->file_url,
150,
'jpg',
true,
true
);
}
$this->fields_form = [
//Entête
'legend' => [
'title' => $this->module->l('Edition'),
'icon' => 'icon-cog'
],
array(
'type' => 'file',
'label' => $this->l('PC Image'),
'name' => 'file_url',
'display_image' => true,
'image' => $image_url ? $image_url : false,
),
....
The upload and the save in DB is OK. But when the image exists and I don't select an other in the field. The file_url field is erased in the DB.
Could you help me?
Thanks !
You need to check if an image was uploaded and only after that update your DB records. So, just try to add return false; to your postImagemethod and that check before your DB update like
if ($this->postImage($id) !== false){
//update image record
}

Decode base64 into jpeg and save the image to server

currently i have base 64 value in
$model->test
and i want to decode the base 64 value in controller and save it to database through API here some of my code in controller
i try to decode and cant figure out how to upload it to server and create path
however i try to to pass the $data to getinstance which is not working
public function doSaveStudent(StudentLoanForm $model)
{
$url = API_URL . 'web/apply/student';
$data1 = $model->test;
$decode = base64_decode($data);
$img = file_put_contents('webcam.jpg', $data);
$model->doUploads();
$ktpdetail = UploadedFile::getInstance($model, 'image_ktp');
$data = null;
$data = [
[
'name' => 'univ_name',
'contents' => $model->univ_name
],
[
'name' => 'test',
'contents' =>$model->test
],
];
// dd($model->test);
if ($ktpdetail != null) {
$data[] = [
'name' => 'image_ktp',
'contents' => fopen(Yii::getAlias('#frontend/web/') . $model->image_ktp, 'r'),
'filename' => $ktpdetail->getBaseName() . '.' . $ktpdetail->getExtension()
];
}
if($ktpayahdetail != null){
$data[] = [
'name' => 'foto_ktp_ayah',
'contents' => fopen(Yii::getAlias('#frontend/web/') . $model->foto_ktp_ayah, 'r'),
'filename' => $ktpayahdetail->getBaseName() . '.' . $ktpayahdetail->getExtension()
];
}
if ($kkdetail != null) {
$data[] = [
'name' => 'image_kk',
'contents' => fopen(Yii::getAlias('#frontend/web/') . $model->image_kk, 'r'),
'filename' => $kkdetail->getBaseName() . '.' . $kkdetail->getExtension()
];
i expect to decode the base 64 and upload all the value using yii2 best practice
The yii\web\UploadedFile is used only for files uploaded using file input in forms.
In your case base64_decode($model->test) should give you binary data of image.
Then you have two options what to do with them.
1) You can store them directly into BLOB attribute in database.
$imageModel = new MyImageModel();
$imageModel->data = base64_decode($model->test);
if(!$imageModel->save()) {
throw new \yii\base\Exception("Couldn't save file to db");
}
2) You can save the file with file_put_contents and then store the path to file in your model.
$imageData = base64_decode($model->test);
//the used alias in path is only example.
//The datetime and random string are used to avoid conflicts
$filename = Yii::getAlias(
'#frontend/web/' . date('Y-m-d-H-i-s') .
Yii::$app->security->generateRandomString(5) . '.jpg'
);
if (file_put_contents($filename, $imageDate === false) {
throw new \yii\base\Exception("Couldn't save image to $filename");
}
$imageModel = new MyImageModel();
$imageModel->path = $filename;
if(!$imageModel->save()) {
//delete file if we couldn't save path into db to prevent creating an orphan
unlink($filename);
throw new \yii\base\Exception("Couldn't add $filename to database");
}

Add a custom notification in buddypress

I would like to add a custom notification to my buddypress "notification" tab when a particular event occurs. How to achieve this?
I followed this tutorial and is very complete. Worked for me
BuddyPress: Adding Custom Notifications
I am going to put that the author wrote. But is better if you go to the post directly, there you can find a much better explanation. I think that the post is for dummies, very complete and explanatory, even has a gist.
1st register your component
You need to register your notification as a budypress component. This is very easy. The name of the component registered was custom
// this is to add a fake component to BuddyPress. A registered component is needed to add notifications
function custom_filter_notifications_get_registered_components( $component_names = array() ) {
// Force $component_names to be an array
if ( ! is_array( $component_names ) ) {
$component_names = array();
}
// Add 'custom' component to registered components array
array_push( $component_names, 'custom' );
// Return component's with 'custom' appended
return $component_names;
}
add_filter( 'bp_notifications_get_registered_components', 'custom_filter_notifications_get_registered_components' );
2nd Render the notification
// this gets the saved item id, compiles some data and then displays the notification
function custom_format_buddypress_notifications( $action, $item_id, $secondary_item_id, $total_items, $format = 'string' ) {
// New custom notifications
if ( 'custom_action' === $action ) {
$comment = get_comment( $item_id );
$custom_title = $comment->comment_author . ' commented on the post ' . get_the_title( $comment->comment_post_ID );
$custom_link = get_comment_link( $comment );
$custom_text = $comment->comment_author . ' commented on your post ' . get_the_title( $comment->comment_post_ID );
// WordPress Toolbar
if ( 'string' === $format ) {
$return = apply_filters( 'custom_filter', '' . esc_html( $custom_text ) . '', $custom_text, $custom_link );
// BuddyBar
} else {
$return = apply_filters( 'custom_filter', array(
'text' => $custom_text,
'link' => $custom_link
), $custom_link, (int) $total_items, $custom_text, $custom_title );
}
return $return;
}
}
add_filter( 'bp_notifications_get_notifications_for_user', 'custom_format_buddypress_notifications', 10, 5 );
3st Launch the Notification
Here you add the notification when someone writes you on a post. Use the action hook wp_insert_comment for catch that event.
// this hooks to comment creation and saves the comment id
function bp_custom_add_notification( $comment_id, $comment_object ) {
$post = get_post( $comment_object->comment_post_ID );
$author_id = $post->post_author;
bp_notifications_add_notification( array(
'user_id' => $author_id,
'item_id' => $comment_id,
'component_name' => 'custom',
'component_action' => 'custom_action',
'date_notified' => bp_core_current_time(),
'is_new' => 1,
) );
}
add_action( 'wp_insert_comment', 'bp_custom_add_notification', 99, 2 );
All together
<?php
// this is to add a fake component to BuddyPress. A registered component is needed to add notifications
function custom_filter_notifications_get_registered_components( $component_names = array() ) {
// Force $component_names to be an array
if ( ! is_array( $component_names ) ) {
$component_names = array();
}
// Add 'custom' component to registered components array
array_push( $component_names, 'custom' );
// Return component's with 'custom' appended
return $component_names;
}
add_filter( 'bp_notifications_get_registered_components', 'custom_filter_notifications_get_registered_components' );
// this gets the saved item id, compiles some data and then displays the notification
function custom_format_buddypress_notifications( $action, $item_id, $secondary_item_id, $total_items, $format = 'string' ) {
// New custom notifications
if ( 'custom_action' === $action ) {
$comment = get_comment( $item_id );
$custom_title = $comment->comment_author . ' commented on the post ' . get_the_title( $comment->comment_post_ID );
$custom_link = get_comment_link( $comment );
$custom_text = $comment->comment_author . ' commented on your post ' . get_the_title( $comment->comment_post_ID );
// WordPress Toolbar
if ( 'string' === $format ) {
$return = apply_filters( 'custom_filter', '' . esc_html( $custom_text ) . '', $custom_text, $custom_link );
// Deprecated BuddyBar
} else {
$return = apply_filters( 'custom_filter', array(
'text' => $custom_text,
'link' => $custom_link
), $custom_link, (int) $total_items, $custom_text, $custom_title );
}
return $return;
}
}
add_filter( 'bp_notifications_get_notifications_for_user', 'custom_format_buddypress_notifications', 10, 5 );
// this hooks to comment creation and saves the comment id
function bp_custom_add_notification( $comment_id, $comment_object ) {
$post = get_post( $comment_object->comment_post_ID );
$author_id = $post->post_author;
bp_notifications_add_notification( array(
'user_id' => $author_id,
'item_id' => $comment_id,
'component_name' => 'custom',
'component_action' => 'custom_action',
'date_notified' => bp_core_current_time(),
'is_new' => 1,
) );
}
add_action( 'wp_insert_comment', 'bp_custom_add_notification', 99, 2 );
You use bp_notifications_add_notification(). The following example function is hooked to bp_activity_sent_mention_email - So when an email notification is sent due to somebody being #-mentioned, a core notification is generated.
function bp_activity_at_mention_add_notification( $activity, $subject, $message, $content, $receiver_user_id ) {
if ( bp_is_active( 'notifications' ) ) {
bp_notifications_add_notification( array(
'user_id' => $receiver_user_id,
'item_id' => $activity->id,
'secondary_item_id' => $activity->user_id,
'component_name' => buddypress()->activity->id,
'component_action' => 'new_at_mention',
'date_notified' => bp_core_current_time(),
'is_new' => 1,
) );
}
}
add_action( 'bp_activity_sent_mention_email', 'bp_activity_at_mention_add_notification', 10, 5 );
Ref: http://codex.buddypress.org/developer/function-examples/bp_notifications_add_notification/

Yii: Multimodelform Extension - How to create more than 1 member

I'm using Multimodelform extension to create multiple model in a single form.
This extension is working great but unfortunately i would like more than 1 member instead.
I have tried it without success at all.
My problem is I could not make more than 1 member by this extension.
Here's my code :
From Controller
public function actionCreate()
{
Yii::import('ext.multimodelform.MultiModelForm');
$model=new Endheader;
$member = new Enddetail;
$member2 = new Enddetailnq; <-- i just ant to this new member.
$validatedMembers = array();
//$validatedMembers2 = array();
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation($model);
if(isset($_POST['Endheader']))
{
$model->attributes=$_POST['Endheader'];
if(isset($_POST['sav'])){
if((MultiModelForm::validate($member, $validatedMembers, $deleteItems) && MultiModelForm::validate($member2, $validatedMembers, $deleteItems)) && $model->save())
{
$masterValues = array('HEH_ID'=>$model->HEH_ID);
if(MultiModelForm::save($member,$validatedMembers,$deleteItems,$masterValues) && MultiModelForm::save($member2,$validatedMembers,$deleteItems,$masterValues))
$msg2 = CHtml::link('View Details',array('view','id'=>$model->HEH_ID));
// $this->redirect(array('view','id'=>$model->HCO_ID));
Yii::app()->user->setFlash('success','You data have been saved successfully. '.$msg2);
$this->redirect(array('update','id'=>$model->HEH_ID));
}
}
}
$this->render('create',array(
'model'=>$model,'transport'=>$transport,
'member2'=>$member2,
'member'=>$member,
// 'validatedMembers2' => $validatedMembers2,
'validatedMembers' => $validatedMembers,
));
}
From View
$memberFormConfig = array(
'elements'=>array(
'HED_RPASS'=>array(
'type'=>'text',
'maxlength'=>11,
),
'HED_PCS'=>array(
'type'=>'text',
'maxlength'=>5,
),
));
$this->widget('ext.multimodelform.MultiModelForm',array(
'id' => 'id_member', //the unique widget id
'formConfig' => $memberFormConfig, //the form configuration array
'model' => $member, //instance of the form model
'tableView' => true,
//if submitted not empty from the controller,
//the form will be rendered with validation errors
'validatedItems' => $validatedMembers,
//'sortAttribute' => 'position',
//array of member instances loaded from db
'data' => $member->findAll('HEH_ID=:HEH_ID', array(':HEH_ID'=>$model->HEH_ID)),
));
$memberFormConfig2 = array(
'elements'=>array(
'HED_ARV_PCS'=>array(
'type'=>'text',
'maxlength'=>5,
),
'HED_ARV_VOL'=>array(
'type'=>'text',
'maxlength'=>10,
),
));
$this->widget('ext.multimodelform.MultiModelForm',array(
'id' => 'id_member2', //the unique widget id
'formConfig' => $memberFormConfig2, //the form configuration array
'model' => $member2, //instance of the form model
'tableView' => true,
//if submitted not empty from the controller,
//the form will be rendered with validation errors
'validatedItems' => $validatedMembers,
//'sortAttribute' => 'position',
//array of member instances loaded from db
'data' => $member->findAll('HEH_ID=:HEH_ID', array(':HEH_ID'=>$model->HEH_ID)),
));