Doctrine 2 customize ObjectMultiCheckbox values - php

How can I custom values with DoctrineModule\Form\Element\ObjectMultiCheckbox?
I used Zend\Form\Element\MultiCheckbox and I set values like this:
$this->add(array(
'type' => 'Zend\Form\Element\MultiCheckbox',
'name' => 'countries',
'options' => array(
'label' => 'Select countries',
'value_options' => array(
'value' => 1,
'label' => 'United Kingdom',
'continent' => 'Europe'
)
)
))
But now I need to use Doctrine 2 Multicheckbox and I need to set custom value options. How can i do this?
I have currently only this:
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectMultiCheckbox',
'name' => 'countries',
'options' => array(
'object_manager' => $this->em,
'target_class' => 'Module\Entity\Country'
)
));
I need this for custom view render. I want to show countries like this:
Europe
- Sweden
- United Kingdom
- and others...
America
- Canada
- United States
- other countries...

SOLVED!
I created a new form element:
ObjectMultiCheckbox:
namespace Application\Form\Element;
use Zend\Form\Element\MultiCheckbox;
use Zend\Stdlib\ArrayUtils;
class ObjectMultiCheckbox extends MultiCheckbox
{
public function setValue($value)
{
if ($value instanceof \Traversable)
{
$value = ArrayUtils::iteratorToArray($value);
foreach ($value as $key => $row)
{
$values[] = $row->getId();
}
return parent::setValue($values);
}
elseif ($value == null)
{
return parent::setValue(array());
}
elseif (!is_array($value))
{
return parent::setValue((array)$value);
}
}
}
It's not really pretty, but it handle object to the form as DoctrineModule\Form\Element\ObjectMultiCheckbox.
My entity which using this code have always identifier 'id' so I can use static code as like this: $row->getId(); It's ugly, but it works!

Related

How to make username case insensitive in zf2

