Yii2 Optional textbox with Checkbox from database - yii2

I am using following code to generate checkboxes from database. I need to add optional textbox for some options. Can anybody give me clue to add it ?
$form->field($model_detail, 'DOCUMENT_TYPE_ID')
->checkboxList(
$listData,array('separator'=>'<BR />')
)->label('Select Document(s)');

You should extends ActiveField and write your custom checkboxList method. It may looks like this:
class ProjectActiveField extends ActiveField
{
/**
* #inheritdoc
*/
public function checkboxList($items, $options = [])
{
$inputs = '';
foreach ($items as $id => $value) {
$input = Html::activeCheckbox($this->model, $this->$id, $options);
$description = $options['itemDescriptions'][$id];
if ($description) {
$input = '<div class="checkbox">' . $description . $input . '</div>';
}
$inputs .= $input;
}
$this->adjustLabelFor($options);
$this->parts['{input}'] = $inputs;
return $this;
}
}

Related

How do I download a generated csv in magento 2.4.5

My files so far are:
system.xml
<field id="generate_csv" translate="label" type="button" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Generate Categories CSV</label>
<frontend_model>Vendor\Module\Block\Adminhtml\System\Config\Button</frontend_model>
</field>
button.php
<?php
namespace [Vendor]\[Module]\Block\Adminhtml\System\Config;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Backend\Block\Template\Context;
use Magento\Framework\Data\Form\Element\AbstractElement;
class Button extends Field
{
protected $_template = 'Vendor_Module::system/config/button.phtml';
public function __construct(
Context $context,
array $data = []
){
parent::__construct($context, $data);
}
public function render(AbstractElement $element)
{
$element->unsScope()->unsCanUseWebsiteValue()->unsCanUseDefaultValue();
return parent::render($element);
}
protected function _getElementHtml(AbstractElement $element)
{
return $this->_toHtml();
}
public function getAjaxUrl()
{
return $this->getUrl('[router]/Export/CategoryExport');
}
public function getButtonHtml()
{
$button = $this->getLayout()->createBlock(
'Magento\Backend\Block\Widget\Button'
)->setData(
[
'id' => 'generate_csv',
'label' => __('Generate CSV')
]
);
return $button->toHtml();
}
}
button.phtml
<script>
require([
'jquery',
'prototype'
], function ($) {
$('#generate_csv').click(function () {
var params = {};
new Ajax.Request('<?php echo $block->getAjaxUrl() ?>', {
parameters: params,
loaderArea: false,
asynchronous: true,
onCreate: function () {
$('#custom_button_response_message').text('');
},
onSuccess: function (transport) {
var resultText = '';
if (transport.status > 200) {
resultText = transport.statusText;
} else {
var response = JSON.parse(transport.responseText);
resultText = response.message
}
$('#generate_csv_response_message').text(resultText);
}
});
});
});
</script>
<?php echo $block->getButtonHtml(); ?>
<p>
<span id="generate_csv_response_message"></span>
</p>
controller
<?php
namespace [Vendor]\[Module]\Controller\Adminhtml\Export;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\Result\Json;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Filesystem;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory;
use Magento\Catalog\Model\CategoryFactory;
class CategoryExport extends Action
{
protected $resultJsonFactory;
/**
* #param Context $context
* #param JsonFactory $resultJsonFactory
*/
public function __construct(
Context $context,
JsonFactory $resultJsonFactory,
Filesystem $filesystem,
DirectoryList $directoryList,
CollectionFactory $categoryCollectionFactory,
CategoryFactory $categoryFactory
){
$this->resultJsonFactory = $resultJsonFactory;
$this->filesystem = $filesystem;
$this->directory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);
$this->categoryCollectionFactory = $categoryCollectionFactory;
$this->categoryFactory = $categoryFactory;
parent::__construct($context);
}
/**
* #return Json
*/
public function execute()
{
$message = 'Success';
$data[] = [
'id' => __('Entity ID'),
'name' => __('Name'),
'level' => __('Level')
];
$categoryCollection = $this->categoryCollectionFactory->create();
$categoryCollection->addAttributeToSelect('*');
$filepath = 'export/customerlist.csv';
$this->directory->create('export');
$stream = $this->directory->openFile($filepath, 'w+');
$stream->lock();
$header = ['Id', 'Name', 'Level'];
$stream->writeCsv($header);
//$categoryArray = array();
foreach ($categoryCollection as $category) {
$data = [];
$data[] = $category->getId();
$data[] = $category->getName();
$data[] = $category->getLevel();
$stream->writeCsv($data);
}
/** #var Json $result */
$result = $this->resultJsonFactory->create();
return $result->setData(['message' => $message]);
}
}
This creates a csv file in var/export directory but I cannot download it
Can anyone help explain how to modify the code so that it will automatically create and down the csv.
I have tried following various examples on the web but none of them have worked.
Please help me out

