So my application has student users. Each of them has an account and can upload files. In my view, I have 2 fields: A dropdown menu field and a browse file. Below those two fields is a table listing all the files uploaded by that user.
My dropdown menu contains the list of the file types needed to be uploaded (e.g. Application Form, Transcript of Record, Bio-data, etc.). The users have to choose one from the list and upload the file/s.
So what I want to do is once a file type has been uploaded, let's say the Application Form, it will be removed from the dropdown list. Of course, in case they have uploaded a wrong file, inside a table there is a remove button. Clicking the remove will bring the selected file's upload type back to the dropdown list.
How can this be done?
View:
$this->Form->input('type', array(
'class' => 'form-control',
'options' => array(
'Application Form' => 'Application Form',
'Manual' => 'Manual',
'Picture' => 'Picture'
),
'empty' => 'Choose an upload type'
));
$this->Form->input('file.', array(
'class' => 'form-control',
'type' => 'file'
));
Table below the dropdown and file browse:
<?php
foreach ($docs as $docs){
<?php echo $docs['Upload']['type'] ?>
<?php echo $this-Html-link('Remove from Table', array('controller' => 'schools', 'action' => 'remove')); ?>
}
Controller:
public function documents(){
$this-> layout = 'schools';
$this->set('docs', $this-Upload->find('all', array('condition' => array('Upload.iddocs' => $doc['Doc']['id']))));
if($this->request->is('post')){
$file = $this-request->data;
$size = (sizeof($this->request->data['Upload']['file']));
$is = $this->Auth->User('userId');
$school = $this->School->find('first', array('conditions' => array('usersId' => $id)));
if(!is_dir(ROOT . DS . 'app' . DS . 'uploads' . DS . $school['School']['name']))
mkdr(ROOT . DS . 'app' . DS . 'uploads' . DS . $school['School']['name']);
for($i=0; $i<$size; $i++){
$dest_file = ROOT . DS . 'app' . DS . 'uploads' . DS . $school['School']['name'] . DS . $file['Upload']['file'][$i]['name'];
if(move_uploaded_file($file['Upload']['file'][$i]['name']['tmp_name'], $dest_file)){
$this->Upload->create();
$data = array(
'iddocs' => $doc['Doc']['id'],
'dest' => $dest_file,
'type' => $this->request->data['Upload']['type']
);
$this->Upload->save($data);
}
}
}
}
?>
Related
http://doc.prestashop.com/display/PS16/Web+service+reference doesn't list any "attachments" or "product_attachments" etc. resource. Moreover, I have tested to fetch the products thanks to the corresponding resource present in the list, but the products don't contain any reference ID to the attachments, nore the attachments object at JSON format.
So how to fetch the products attachments? Is it possible, at least?
It doesn't or at least I could find it.
You can add it by overriding core Product class.
Add new method
public function getWsProductAttachments()
{
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(
'SELECT pa.`id_attachment` AS id, a.file, a.file_name
FROM `' . _DB_PREFIX_ . 'product_attachment` pa
LEFT JOIN `' . _DB_PREFIX_ . 'attachment` a ON (a.id_attachment = pa.id_attachment)
' . Shop::addSqlAssociation('attachment', 'a') . '
WHERE pa.`id_product` = ' . (int) $this->id
);
return $result;
}
Add next element to $webserviceParameters['associations'] property:
'attachments' => array(
'resource' => 'product',
'api' => 'products',
'getter' => 'getWsProductAttachments',
'fields' => array(
'id' => array('required' => true),
'file' => array(),
'file_name' => array(),
),
),
Now your products/{id} request will return something like
<attachments nodeType="product" api="products">
<product>
<id><![CDATA[1]]></id>
<file><![CDATA[cc046998a333a9bffaa23ce292f2da43edb37065]]></file>
<file_name><![CDATA[bbb.yml]]></file_name>
</product>
<product>
<id><![CDATA[2]]></id>
<file><![CDATA[b04566afd74cdaa54c921c8907c7efd489a2eec0]]></file>
<file_name><![CDATA[aaa.csv]]></file_name>
</product>
</attachments>
And you can download attachments like my.shop/download/cc046998a333a9bffaa23ce292f2da43edb37065
The concept of our project is, area wise products filtering, the products may be same or different. If the admin change the price of the product for particular area, then the price should change only that corresponding area.
For that, we have created new table as like oc_product_to_category with following new fields price,quantity,offer.
if the new table has the price value means then use that value for the process, if else means use default price value at the oc_product table. Upto category page we have successfully implemented this concept,
Category.php:
$this->load->model('mobile/product');
$price_by_category = $this->model_mobile_product->getpricebycategory($result['product_id'],$category_id);
if($price_by_category['price'] != ""){
$data['products'][] = array(
'product_id' => $result['product_id'],
'thumb' => $image,
'name' => $result['name'],
'description' => utf8_substr(strip_tags(html_entity_decode($result['description'], ENT_QUOTES, 'UTF-8')), 0, $this->config->get('config_product_description_length')) . '..',
'price' => "Rs.".$price_by_category['price'].".00",
'special' => $special,
'tax' => $tax,
'minimum' => $result['minimum'] > 0 ? $result['minimum'] : 1,
'rating' => $result['rating'],
'href' => $this->url->link('product/product', 'path=' . $this->request->get['path'] . '&product_id=' . $result['product_id'] . $url)
);;
}else{
$data['products'][] = array(
'product_id' => $result['product_id'],
'thumb' => $image,
'name' => $result['name'],
'description' => utf8_substr(strip_tags(html_entity_decode($result['description'], ENT_QUOTES, 'UTF-8')), 0, $this->config->get('config_product_description_length')) . '..',
'price' => $price,
'special' => $special,
'tax' => $tax,
'minimum' => $result['minimum'] > 0 ? $result['minimum'] : 1,
'rating' => $result['rating'],
'href' => $this->url->link('product/product', 'path=' . $this->request->get['path'] . '&product_id=' . $result['product_id'] . $url)
);
}
At cart , it takes the default price table value. If I create new function means, i have to change whole cart operation but i only want to change the price calculation, Based on the area id and product id.
I hope someone will give the solution.
Thanks..
There's no need to repeat the entire block for category.php. You can simply re-assign the price before adding to the array like $price = $price_by_category['price'] ?: $price.
To load your model in cart.php you can do it like this. In the __contruct block add:
public function __construct($registry) {
$this->registry = $registry;
Then in the getProducts() method you can load your model:
$this->load->model('mobile/product');
$mobileProduct = $this->registry->get('model_mobile_product');
$price_by_category = $mobileProduct->getpricebycategory($product_id,$category_id);
Of course the challenge here is you will need to add category data to the cart array when customer adds product to cart so you will be able to reference this later. My suggestion would be to encode it as a third slice in the cart session. Normally products look like this:
product-id:serialized-option-data:profile-id
So you can add another slice to store category id when adding to cart:
product-id:serialized-option-data:profile-id:category_id
Then afterward:
if (!empty($product[3])) {
$category_id = $product[3];
} else {
$category_id = 0;
}
You will also need to send category_id as POST data to controller/checkout/cart -> add() and then again pass it to system/library/cart.php to be encoded into the cart array.
For my need, I'm planning to add a custom column to a entity list.
I've written this inside the configureListFields :
->add('_action', 'actions', array(
'actions' => array(
'code' => array('template' => 'BOBAdminBundle:test:custom.html.twig'),
)
))
My twig :
<img src="{{ asset('bundles/sonataadmin/famfamfam/delete.png') }}" />
It works.
Problem : I don't know why :S, since I've just copy/paste the code from somewhere.
I figured out than the '_action' determined the name of the column. But what if I want to change it ?
Where does this 'actions' name come from ? Where can I change it ?
The _action is used to add custom actions for the list items. Like edit and delete which are set by default. Here is a full documentation:
List actions
You can set actions for the list items by adding an ‘_action’ field in configureListFields:
<?php
$listMapper->add('_action', 'actions', array(
'actions' => array(
'view' => array(),
'edit' => array(),
)
))
Edit and delete actions are enabled in the default configuration. You can add your own! Default template file is: *SonataAdminBundle:CRUD:list_action[ACTION_NAME].html.twig*
You can specify your own by setting up the ‘template’ option like so:
<?php
$listMapper->add('_action', 'actions', array(
'actions' => array(
'view' => array(),
'edit' => array(),
'delete' => array('template' => 'MyBundle:MyController:my_partial.html.twig'),
)
))
I am developing a module for prestashop (basically, it's a very custom import of data and the only thing I need is to have a form and process data). I have created controller class derived from the ModuleAdminController but the problem is where should I put the tpl file containing the look of my custom form?
I realize that I can put tpl file to the templates but I want to keep all files within my module folder, is it possible (probably somewhere like "/views/templates/admin")?
This is the most easy method to create a basic admin controller / action in Prestashop 1.6
Create basic configuration :
./config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<module>
<name>foo</name>
<displayName><![CDATA[Foo]]></displayName>
<version><![CDATA[2.1.3]]></version>
<description><![CDATA[Bar.]]></description>
<author><![CDATA[your-name]]></author>
<tab><![CDATA[administration]]></tab>
<is_configurable>0</is_configurable>
<need_instance>0</need_instance>
<limited_countries></limited_countries>
</module>
./foo.php
if (!defined('_PS_VERSION_'))
exit;
class BarcodeEasyPrint extends Module
{
public function __construct()
{
$this->name = 'foo';
$this->tab = 'administration';
$this->version = '1.0.0';
$this->author = 'your-name-here';
$this->need_instance = 0;
$this->bootstrap = true;
parent::__construct();
$this->displayName = $this->l('Foo');
$this->description = $this->l('Bar.');
if ((int)Tools::getValue('p'))
$this->page = (int)Tools::getValue('p');
}
}
You need to create the controller with base functions :
./controllers/admin/AdminFooController.php
class AdminFooController extends ModuleAdminController {
public function __construct() {
$this->bootstrap = true;
parent::__construct();
}
public function createTemplate($tpl_name) {
if (file_exists($this->getTemplatePath() . $tpl_name) && $this->viewAccess())
return $this->context->smarty->createTemplate($this- >getTemplatePath() . $tpl_name, $this->context->smarty);
return parent::createTemplate($tpl_name);
}
public function initContent(){
parent::initContent();
$tpl = $this->createTemplate('content.tpl')->fetch();
/* DO STUFF HERE */
$posts = array();
$this->context->smarty->assign('posts', $posts);
}
}
You can use boostrap directly in the template file :
./views/templates/admin/content.tpl
<div class="row">
<div class="col-md-6">
</div>
<div class="col-md-6">
</div>
</div>
If it is an admin module only, then you will have no need to create any views. Because Prestashop provides a nice structure for admin section which is easy to use and we dont need to use any views or .tpl files. For admin section, normally three types of views or .tpl files are required, one for data display in grid, second for form and third for displaying a single record.
Prestashop already created .tpl files for them which you can find in "admin_folder/themes/default/templates". In our controllers for admin, for form and for data grid, we just create arrays and PS handles to view the form and data grid according to the arrays we created.
So if you need a custom form at admin, then create a public function renderForm and create the form array in it, like below:
$this->fields_form = array(
'legend' => array(
'title' => $this->l('Video'),
'image' => '../img/admin/tab-genders.gif'
),
'input' => array(
array(
'type' => 'text',
'label' => $this->l('Video Title:'),
'name' => 'title',
'lang' => true,
'size' => 70,
'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()##"�{}_$%:',
'required' => true
),
array(
'type' => 'textarea',
'label' => $this->l('Video Code'),
'name' => 'video_code',
'rows' => 5,
'cols' => 70,
'desc' => $this->l('Place the embed code for the video')
),
),
'submit' => array(
'title' => $this->l('Save'),
'class' => 'button'
)
);
return parent::renderForm();
} /* End of render member */
For other fields, checkout other prestashop admin controllers and you will see that how easily we can create forms in PS using that simple definitions in the arrays and we dont need to create .tpl files.
For front end, we can use the new modules MVC structure, where our module folder have sub folders for controllers (controllers/front, controllers/admin) , views and models .
Hope this will help you.
Thank you
You need to use the helper form, here is the documentation for it, it is really easy to use ;) .
http://doc.prestashop.com/display/PS15/HelperForm
You also can find more information about how and where to use helper form, look for the function getContent() and displayForm().
http://doc.prestashop.com/display/PS15/Creating+a+PrestaShop+module
unfortunately any document not exist to point directly to solve this question but hear i have some URLs really useful and you should combine theme and get your realize:
http://presthemes.com/prestashop-news/modules-classes-and-controller-override-by-julien-breux-4.html
http://doc.prestashop.com/display/PS15/Diving+into+PrestaShop+Core+development
http://doc.prestashop.com/display/PS15/New+Developers+Features+In+PrestaShop+1.5
http://blog.belvg.com/how-to-implement-a-controller.html
best regards
extending the answer from #altafhussain create a folder views/templates/admin in your module and place your customview.tpl
Than append the free text block as below.
$this->fields_form = array(
'legend' => array(
'title' => $this->l('Legend')
),
'input' => array(
array(
'type' => 'free',
'label' => 'Whatever label text',
'desc' => $this->display(__FILE__,'views/templates/admin/customview.tpl'),
'name' => 'FREE_TEXT',
'required' => false
)
),
'submit' => array(
'title' => $this->l('Save'),
'class' => 'button'
)
);
return parent::renderForm();
}
I found a comment here: http://bakery.cakephp.org/articles/PHPdiddy/2006/10/06/custom-urls-from-the-site-root
That said:
Just change last line.
Router::connect('/',
array('controller' => 'members',
'action' => 'show'));
to
Router::connect('(?!admin|items|images)(.*)',
array('controller' => 'members', 'action' => 'show'));
Some people were able to get that to work... It didn't look quite right to me though so I tried the following, but still had no luck:
Router::connect('(?!/admin|/items|/images)(/.*)',
array('controller' => 'members','action' => 'show'));
In any case, the goal is to have a url like http://domainname/username , map to a users unique id. It works with /*, but I rather not use that method. Ideas?
Update to solution:
I used the selected answer below and added the following. It may be helpful to someone else.
$misc = array(*your misc webroot, admin route items here...*);
$notList = array_merge(Configure::listObjects('plugin'),Configure::listObjects('controller'));
$notListLowerCase = array();
foreach ($notList as $key=>$item):
$notListLowerCase[] = strtolower(preg_replace("/(.)([A-Z])/","\\1_\\2",$item));
endforeach;
$notList = array_merge($notList,$misc,$notListLowerCase);
$notList = implode('|', $notList);
Router::connect('/:username',
array(
'controller'=>'users',
'action'=>'view'
),
array(
'username' => '\b(?:(?!'.$notList.')\w)+\b'
)
);
Here ya go. You need to capture it as a param and then reference it in the regex. The username will be available in $this->params['username'] in the controller action.
Router::connect('/:username',
array(
'controller'=>'members',
'action'=>'show'
),
array(
'username' => '\b(?:(?!admin|items|images)\w)+\b'
)
);
$misc = array(*your misc webroot, admin route items here...*);
$notList = array_merge(App::objects('plugin'),str_replace('Controller','',App::objects('controller')));
$notListLowerCase = array();
foreach ($notList as $key=>$item):
$notListLowerCase[] = strtolower(preg_replace("/(.)([A-Z])/","\\1_\\2",$item));
endforeach;
$notList = array_merge($notList,$misc,$notListLowerCase);
$notList = implode('|', $notList);
Router::connect('/:username', array('controller' => 'members', 'action' => 'show'),array('pass'=>array('username'),'username'=>'\b(?:(?!'.$notList.')\w)+\b'));