I used zf2 authentication for authenticate user in my project.I saved Harib in my user table as user name but if i use my user name Harib then its accept or if i use harib then its not accept,i want to remove case sensitivity of user name so both Harib or harib access how i fix this?
Here is my code:
public function loginAction()
{
$this->layout('layout/login-layout.phtml');
$login_error = false;
$loginForm = new LoginForm();
$form_elements = json_encode($loginForm->form_elements);
if ($this->request->isPost()) {
$post = $this->request->getPost();
$loginForm->setData($post);
if ($loginForm->isValid()) {
$hashed_string = '';
if(
array_key_exists('hashed_input' , $post) &&
$post['hashed_input'] != '' &&
strpos(urldecode($this->params('redirect')) , 'programdetailrequest') !== false
) {
$hashed_string = $post['hashed_input'];
}
$data = $loginForm->getData();
$authService = $this->getServiceLocator()->get('doctrine.authenticationservice.odm_default');
$adapter = $authService->getAdapter();
$adapter->setIdentityValue($data['username']);
$adapter->setCredentialValue(md5($data['password']));
$authResult = $authService->authenticate();
if($authResult->isValid()){
$identity = $authResult->getIdentity();
if( is_object($identity) && method_exists($identity, 'getData') ){
$user_data = $identity->getData();
$authService->getStorage()->write($identity);
// for remeber checkbox
if ($post['rememberme']) {
$token = new UserToken();
$dm = $this->getServiceLocator()->get('doctrine.documentmanager.odm_default');
//if same user already running from other browser then remove previous token.
$check_token = $dm->getRepository('Admin\Document\UserToken')->findOneBy(array( "user_id.id" => $user_data['id'] ));
if (is_object($check_token) && !is_null($check_token)) {
$remove_token = $dm->createQueryBuilder('Admin\Document\UserToken')
->remove()
->field('id')->equals($check_token->id)
->getQuery()->execute();
}
//create token
$user = $dm->getRepository('Admin\Document\User')->findOneBy(array( "id" => $user_data['id'] ));
$token->setProperty('user_id', $user);
$token->setProperty('dataentered', new \MongoDate());
$dm->persist($token);
$dm->flush($token);
//create cookie
if(is_object($token) && property_exists($token, 'id')){
$time = time() + (60 * 60 * 24 * 30); // 1 month
setcookie('token', $token->getProperty('id'), $time, '/');
}
}
if ($user_data['user_type'] == 'onlinemarketer') {
$this->redirect()->toRoute('admin_program_meta');
} elseif ($user_data['user_type'] == 'bucharestofficemanager') {
$this->redirect()->toRoute('admin_program_detail_request');
} else {
if ($this->params('redirect') && urldecode($this->params('redirect')) !== '/logout/') {
$server_url = $this->getRequest()->getUri()->getScheme() . '://' . $this->getRequest()->getUri()->getHost().urldecode($this->params('redirect') . $hashed_string);
return $this->redirect()->toUrl($server_url);
}
return $this->redirect()->toRoute('admin_index');
}
}
} else {
$identity = false;
$login_error = true;
}
}
}
return new ViewModel(array(
'loginForm' => $loginForm,
'form_elements' =>$form_elements,
'login_error' => $login_error,
));
}
and here is my login form code:
<?php
namespace Admin\Form;
use Zend\Form\Form;
use Zend\Form\Element;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\Factory as InputFactory;
class LoginForm extends Form implements InputFilterAwareInterface
{
protected $inputFilter;
public $form_elements = array(
array(
'name' => 'username',
'attributes' => array(
'id' => 'username',
'type' => 'text',
'error_msg' => 'Enter Valid Username',
'data-parsley-required' => 'true',
'data-parsley-pattern' => '^[a-zA-Z0-9_\.\-]{1,50}$',
'data-parsley-trigger' => 'change'
),
'options' => array(
'label' => 'User Name'
),
'validation' => array(
'required'=>true,
'filters'=> array(
array('name'=>'StripTags'),
array('name'=>'StringTrim')
),
'validators'=>array(
array('name'=>'Regex',
'options'=> array(
'pattern' => '/^[a-z0-9_.-]{1,50}+$/', // contain only a to z 0 to 9 underscore, hypen and space, min 1 max 50
'pattern_js' => '^[a-zA-Z0-9_\.\-]{1,50}$'
)
)
)
)
),
array(
'name' => 'password',
'attributes' => array(
'id' => 'password',
'type' => 'password',
'error_msg' => 'Enter Valid Password',
'data-parsley-required' => 'true',
'data-parsley-pattern' => '^[a-zA-Z0-9_\.\-]{6,25}$',
'data-parsley-trigger' => 'change'
),
'options' => array(
'label' => 'Password'
),
'validation' => array(
'required' => true,
'filters'=> array(
array('name'=>'StripTags'),
array('name'=>'StringTrim')
),
'validators'=>array(
array('name'=>'Regex',
'options'=> array(
'pattern' => '/^[a-z0-9_.-]{6,25}+$/', // contain only a to z 0 to 9 underscore, hypen and space, min 1 max 50
'pattern_js' => '^[a-zA-Z0-9_\.\-]{6,25}$'
)
)
)
)
),
array(
'name' => 'hashed_input',
'attributes' => array(
'type' => 'hidden',
'id' => 'hashed_input',
'value' => ''
)
),
array(
'name' => 'rememberme',
'attributes' => array(
'value' => 1,
'id' => 'rememberme',
'type' => 'Checkbox'
),
'options' => array(
'label' => 'Remember Me',
'use_hidden_element' => false,
)
),
array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Log in',
'id' => 'submitbutton'
)
)
);
public function __construct()
{
parent::__construct('user');
$this->setAttribute('method', 'post');
$this->setAttribute('data-parsley-validate', '');
$this->setAttribute('data-elements', json_encode($this->form_elements));
$this->setAttribute('autocomplete', 'off');
for($i=0;$i<count($this->form_elements);$i++){
$elements=$this->form_elements[$i];
$this->add($elements);
}
}
public function getInputFilter($action=false)
{
if(!$this->inputFilter){
$inputFilter = new InputFilter();
$factory = new InputFactory();
for($i=0;$i<count($this->form_elements);$i++){
if(array_key_exists('validation',$this->form_elements[$i])){
$this->form_elements[$i]['validation']['name']=$this->form_elements[$i]['name'];
$inputFilter->add($factory->createInput( $this->form_elements[$i]['validation'] ));
}
}
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
how we remove case sensitivity of user name so both Harib or harib accepted?
Add a filter StringToLower in your loginform on the element user_id.
For this, the class that defines your loginform must implement InputFilterProviderInterface and you must add in the getInputFilterSpecification method as follows :
public function getInputFilterSpecification()
{
return [
'username' => [
'name' => 'username',
'required' => true,
'filters' => [
'name' => 'StringToLower',
'name'=>'StripTags',
'name'=>'StringTrim'
],
validators => [
[
'name'=>'Regex',
'options'=> [
'pattern' => '/^[a-z0-9_.-]{1,50}+$/',
'pattern_js' => '^[a-zA-Z0-9_\.\-]{1,50}$'
]
]
]
],
'password' => [
'name' => 'password',
'required' => true,
'filters' => [
array('name'=>'StripTags'),
array('name'=>'StringTrim')
],
'validators' => [
[
'name'=>'Regex',
'options'=> [
'pattern' => '/^[a-z0-9_.-]{6,25}+$/',
'pattern_js' => '^[a-zA-Z0-9_\.\-]{6,25}$'
]
]
]
]
];
}
So you are assured that the value returned in the post is in lowercase.
Since you're using MongoDB, you could use a regex to get the user name from the database.
Suggestion 1:
In your example that would be:
db.stuff.find( { foo: /^bar$/i } );
Suggestion 2:
You can Use $options => i for case insensitive search. Giving some possible examples required for string match.
Exact case insensitive string
db.collection.find({name:{'$regex' : '^string$', '$options' : 'i'}})
Contains string
db.collection.find({name:{'$regex' : 'string', '$options' : 'i'}})
Start with string
db.collection.find({name:{'$regex' : '^string', '$options' : 'i'}})
End with string
db.collection.find({name:{'$regex' : 'string$', '$options' : 'i'}})
Doesn't Contains string
db.collection.find({name:{'$regex' : '^((?!string).)*$', '$options' : 'i'}})
More about regex in MongoDb here: https://docs.mongodb.com/manual/reference/operator/query/regex/index.html
You may do this in two ways. Either you may create a custom authentication adapter or override a method of the default authentication adapter. I recommend that override that method which is easier than creating custom adapter.
So here is the method CredentialTreatmentAdapter::authenticateCreateSelect(). If you look up around 94 line (of zf 2.5) of that method from zend-authentication component then you would find the following line.
$dbSelect->from($this->tableName)
->columns(['*', $credentialExpression])
// See the making of where clause
->where(new SqlOp($this->identityColumn, '=', $this->identity));
Here we are going to make our changes. Now lets override that method by extending Zend\Authentication\Adapter\DbTable. We would make a where clause which would search for both Harib or harib therefore. See the following extended CustomDbTable::class.
<?php
namespace Define\Your\Own\Namespace;
use Zend\Authentication\Adapter\DbTable;
class CustomDbTable extends DbTable
{
protected function authenticateCreateSelect()
{
// build credential expression
if (empty($this->credentialTreatment) || (strpos($this->credentialTreatment, '?') === false)) {
$this->credentialTreatment = '?';
}
$credentialExpression = new SqlExpr(
'(CASE WHEN ?' . ' = ' . $this->credentialTreatment . ' THEN 1 ELSE 0 END) AS ?',
array($this->credentialColumn, $this->credential, 'zend_auth_credential_match'),
array(SqlExpr::TYPE_IDENTIFIER, SqlExpr::TYPE_VALUE, SqlExpr::TYPE_IDENTIFIER)
);
// Here is the catch
$where = new \Zend\Db\Sql\Where();
$where->nest()
->equalTo($this->identityColumn, $this->identity)
->or
->equalTo($this->identityColumn, strtolower($this->identity))
->unnest();
// get select
$dbSelect = clone $this->getDbSelect();
$dbSelect->from($this->tableName)
->columns(array('*', $credentialExpression))
->where($where); // Here we are making our own where clause
return $dbSelect;
}
}
Now custom authentication adapter is ready. You need to use this one inside the factory for authentication service instead of Zend\Authentication\Adapter\DbTable as follows
'factories' => array(
// Auth service
'AuthService' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
// Use CustomDbTable instead of DbTable here
$customDbTable = new CustomDbTable($dbAdapter, 'tableName', 'usernameColumn', 'passwordColumn', 'MD5(?)');
$authService = new AuthenticationService();
$authService->setAdapter($customDbTable);
return $authService;
},
),
All are now set. That overridden method should be called whenever you call this one in your controller method:
$authResult = $authService->authenticate();
This is not tested. So you may need to change things where you need. Please fix those if needed.
Hope this would help you!

Ordering categories alphabetically in Prestashop top menu

I have set up a Prestashop 1.7 website for a client and I'm importing his new products with a script every day. These products are put in categories that I create if they don't yet exist. My problem is that the newly created categories are put at the end of the drop down top menu, and it would be much better to have them displayed alphabetically. I know I can do that in the back office by drag and dropping them in place, but I want my script to do it automatically.
I've already overriden the Category.phpclass to make other changes so I can edit this file. I tried to change every ORDER BY clauses I found from depth or position to name. It had some effects as categories were indeed sorted by name but a lot of them simply disappeared from the menu (i.e. out of say 10 categories sorted by position, only 4 remained sorted by name).
Do you know a way to achieve this?
You can do this 2 ways.
My approach is to do this when the menu is created, this way it's sorted in every language. To do so, just use this override for ps_mainmenu module:
use PrestaShop\PrestaShop\Core\Module\WidgetInterface;
class Ps_MainMenuOverride extends Ps_MainMenu implements WidgetInterface
{
protected function generateCategoriesMenu($categories, $is_children = 0)
{
$categories = $this->sortCategories($categories);
return parent::generateCategoriesMenu($categories, $is_children);
}
public function sortCategories($categories)
{
uasort($categories, 'cmpcat');
foreach($categories as $k => $category)
{
if (isset($category['children']) && !empty($category['children'])) {
$children = $this->sortCategories($category['children']);
$categories[$k]['children'] = $children;
}
}
return $categories;
}
}
function cmpcat($a, $b) {
return strcmp($a['name'], $b['name']);
}
The other option is to sort when creating the menu. But I would have to see the current import code, and even then could be more difficult.
This is for the children categories. For the main categories it would be necessary to override another function.
The problem is the query, if, for example, the child category name starts with a and parent with b, prestashop doesn't show it, you must add a primary "order by", in this case: level_depth.
I hope my override code will be useful:
use PrestaShop\PrestaShop\Core\Module\WidgetInterface;
class Ps_MainMenuOverride extends Ps_MainMenu implements WidgetInterface
{
protected function makeMenu()
{
$root_node = $this->makeNode([
'label' => null,
'type' => 'root',
'children' => []
]);
$menu_items = $this->getMenuItems();
$id_lang = (int)$this->context->language->id;
$id_shop = (int)Shop::getContextShopID();
foreach ($menu_items as $item) {
if (!$item) {
continue;
}
preg_match($this->pattern, $item, $value);
$id = (int)substr($item, strlen($value[1]), strlen($item));
switch (substr($item, 0, strlen($value[1]))) {
case 'CAT':
$categories = $this->generateCategoriesMenu(
Category::getNestedCategories($id, $id_lang, false, $this->user_groups,true,'',' ORDER BY c.`level_depth`,cl.`name` ASC ')
);
$root_node['children'] = array_merge($root_node['children'], $categories);
break;
case 'PRD':
$product = new Product((int)$id, true, (int)$id_lang);
if ($product->id) {
$root_node['children'][] = $this->makeNode([
'type' => 'product',
'page_identifier' => 'product-' . $product->id,
'label' => $product->name,
'url' => $product->getLink(),
]);
}
break;
case 'CMS':
$cms = CMS::getLinks((int)$id_lang, array($id));
if (count($cms)) {
$root_node['children'][] = $this->makeNode([
'type' => 'cms-page',
'page_identifier' => 'cms-page-' . $id,
'label' => $cms[0]['meta_title'],
'url' => $cms[0]['link']
]);
}
break;
case 'CMS_CAT':
$root_node['children'][] = $this->generateCMSCategoriesMenu((int)$id, (int)$id_lang);
break;
// Case to handle the option to show all Manufacturers
case 'ALLMAN':
$children = array_map(function ($manufacturer) use ($id_lang) {
return $this->makeNode([
'type' => 'manufacturer',
'page_identifier' => 'manufacturer-' . $manufacturer['id_manufacturer'],
'label' => $manufacturer['name'],
'url' => $this->context->link->getManufacturerLink(
new Manufacturer($manufacturer['id_manufacturer'], $id_lang),
null,
$id_lang
)
]);
}, Manufacturer::getManufacturers());
$root_node['children'][] = $this->makeNode([
'type' => 'manufacturers',
'page_identifier' => 'manufacturers',
'label' => $this->trans('All brands', array(), 'Modules.Mainmenu.Admin'),
'url' => $this->context->link->getPageLink('manufacturer'),
'children' => $children
]);
break;
case 'MAN':
$manufacturer = new Manufacturer($id, $id_lang);
if ($manufacturer->id) {
$root_node['children'][] = $this->makeNode([
'type' => 'manufacturer',
'page_identifier' => 'manufacturer-' . $manufacturer->id,
'label' => $manufacturer->name,
'url' => $this->context->link->getManufacturerLink(
$manufacturer,
null,
$id_lang
)
]);
}
break;
// Case to handle the option to show all Suppliers
case 'ALLSUP':
$children = array_map(function ($supplier) use ($id_lang) {
return $this->makeNode([
'type' => 'supplier',
'page_identifier' => 'supplier-' . $supplier['id_supplier'],
'label' => $supplier['name'],
'url' => $this->context->link->getSupplierLink(
new Supplier($supplier['id_supplier'], $id_lang),
null,
$id_lang
)
]);
}, Supplier::getSuppliers());
$root_node['children'][] = $this->makeNode([
'type' => 'suppliers',
'page_identifier' => 'suppliers',
'label' => $this->trans('All suppliers', array(), 'Modules.Mainmenu.Admin'),
'url' => $this->context->link->getPageLink('supplier'),
'children' => $children
]);
break;
case 'SUP':
$supplier = new Supplier($id, $id_lang);
if ($supplier->id) {
$root_node['children'][] = $this->makeNode([
'type' => 'supplier',
'page_identifier' => 'supplier-' . $supplier->id,
'label' => $supplier->name,
'url' => $this->context->link->getSupplierLink(
$supplier,
null,
$id_lang
)
]);
}
break;
case 'SHOP':
$shop = new Shop((int)$id);
if (Validate::isLoadedObject($shop)) {
$root_node['children'][] = $this->makeNode([
'type' => 'shop',
'page_identifier' => 'shop-' . $id,
'label' => $shop->name,
'url' => $shop->getBaseURL(),
]);
}
break;
case 'LNK':
$link = Ps_MenuTopLinks::get($id, $id_lang, $id_shop);
if (!empty($link)) {
if (!isset($link[0]['label']) || ($link[0]['label'] == '')) {
$default_language = Configuration::get('PS_LANG_DEFAULT');
$link = Ps_MenuTopLinks::get($link[0]['id_linksmenutop'], $default_language, (int)Shop::getContextShopID());
}
$root_node['children'][] = $this->makeNode([
'type' => 'link',
'page_identifier' => 'lnk-' . Tools::str2url($link[0]['label']),
'label' => $link[0]['label'],
'url' => $link[0]['link'],
'open_in_new_window' => $link[0]['new_window']
]);
}
break;
}
}
return $this->mapTree(function ($node, $depth) {
$node['depth'] = $depth;
return $node;
}, $root_node);
}
}

magento saveAction - for beginners

I am a Magento beginner so please bear with me...
I am creating a simple extension for my site to add a custom field to my Tags in adminhtml. The custom field is just a number which I need to identify a specific Z-block (cms block extension) so that I can access it as a widget and show it on the frontend in the Tag "category".
I have created a custom module which is working: I set a field in the form using $fieldset and have extended TagController.php, both of which are being used (I made a simple trial to see whether or not they had been recognized). However, I do not know how to go about saving my custom field to DB (whether amending saveAction is enough, and I haven't done it properly, or if I need to add a custom Model or sql install).
Sorry for the "basic" question but I'm new at this, and have mostly done frontend dev (so my extension knowledge is simply limited).
Thank you to anyone who can help...
Claudia
NEW TAG FORM:
public function __construct()
{
parent::__construct();
$this->setId('tag_form');
$this->setTitle(Mage::helper('tag')->__('Block Information'));
}
/**
* Prepare form
*
* #return Mage_Adminhtml_Block_Widget_Form
*/
protected function _prepareForm()
{
$model = Mage::registry('tag_tag');
$form = new Varien_Data_Form(
array('id' => 'edit_form', 'action' => $this->getData('action'), 'method' => 'post')
);
$fieldset = $form->addFieldset('base_fieldset',
array('legend'=>Mage::helper('tag')->__('General Information')));
if ($model->getTagId()) {
$fieldset->addField('tag_id', 'hidden', array(
'name' => 'tag_id',
));
}
$fieldset->addField('form_key', 'hidden', array(
'name' => 'form_key',
'value' => Mage::getSingleton('core/session')->getFormKey(),
));
$fieldset->addField('store_id', 'hidden', array(
'name' => 'store_id',
'value' => (int)$this->getRequest()->getParam('store')
));
$fieldset->addField('name', 'text', array(
'name' => 'tag_name',
'label' => Mage::helper('tag')->__('Tag Name'),
'title' => Mage::helper('tag')->__('Tag Name'),
'required' => true,
'after_element_html' => ' ' . Mage::helper('adminhtml')->__('[GLOBAL]'),
));
$fieldset->addField('zblock', 'text', array(
'name' => 'zblock_id',
'label' => Mage::helper('tag')->__('Z-Block Id'),
'title' => Mage::helper('tag')->__('Z-Block Id'),
'required' => true,
'after_element_html' => ' ' . Mage::helper('adminhtml')->__('[GLOBAL]'),
));
$fieldset->addField('status', 'select', array(
'label' => Mage::helper('tag')->__('Status'),
'title' => Mage::helper('tag')->__('Status'),
'name' => 'tag_status',
'required' => true,
'options' => array(
Mage_Tag_Model_Tag::STATUS_DISABLED => Mage::helper('tag')->__('Disabled'),
Mage_Tag_Model_Tag::STATUS_PENDING => Mage::helper('tag')->__('Pending'),
Mage_Tag_Model_Tag::STATUS_APPROVED => Mage::helper('tag')->__('Approved'),
),
'after_element_html' => ' ' . Mage::helper('adminhtml')->__('[GLOBAL]'),
));
$fieldset->addField('base_popularity', 'text', array(
'name' => 'base_popularity',
'label' => Mage::helper('tag')->__('Base Popularity'),
'title' => Mage::helper('tag')->__('Base Popularity'),
'after_element_html' => ' ' . Mage::helper('tag')->__('[STORE VIEW]'),
));
if (!$model->getId() && !Mage::getSingleton('adminhtml/session')->getTagData() ) {
$model->setStatus(Mage_Tag_Model_Tag::STATUS_APPROVED);
}
if ( Mage::getSingleton('adminhtml/session')->getTagData() ) {
$form->addValues(Mage::getSingleton('adminhtml/session')->getTagData());
Mage::getSingleton('adminhtml/session')->setTagData(null);
} else {
$form->addValues($model->getData());
}
$this->setForm($form);
return parent::_prepareForm();
}
NEW CONTROLLER:
public function saveAction()
{
if ($postData = $this->getRequest()->getPost()) {
if (isset($postData['tag_id'])) {
$data['tag_id'] = $postData['tag_id'];
}
$data['name'] = trim($postData['tag_name']);
$data['zblock'] = $postData['zblock_id'];
$data['status'] = $postData['tag_status'];
$data['base_popularity'] = (isset($postData['base_popularity'])) ? $postData['base_popularity'] : 0;
$data['store'] = $postData['store_id'];
if (!$model = $this->_initTag()) {
Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Wrong tag was specified.'));
return $this->_redirect('*/*/index', array('store' => $data['store']));
}
$model->addData($data);
if (isset($postData['tag_assigned_products'])) {
$productIds = Mage::helper('adminhtml/js')->decodeGridSerializedInput(
$postData['tag_assigned_products']
);
$model->setData('tag_assigned_products', $productIds);
}
try {
$model->save();
Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('The tag has been saved.'));
Mage::getSingleton('adminhtml/session')->setTagData(false);
if (($continue = $this->getRequest()->getParam('continue'))) {
return $this->_redirect('*/tag/edit', array('tag_id' => $model->getId(), 'store' => $model->getStoreId(), 'ret' => $continue));
} else {
return $this->_redirect('*/tag/' . $this->getRequest()->getParam('ret', 'index'));
}
} catch (Exception $e) {
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
Mage::getSingleton('adminhtml/session')->setTagData($data);
return $this->_redirect('*/*/edit', array('tag_id' => $model->getId(), 'store' => $model->getStoreId()));
}
}
return $this->_redirect('*/tag/index', array('_current' => true));
}
The custom field I'm trying to add is "zblock"...thanks and, again, bear with me! :)
First add the field in database table.
For example if you want to add in your custom table.
ALTER TABLE myCustomModuleTable ADD COLUMN 'myCustomField' int(10);
Thenafter, In your controller action take the model object of that table and set the field.
If you are adding data in existing table row:
$value = 6;
$rowInWhichIWantToSave = Mage:getModel('companyname/modulename')->load($rowId);
$rowInWhichIWantToSave->setData('myCustomField',$value)->save();
If you are adding a new row:
$value = 6;
$rowInWhichIWantToSave = Mage:getModel('companyname/modulename');
$rowInWhichIWantToSave->setData('myCustomField',$value)->save();
Hope this helps!!

php for loop on an object -zendform 2 forms

I am trying to retrieve data (a dependency) from a database and use the returned values to populate a zend form select element.
The final values should look like below:
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'jobId',
'options' => array(
'label' => 'countryList',
'value_options' => array(
'1'=>'USA',
'2'=> 'United Kingdom',
etc
'
),
),
'attributes' => array(
'value' => '1' //set selected to '1'
)
));
I have used doctrine2 to retrieve the values, i.e:
public function getOptionsForSelect()
{
$entity = $this->getEntityManager()
->getRepository('Workers\Entity\CountryList')
->findAll();
foreach ($entity as $entity)
{
echo $entity->country;
echo $entity->id;
}
}
The above gives me all the required values. I am however stuck on how to then place these values into an array such that once the $this->getOptionsForSelect() is placed in the form, it will immediately populate the values;
i.e.
foreach ($entity as $entity)
{
$id = $entity->id;
$country= $entity->country;
$data['data'] = $id.'=>'.$country;
}
return $data;
The final version of the form field will look like below:
$this->add(array(
'name' => 'countrylist',
'type' => 'Zend\Form\Element\Select',
'options' => array(
'label' => 'countrylist',
'value_options' => $this->getOptionsForSelect(),
'empty_option' => '--- please choose ---'
)
));
There is ObjectSelect/EntitySelect in DoctrineModule for ZF2 which might simplify this - https://github.com/doctrine/DoctrineModule/blob/master/docs/form-element.md
You don't need your own getOptionsForSelect(), because doctrine can handle that already.
If I understood you correctly, you could implement your getOptionsForSelect like so:
public function getOptionsForSelect()
{
$entity = $this->getEntityManager()
->getRepository('Workers\Entity\CountryList')
->findAll();
$options = array();
foreach ($entity as $entity) {
$options[$entity->id] = $entity->country;
}
return $options;
}
I haven't worked with doctrine, but I'd expect it to have some method to extract data as an array, or at least that I'd be possible to pass it to some serialized object to do that.