Upload a file to filesystem and then store details on a datatable [duplicate]

This question already has answers here:
Yii Framework 2.0 Uploading Files Error finfo_file(): failed to open stream: No such file or directory
(10 answers)
Closed 3 years ago.
I'm coding a view to upload a file, the user may choose between upload it to the filesystem or upload it to the filesystem and record the filename on a datatable.
At this moment, the first stage (upload it to the filesystem only) is working, regards to the second option, the file is uploaded to the directory but I can't add the filename info to the table; I am confuse with these 2 facts: 1) I am getting this error: finfo_file(/tmp/phpKB2h1A): failed to open stream: No such file or directory, 2) the var (tplfilename) is blank
This is the View:
<?php
use yii\widgets\ActiveForm;
?>
<?php if (Yii::$app->session->hasFlash('sminfo2')): ?>
<div class="alert alert-success">
<?= Yii::$app->session->getFlash('sminfo2');?>
</div>
<?php else: ?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'tplfilename')->fileInput()->label('Choose your Template',['class'=>'label-class']) ?>
<?= $form->field($model, 'destination')->radioList(array('1'=>'Filesystem','2'=>'Datatable'))->label('File store destination:') ?>
<button>Submit</button>
<?php ActiveForm::end() ?>
<?php endif; ?>
This is the controller's function:
public function actionUploadtpl(){
$model = new UploadtplForm();
if (Yii::$app->request->isPost) {
$model->destination = $_POST['UploadtplForm']['destination'];
$model->tplfilename = UploadedFile::getInstance($model, 'tplfilename');
if($model->destination == "1"){
if ($model->upload()) {
// file is uploaded successfully
Yii::$app->session->setFlash("sminfo2", "Template file uploaded successfully to Filesystem");
return $this->refresh();
//return;
}//end of if model upload
}//end of if model destination ==1
else{
if($model->upload()){
$model->save();
Yii::$app->session->setFlash("sminfo2", "Template file uploaded successfully to Datatable");
return $this->refresh();
}
}
}//end of isPost
return $this->render('uploadtpl', ['model' => $model]);
}//end of uploadtplform
And this is the model:
<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\web\UploadedFile;
use yii\db\ActiveRecord;
/**
* #property int $id
* #property string $tplfilename
**/
//class UploadtplForm extends Model
class UploadtplForm extends \yii\db\ActiveRecord
{
/**
* #var UploadedFile
*/
public $tplfilename; //upload filename
public $destination; //set by user on view: upload the file to filesystem or datatable
public static function tableName(){
return 'templates';
}
public function rules()
{
return [
[['tplfilename'], 'file', 'skipOnEmpty' => false, 'extensions' => 'php'],
];
}
public function upload()
{
/*
if ($this->validate()) {
$this->tplFile->saveAs('mail/views' . $this->tplFile->baseName . '.' . $this->tplFile->extension);
return true;
} else {
return false;
}
*/
//store using filesystem
$this->tplfilename->saveAs('../mail/views/' . $this->tplfilename->baseName . '.' . $this->tplfilename->extension);
return true;
}//end of upload function
public function attributeLabels()
{
return [
'id' => 'ID',
'tplfilename' => 'File name',
];
}
}
?>
I would like to have your comments about how to achieve to upload the file and record the filename on the data table, most of the issue is about this line: $model->save().
Here is my model like an example:
/*
* Upload image
* #params $url Url where to upload
* #return filename
*/
public function upload($url, $image_name)
{
try{
if ($this->validate()) {
$this->imageFile->saveAs($url . $this->imageFile->baseName . '.' . $this->imageFile->extension);
if($image_name){
FileHelper::unlink($url . $image_name);
}
return $this->imageFile->baseName . '.' . $this->imageFile->extension;
}
} catch (Exception $ex) {
throw new Exception("Error while upload file.");
return false;
}
Here is my controller:
/**
* Upload image for product.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
protected function Upload(UploadedFile $object, $name = null)
{
$user_id = $this->getUser()->id;
$model = new UploadForm();
$model->imageFile = $object;
$path = Yii::getAlias('#frontend/uploads/user-files/user-') . $user_id;
//check if dirrectory exist
if ( ! is_dir($path)) {
FileHelper::createDirectory($path);
}
$url = $path . '/';
return $model->upload($url, $name);
}
and here i call my method from action and save the model:
$cart_item_option->option_type_value = $this->Upload(UploadedFile::getInstanceByName('image'), null);
$cart_item_option->save();

Zend error Connection

I have a problem with my code, the first code is like
<?php
require_once('zend/json.php');
require_once('zend/db.php');
//require_once 'Zend/Db/Adapter/Pdo/pgsql.php';
class jsonvi
{
protected $_db;
public function _koneksi ()
{
try
{
$this->_db = zend_db::factory('PDO_PGSQL',array(
'host'=>'localhost',
'username'=>'stet',
'password'=>'test',
'dbname'=>'test'
));
return $this->_db;
}
catch(zend_db_exception $e)
{
return $e->getmessage();
}
}
public function getdata()
{
$db = $this->_koneksi();
try
{
$sql = "select * from info ";
$da = $db->fetchall($sql);
$num = count($da);
for ($a=0;$a<$num;$a++)
{
$data = $db->fetchall($sql);
return $data;
}
}
catch (zend_db_exception $e)
{
return $e->getmessage();
}
}
}
$view = new jsonvi();
$view = $view->getdata();
echo zend_json::encode($view);
?>
and it works well, but I want to make it like
<?php
include ('table.php');
include ('config.php');
require_once('zend/json.php');
require_once('zend/db.php');
require_once 'Zend/Db/Adapter/Pdo/pgsql.php';
class jsonvi
{
protected $_db;
public function _koneksi ()
{
try
{
$this->_db = zend_db::factory('PDO_PGSQL',array(
'host'=>$dbhost,
'username'=>$dbuser,
'password'=>$dbpass,
'dbname'=>$dbdb
));
return $this->_db;
}
catch(zend_db_exception $e)
{
return $e->getmessage();
}
}
public function getdata()
{
$db = $this->_koneksi();
try
{
$sql = "select * from ".$table;
$da = $db->fetchall($sql);
$num = count($da);
for ($a=0;$a<$num;$a++)
{
$data = $db->fetchall($sql);
return $data;
}
}
catch (zend_db_exception $e)
{
return $e->getmessage();
}
}
}
$view = new jsonvi();
$view = $view->getdata();
echo zend_json::encode($view);
?>
I don't know whats wrong with this code, I need help.
the error message Notice: Undefined variable: dbdb in C:\wamp....
The config.php is only have code like $dbpass = 'test'; and like that, I'm creating a simple web and I want to make my code to other database and aplikasi, so I only changed the config.php and the table.php
for the table.php maybe will work if the config.php work.
Thanks.
You are using a class and not paying attention to variable scope.
I understand you have variables with values for the DB connection in that config.php file. Although these variables are available inside the script file with the include they are NOT available and accessible inside your class. The only difference would be any constants with define (or variables inside a global which is not a good idea).
You could create a config class inside the config.php and set the values as properties then instantiate that class inside your _koneksi method. And then you would use a require_once instead of the include.
UPDATE
So here's an example that is similar to your file where your include ('config.php'); is essentially the same as declaring your variables directly before the class begins.
// variable defined outside the class
$foo = 'foo';
class demo
{
public $bar = 'bar';
function test()
{
$foobar = 'foobar';
echo 'Class property $bar is:' . $this->bar . PHP_EOL;
echo 'Local variable $foobar is:' . $foobar . PHP_EOL;
}
function run()
{
if (isset($foo)) {
echo 'Global variable $foo is:' . $foo . PHP_EOL;
} else {
// This is where you have your problem.
// Variables from outside the class are not available.
echo 'Global variable $foo not found' . PHP_EOL;
}
}
}
$demo = new demo();
$demo->test(); // Class property $bar is:bar
// Local variable $foobar is:foobar
$demo->run(); // Global variable $foo not found
echo 'Variable $foo is: ' . $foo . PHP_EOL; // Class property $bar is:bar

Amazon Product Ads, is there an API to search for Categories?

I'm building a module that will help seller put their products catalogue in the Amazon Product Ads service. For that, I need to make a mapping between the client's category and the Amazon Product Ads categories.
Problem is, I can't find an API that will help me search for Categories, or a file containing all the existing categories for Amazon Product Ads.
I found that link http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BrowseNodeIDs.html, that may be a start, but based on their API, it's not possible to search by text (like "Apparel") but by NodeId, which is not what I'm looking for :/
Can anyone of you help me please?
Thank you for your help :)
You have to use Browse Node Id of parent categories and bases on that you can search for sub categories.
Create a file named amazon_api_class.php
<?php
require_once 'aws_signed_request.php';
class AmazonProductAPI
{
/**
* Your Amazon Access Key Id
* #access private
* #var string
*/
private $public_key = "";
/**
* Your Amazon Secret Access Key
* #access private
* #var string
*/
private $private_key = "";
private $media_type = "";
private $region = "";
private $out_file_fp = "";
public function __construct($public, $private, $region) {
$this->public_key = $public;
$this->private_key = $private;
$this->region = $region;
}
public function getNode($node)
{
$parameters = array("Operation" => "BrowseNodeLookup",
"BrowseNodeId" => $node,
"ResponseGroup" => "BrowseNodeInfo");
$xml_response = aws_signed_request($parameters,
$this->public_key,
$this->private_key,
$this->region);
return ($xml_response);
}
public function setMedia($media, $file = "") {
$media_type = array("display", "csv");
if(!in_array($media,$media_type)) {
throw new Exception("Invalid Media Type");
exit();
}
$this->media_type = $media;
if($media == "csv") {
$this->out_file_fp = fopen($file,'a+');
}
}
private function writeOut($level, $name, $id, $parent) {
if($this->media_type == "display") {
$spaces = str_repeat( ' ', ( $level * 6 ) );
echo $spaces . $parent . ' : ' . $name . ' : ' . $id . "\n";
} elseif ($this->media_type == "csv") {
$csv_line = '"' . $parent . '","' . $name . '","' . $id . '"' . "\n";
fputs($this->out_file_fp, $csv_line);
} else {
throw new Exception("Invalid Media Type");
exit();
}
}
public function getBrowseNodes($nodeValue, $level = 0)
{
try {
$result = $this->getNode($nodeValue);
}
catch(Exception $e) {
echo $e->getMessage();
}
if(!isset($result->BrowseNodes->BrowseNode->Children->BrowseNode)) return;
if(count($result->BrowseNodes->BrowseNode->Children->BrowseNode) > 0) {
foreach($result->BrowseNodes->BrowseNode->Children->BrowseNode as $node) {
$this->writeOut($level, $node->Name,
$node->BrowseNodeId,
$result->BrowseNodes->BrowseNode->Name);
$this->getBrowseNodes($node->BrowseNodeId, $level+1);
}
} else {
return;
}
}
public function getNodeName($nodeValue)
{
try {
$result = $this->getNode($nodeValue);
}
catch(Exception $e) {
echo $e->getMessage();
}
if(!isset($result->BrowseNodes->BrowseNode->Name)) return;
return (string)$result->BrowseNodes->BrowseNode->Name;
}
public function getParentNode($nodeValue)
{
try {
$result = $this->getNode($nodeValue);
}
catch(Exception $e) {
echo $e->getMessage();
}
if(!isset($result->BrowseNodes->BrowseNode->Ancestors->BrowseNode->BrowseNodeId)) return;
$parent_node = array("id" => (string)$result->BrowseNodes->BrowseNode->Ancestors->BrowseNode->BrowseNodeId,
"name" => (string)$result->BrowseNodes->BrowseNode->Ancestors->BrowseNode->Name);
return $parent_node;
}}?>
Create file named as aws_signed_request.php
<?php
function aws_signed_request($params,$public_key,$private_key,$region)
{
$method = "GET";
$host = "ecs.amazonaws.".$region; // must be in small case
$uri = "/onca/xml";
$params["Service"] = "AWSECommerceService";
$params["AWSAccessKeyId"] = $public_key;
$params["AssociateTag"] = 'YOUR-ASSOCIATES-ID-HERE';
$params["Timestamp"] = gmdate("Y-m-d\TH:i:s\Z");
$params["Version"] = "2009-03-31";
/* The params need to be sorted by the key, as Amazon does this at
their end and then generates the hash of the same. If the params
are not in order then the generated hash will be different thus
failing the authetication process.
*/
ksort($params);
$canonicalized_query = array();
foreach ($params as $param=>$value)
{
$param = str_replace("%7E", "~", rawurlencode($param));
$value = str_replace("%7E", "~", rawurlencode($value));
$canonicalized_query[] = $param."=".$value;
}
$canonicalized_query = implode("&", $canonicalized_query);
$string_to_sign = $method."\n".$host."\n".$uri."\n".$canonicalized_query;
/* calculate the signature using HMAC with SHA256 and base64-encoding.
The 'hash_hmac' function is only available from PHP 5 >= 5.1.2.
*/
$signature = base64_encode(hash_hmac("sha256", $string_to_sign, $private_key, True));
/* encode the signature for the request */
$signature = str_replace("%7E", "~", rawurlencode($signature));
/* create request */
$request = "http://".$host.$uri."?".$canonicalized_query."&Signature=".$signature;
/* I prefer using CURL */
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$request);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$xml_response = curl_exec($ch);
if ($xml_response === False)
{
return False;
}
else
{
/* parse XML */
$parsed_xml = #simplexml_load_string($xml_response);
return ($parsed_xml === False) ? False : $parsed_xml;
}
}
?>
Create file named as index.php
<?php
/* Example usage of the Amazon Product Advertising API */
include("amazon_api_class.php");
$public_key = "YOUR-AMAZON-PUBLIC-KEY";
$private_key = "YOUR-AMAZON-SECRET-KEY";
$region = "com"; // or "CA" or "DE" etc.
$obj = new AmazonProductAPI($public_key, $private_key, $region);
$obj->setMedia("display");
$obj->getBrowseNodes("1036592"); //Apparel US store
?>
Dont forget to update your public and private key in index.php

How to force convert json action in Cakephp Rest

i need force convert json action in cakephp rest response. When i set '_serialize' like this
$this->set(array('message' => $lessons, '_serialize' => array('message')));
it works but some turkish characters view in unicode like "\u00e7al\u0131\u015fma alan\u0131".
It's solution is render data with json_encode($data, JSON_UNESCAPED_UNICODE) but cakephp render it automatically. How to force json_encode with JSON_UNESCAPED_UNICODE ?
Sorry for bad English.
in cakePHP 3 you can say in controller:
$this->set('_jsonOptions', JSON_UNESCAPED_UNICODE);
$this->set('_serialize', ['zones']);
which will override the options used.
JsonView doesn't accept options
There's no way to inject options in the json_encode() call invoked by JsonView, as it's hard coded optionless in the _serialize() method like this:
protected function _serialize($serialize) {
// ...
if (version_compare(PHP_VERSION, '5.4.0', '>=') && Configure::read('debug')) {
return json_encode($data, JSON_PRETTY_PRINT);
}
return json_encode($data);
}
Use a custom/extended view
So if you want to use automatic serialization, then you have to create your own/an extended view that either accepts options, or hard codes your desired options.
Here's an (untested) example with hard coded options. The _serialize() method is basically just a copy with the JSON_UNESCAPED_UNICODE option added:
App::uses('JsonView', 'View');
class MyJsonView extends JsonView {
protected function _serialize($serialize) {
if (is_array($serialize)) {
$data = array();
foreach ($serialize as $alias => $key) {
if (is_numeric($alias)) {
$alias = $key;
}
if (array_key_exists($key, $this->viewVars)) {
$data[$alias] = $this->viewVars[$key];
}
}
$data = !empty($data) ? $data : null;
} else {
$data = isset($this->viewVars[$serialize]) ? $this->viewVars[$serialize] : null;
}
if (version_compare(PHP_VERSION, '5.4.0', '>=') && Configure::read('debug')) {
return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
return json_encode($data, JSON_UNESCAPED_UNICODE);
}
}
See also http://book.cakephp.org/2.0/en/views.html#creating-your-own-view-classes
I haven't tested this myself, so it's just from the top of my head.
You could write your own View class extending JsonView and override the _serialize method.
https://github.com/cakephp/cakephp/blob/4e8e266754a25748f481b2f567e45f767808be53/lib/Cake/View/JsonView.php#L131
<?php
App::uses('JsonView', 'View');
class MyCustomView extends JsonView {
protected function _serialize($serialize) {
if (is_array($serialize)) {
$data = array();
foreach ($serialize as $alias => $key) {
if (is_numeric($alias)) {
$alias = $key;
}
if (array_key_exists($key, $this->viewVars)) {
$data[$alias] = $this->viewVars[$key];
}
}
$data = !empty($data) ? $data : null;
} else {
$data = isset($this->viewVars[$serialize]) ? $this->viewVars[$serialize] : null;
}
return json_encode($data, JSON_UNESCAPED_UNICODE);
}
}
And then in your controller do something like
<?php
App::uses('MyCustomView', 'View');
class SomeController extends AppController {
public function someMethod() {
$this->viewClass = 'MyCustomView';
// What ever you normally do
}
}