Filtering CGridView with CArrayDataProvider in Yii: how?

I created a CGridView in Yii whose rows are read from an XML file. I'm not using any models: only a controller (where I read the file) and a view (where I display the grid). What I cannot create is a filter (one input field per column) in the first row of the grid so to visualize only certain rows. How can I do it?
This is what I have until now:
Controller:
<?php
class TestingController extends Controller {
public function actionIndex() {
$pathToTmpFiles = 'public/tmp';
$xmlResultsFile = simplexml_load_file($pathToTmpFiles.'/test.xml');
$resultData = array();
foreach ($xmlResultsFile->result as $entry) {
$chromosome = $entry->chromosome;
$start = $entry->start;
$end = $entry->end;
$strand = $entry->strand;
$crosslinkScore = $entry->crosslinkScore;
$rank = $entry->rank;
$classification = $entry->classification;
$mutation = $entry->mutation;
$copies = $entry->copies;
array_push($resultData, array('Chromosome'=>$chromosome, \
'Start'=>$start, 'End'=>$end, Strand'=>$strand, \
'Crosslink_Score'=>$crosslinkScore,'Rank'=>$rank, \
'Classification'=>$classification, 'Mutation'=>$mutation, \
'Copies'=>$copies));
}
$this->render('index', array('resultData' => $resultData));
}
}
?>
View:
<?php
$dataProvider = new CArrayDataProvider($resultData, \
array('pagination'=>array('pageSize'=>10,),));
$this->widget('zii.widgets.grid.CGridView', array( 'id' => 'mutationResultsGrid',
'dataProvider' => $dataProvider, 'columns' => array(
array(
'name' => 'Chromosome',
'type' => 'raw',
),
array(
'name' => 'Start',
'type' => 'raw',
),
array(
'name' => 'End',
'type' => 'raw',
),
array(
'name' => 'Strand',
'type' => 'raw',
),
array(
'name' => 'Crosslink_Score',
'type' => 'raw',
),
array(
'name' => 'Rank',
'type' => 'raw',
),
array(
'name' => 'Classification',
'type' => 'raw',
),
array(
'name' => 'Mutation',
'type' => 'raw',
),
array(
'name' => 'Copies',
'type' => 'raw',
),
),
));
?>
Thanks for your help
Ale
file: FiltersForm.php (I put it in components folder)
/**
* Filterform to use filters in combination with CArrayDataProvider and CGridView
*/
class FiltersForm extends CFormModel
{
public $filters = array();
/**
* Override magic getter for filters
*/
public function __get($name)
{
if(!array_key_exists($name, $this->filters))
$this->filters[$name] = null;
return $this->filters[$name];
}
/**
* Filter input array by key value pairs
* #param array $data rawData
* #return array filtered data array
*/
public function filter(array $data)
{
foreach($data AS $rowIndex => $row) {
foreach($this->filters AS $key => $value) {
// unset if filter is set, but doesn't match
if(array_key_exists($key, $row) AND !empty($value)) {
if(stripos($row[$key], $value) === false)
unset($data[$rowIndex]);
}
}
}
return $data;
}
}
In your controller:
...
$filtersForm = new FiltersForm;
if (isset($_GET['FiltersForm'])) {
$filtersForm->filters = $_GET['FiltersForm'];
}
$resultData = $filtersForm->filter($resultData);
$this->render('index', array(
'resultData' => $resultData,
'filtersForm' => $filtersForm
)}//end action
And last what need - add filters to CGridView config array:
...
'dataProvider' => $dataProvider,
'enableSorting' => true,
'filter' => $filtersForm,
...
Why don't you store the information from the xml to a database and use YII ActiveRecord?
In your case you would need a live mechanism to filter the resultset on every filter query. Like with the search() method, when you use YII ActiveRecord models.
So you could use something like array_filter() with callback on your array on every filter call. (Edit: or the mechanism used here with stripos to return the matching "rows": Yii Wiki)
Or, second option, you could make the xml parser dependend on your filter inputs, which does not feel good to me :). The parser would habe to parse on every filter input, which could be a problem with big xml files.
Or, as mentioned, save the information to the database and use standard YII mechanisms.
Assuming you can use the data obtained in the objects in your foreach loop as the filter for that particular column, you could then pass these values through to the view, something like:
<?php
class TestingController extends Controller {
public function actionIndex() {
$pathToTmpFiles = 'public/tmp';
$xmlResultsFile = simplexml_load_file($pathToTmpFiles.'/test.xml');
$resultData = array();
foreach ($xmlResultsFile->result as $entry) {
...
$chromosomeFilter[] = $entry->chromosome;
...
}
$this->render('index', array(
'resultData' => $resultData,
'chromosomeFilter' => $chromosomeFilter,
...
);
}
}
?>
And then use that value in the filter for that column;
...
array(
'name' => 'Chromosome',
'type' => 'raw',
'filter' => $chromosomeFilter,
),
...
I've not tested, and it depends a lot on the structure of your xml and $entry->chromosome, but that might help put you on the right path?
I had the same problem
and what I did was I implement http://www.datatables.net/
And pull the data remotely . I pass the sorting and pagination to javascript .

Categories