Prestashop 1.7.8.2 add country in registration form - forms

i need to add a select with defined in admin countries to a prestashop registration form.
Any hint on how to do this?
Simple prestashop 1.7.8.2
Was searching the web, but no strict answers.

You can use additionalCustomerFormFields hook that is placed inside CustomerFormatter class.
Example usage:
https://github.com/PrestaShop/ps_emailsubscription/blob/dev/ps_emailsubscription.php#L1005

Well, i managed to sort it out myself also by:
Adding select with countries that are added to Presta in file /override/classes/form/CustomerFormatter.php
$countries = Country::getCountries((int)$this->language->id, true, false, false);
if (count($countries) > 0) {
$countryField = (new FormField)
->setName('id_country')
->setType('countrySelect')
->setLabel($this->translator->trans('Country', [], 'Shop.Forms.Labels'))
->setRequired(true);
foreach ($countries as $country) {
$countryField->addAvailableValue(
$country['id_country'],
$country['country']
);
}
$format[$countryField->getName()] = $countryField;
}
Adding to file /override/classes/AuthController.php right below:
if ($hookResult && $register_form->submit()) {
this code:
//address saving
$customer = new Customer();
$customer = $customer->getByEmail($register_form->getCustomer()->email);
$address = new Address(
null,
$this->context->language->id
);
$address->id_country = (int) Tools::getCountry();
$address->address1 = Tools::getValue('address1');
$address->postcode = Tools::getValue('postcode');
$address->city = Tools::getValue('city');
$address->phone = Tools::getValue('phone');
$address->firstname = $customer->firstname;
$address->lastname = $customer->lastname;
$address->id_customer = (int) $customer->id;
$address->id_state = 0;
$address->alias = $this->trans('My Address', [], 'Shop.Theme.Checkout');
if($address->save()){
$should_redirect = true;
} else {
$customer->delete();
$this->errors[] = $this->trans('Could not update your information, please check your data.', array(), 'Shop.Notifications.Error');
$this->redirectWithNotifications($this->getCurrentURL());
}
}
The above code is responsible to add new address within provided data. In My case additional is only country, but if You want to add more address data the fields should be added again in CustomerFormatter.php
Credits for several parts of the code:
https://prestapros.com/en/blog/additional-fields-for-registration-form-prestashop-1-7
And:
https://www.prestashop.com/forums/topic/621262-prestashop-17-add-address-in-registration-form/?do=findComment&comment=3380394
Cheers!

Related

How to get Filterable Attributes from a category in Magento 2

I have created category "Bag" in Magento 2. having filter attribute:
color
Size
I'm trying to get Filterable Attributes from category "Bag".
I have already done this in Magento 1.9:
Mage::app()->setCurrentStore($store);
$layer = Mage::getModel("catalog/layer");
$category = Mage::getModel("catalog/category")->load($categoryid);
$layer->setCurrentCategory($category);
$attributes = $layer->getFilterableAttributes();
But it does not seem to work for 2.x
I faced the same problem recently.
I documented my investigation here.
I was not able to find framework api to provide filterable attributes for specific category, however I will share workarounds.
Basically all filterable attributes in Magento 2 can be retrived from FilterableAttributeList:
$filterableAttributes = ObjectManager::getInstance()->get(\Magento\Catalog\Model\Layer\Category\FilterableAttributeList::class);
$attributes = $filterableAttributes->getList();
Please use DI instead of ObjectManager::getInstance(). I used it just to have more compact example :)
Retrieving filters involved in layered navigation is a bit more tricky.
$filterableAttributes = ObjectManager::getInstance()->get(\Magento\Catalog\Model\Layer\Category\FilterableAttributeList::class);
$appState = ObjectManager::getInstance()->get(\Magento\Framework\App\State::class);
$layerResolver = ObjectManager::getInstance()->get(\Magento\Catalog\Model\Layer\Resolver::class);
$filterList = ObjectManager::getInstance()->create(
\Magento\Catalog\Model\Layer\FilterList::class,
[
'filterableAttributes' => $filterableAttributes
]
);
$category = 1234;
$appState->setAreaCode('frontend');
$layer = $layerResolver->get();
$layer->setCurrentCategory($category);
$filters = $filterList->getFilters($layer);
However, this is not the final result. To be sure that filters are actual, it is required to check number of items for each filters. (that check is actually performed during core layered navigation rendering)
$finalFilters = [];
foreach ($filters as $filter) {
if ($filter->getItemsCount()) {
$finalFilters[] = $filter;
}
}
Then you can get filter names and values. ie:
$name = $filter->getName();
foreach ($filter->getItems() as $item) {
$value = $item->getValue();
}
Finally, I would like to add alternative solution, that is a bit brutal, thought :)
$categoryId = 1234;
$resource = ObjectManager::getInstance()->get(\Magento\Framework\App\ResourceConnection::class);
$connection = $resource->getConnection();
$select = $connection->select()->from(['ea' => $connection->getTableName('eav_attribute')], 'ea.attribute_id')
->join(['eea' => $connection->getTableName('eav_entity_attribute')], 'ea.attribute_id = eea.attribute_id')
->join(['cea' => $connection->getTableName('catalog_eav_attribute')], 'ea.attribute_id = cea.attribute_id')
->join(['cpe' => $connection->getTableName('catalog_product_entity')], 'eea.attribute_set_id = cpe.attribute_set_id')
->join(['ccp' => $connection->getTableName('catalog_category_product')], 'cpe.entity_id = ccp.product_id')
->where('cea.is_filterable = ?', 1)
->where('ccp.category_id = ?', $categoryId)
->group('ea.attribute_id');
$attributeIds = $connection->fetchCol($select);
Then it is possible to use attribute ids to load collection.
/** #var $collection \Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection */
$collection = $this->collectionFactory->create();
$collection->setItemObjectClass('Magento\Catalog\Model\ResourceModel\Eav\Attribute')
->addStoreLabel($this->storeManager->getStore()->getId());
$collection->addFieldToFilter('attribute_id', ['in' => $attributeIds]);
If you know how to build module then you can take help from 'FiltersProvider.php' from 'module-catalog-graph-ql\Model\Resolver\Layer'.
use Magento\Catalog\Model\Layer\Category\FilterableAttributeList as CategoryFilterableAttributeList;
use Magento\Catalog\Model\Layer\FilterListFactory;
use Magento\Catalog\Model\Layer\Resolver;
use Magento\Framework\UrlInterface;
public function __construct(
Resolver $layerResolver,
FilterListFactory $filterListFactory,
CategoryFilterableAttributeList $categoryFilterableAttributeList,
UrlInterface $urlBuilder
) {
$this->_navigation = $navigation;
$this->layerResolver = $layerResolver;
$this->filterListFactory = $filterListFactory;
$this->urlBuilder = $urlBuilder;
$this->_categoryFilterableAttributeList = $categoryFilterableAttributeList;
}
public function getCatMenu($catid)
{
$fill_arr = [];
$filterList = $this->filterListFactory->create(['filterableAttributes' => $this->_categoryFilterableAttributeList]);
$layer = clone $this->layerResolver->get();
$layer->setCurrentCategory($catid);
$filters = $filterList->getFilters($layer);
return $fill_arr;
}

Hide Bundle Product if one of the Children is outofstock

how can i filter product collection so it will return the collection which does not contain bundle product whose one of children is Out of stock.
Got the solution for my question
$collection = Mage::getResourceModel('catalog/product_collection');
$bundled_items = array();
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection);
foreach ($collection->getAllIds() as $proId)
{
$bundled_product=Mage::getModel('catalog/product')->load($proId);
if($bundled_product->getTypeId()=="bundle")
{
$selectionCollection = $bundled_product->getTypeInstance(true)->getSelectionsCollection(
$bundled_product->getTypeInstance(true)->getOptionsIds($bundled_product), $bundled_product
);
foreach($selectionCollection as $option)
{
$product = Mage::getModel('catalog/product')->load($option->getProductId());
$stockItem = $product->getStockItem();
if($product->stock_item->is_in_stock == 0)
{
$bundled_items[] = $proId;
}
}
}
}
if(isset($bundled_items) && !empty($bundled_items))
{
$collection->addFieldToFilter('entity_id',array( 'nin' => array_unique($bundled_items)));
}
Alternate answer
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection);
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection);
$otherProductIds = $collection->getAllIds();
//get only bundle
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToFilter('type_id','bundle');
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection);
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection);
$bundleIds = $collection->getAllIds();
//checking bundle associate product stock status
$readAdapter = Mage::getSingleton('core/resource')->getConnection('core_read');
$select = $readAdapter->select()
->from(array('css'=> Mage::getSingleton('core/resource')->getTableName('cataloginventory/stock_status')),array())
->join(
array('bs'=> Mage::getSingleton('core/resource')->getTableName('bundle/selection')),
'bs.product_id = css.product_id',
array('parent_product_id')
)
->where('bs.parent_product_id IN (?)',$bundleIds)
->where('css.stock_status = 0')
->group('bs.parent_product_id');
$excludeBundleIds = $readAdapter->fetchCol($select);//return outstock associated products parent ids
$allIds = array_merge($otherProductIds, array_diff($bundleIds,$excludeBundleIds));
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToFilter('entity_id',array( 'in' => $allIds))
->addMinimalPrice()
->addFinalPrice();
return $collection
Hope this will helpful

Emails are not send to the user

I have a problem with sending emails with raports. I am create some data, and then try to send it as an email to the user. But emails are not deliwered. I am using swiftmailer configured as in the Symfony cookbool. Parameters for the swiftmailer are set properly because emails from FosUserBundle are working without problems. I have write a method to use it in comand line, the code is below
class DailyRaportCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
->setName('raport:daily')
->setDescription('Send daily raports to the Users');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$em = $this->getContainer()->get('doctrine')->getEntityManager();
$users = $em->getRepository('GLUserBundle:User')->findAllByRaport('DAILY');
foreach($users as $user)
{
$date_to = new \DateTime();
$date_to = $date_to->sub(date_interval_create_from_date_string('1 day'));
$date_from = new \DateTime();
$date_from = $date_from->sub(date_interval_create_from_date_string('1 day'));
$format = "Y-m-d";
$raport = array();
foreach($user->getShops() as $shop)
{
$raport[$shop->getName()] = array();
$shop_list = array();
$shop_list[] = $shop->getId();
$groupBy = array();
$all_policies = $em->getRepository('GLPolicyBundle:Policy')
->findAllByOptions($shop_list, $date_from, $date_to, $groupBy);
$raport[$shop->getName()]['all'] = $all_policies;
$groupBy[] = 'typePolicy';
$policies_by_type = $em->getRepository('GLPolicyBundle:Policy')
->findAllByOptions($shop_list, $date_from, $date_to, $groupBy);
$raport[$shop->getName()]['type'] = $policies_by_type;
$groupBy[] = 'bundle';
$policies_by_bundle = $em->getRepository('GLPolicyBundle:Policy')
->findAllByOptions($shop_list, $date_from, $date_to, $groupBy);
$raport[$shop->getName()]['bundle'] = $policies_by_bundle;
}
$message = \Swift_Message::newInstance()
->setSubject('Dzienny raport sprzedaży')
->setFrom('g#######1#gmail.com')
->setTo($user->getEmail())
->setBody(
$this->getContainer()->get('templating')->render(
'GLRaportBundle:Raport:raport.html.twig',
array('raport' => $raport)
));
$this->getContainer()->get('mailer')->send($message);
}
The wiev of the email is rendered in outside twig file. I will be grateful if someone point whots the reason of this problem.
You might need to manually flush the memory spool, see the following answer which helped me with the same problem:
Unable to send e-mail from within custom Symfony2 command but can from elsewhere in app

Jomsocial Extra Field

I am trying to create extra fields on the Jomsocial Groups Create New Group page, its suggested on the Jomsocial docs that the best way is to creat a plugin to do this.
As I have never created such a complex plugin do anyone have a working example to start with?
Here is the code that I have tried with
<?php
defined('_JEXEC') or die('Restricted access');
if (! class_exists ( 'plgSpbgrouppostcode' )) {
class plgSpbgrouppostcode extends JPlugin {
/**
* Method construct
*/
function plgSystemExample($subject, $config) {
parent::__construct($subject, $config);
// JPlugin::loadLanguage ( 'plg_system_example', JPATH_ADMINISTRATOR ); // only use if theres any language file
include_once( JPATH_ROOT .'/components/com_community/libraries/core.php' ); // loading the core library now
}
function onFormDisplay( $form_name )
{
/*
Add additional form elements at the bottom privacy page
*/
$elements = array();
if( $form_name == 'jsform-groups-forms' )
{
$obj = new CFormElement();
$obj->label = 'Labe1 1';
$obj->position = 'after';
$obj->html = '<input name="custom1" type="text">';
$elements[] = $obj;
$obj = new CFormElement();
$obj->label = 'Labe1 2';
$obj->position = 'after';
$obj->html = '<input name="custom2" type="text">';
$elements[] = $obj;
}
return $elements;

Zend_Form_Element fails when i addElements

I have been having trouble adding a hidden zend form element.
when i invoke addElements the form fails and prints the following error to the page.
but only when i try and add $formContactID and $formCustomerID.
Fatal error: Call to a member function getOrder() on a non-object in /home/coder123/public_html/wms2/library/Zend/Form.php on line 3291
My code is as follows.
private function buildForm()
{
$Description = "";
$FirstName = "";
$LastName = "";
$ContactNumber = "";
$Fax = "";
$Position = "";
$Default = "";
$custAddressID = "";
$CustomerID = "";
$Email = "";
$ContactID = "";
if($this->contactDetails != null)
{
$Description = $this->contactDetails['Description'];
$CustomerID = $this->contactDetails['CustomerID'];
$FirstName = $this->contactDetails['FirstName'];
$LastName = $this->contactDetails['LastName'];
$ContactNumber = $this->contactDetails['ContactNumber'];
$Position = $this->contactDetails['Position'];
$Fax = $this->contactDetails['Fax'];
$Email = $this->contactDetails['Email'];
$Default = $this->contactDetails['Default'];
$custAddressID = $this->contactDetails['custAddressID'];
$ContactID = $this->contactDetails['custContactID'];
}
$formfirstname = new Zend_Form_Element_Text('FirstName');
$formfirstname->setValue($FirstName)->setLabel('First Name:')->setRequired();
$formlastname = new Zend_Form_Element_Text('LastName');
$formlastname->setLabel('Last Name:')->setValue($LastName)->setRequired();
$formPhone = new Zend_Form_Element_Text('ContactNumber');
$formPhone->setLabel('Phone Number:')->setValue($ContactNumber)->setRequired();
$formFax = new Zend_Form_Element_Text('FaxNumber');
$formFax->setLabel('Fax Number:')->setValue($Fax);
$FormPosition = new Zend_Form_Element_Text('Position');
$FormPosition->setLabel('Contacts Position:')->setValue($Position);
$FormDescription = new Zend_Form_Element_Text('Description');
$FormDescription->setLabel('Short Description:')->setValue($Description)->setRequired();
$formEmail = new Zend_Form_Element_Text('Email');
$formEmail->setLabel('Email Address:')->setValue($Email);
$FormDefault = new Zend_Form_Element_Checkbox('Default');
$FormDefault->setValue('Default')->setLabel('Set as defualt contact for this business:');
if($Default == 'Default')
{
$FormDefault->setChecked(true);
}
$formCustomerID = new Zend_Form_Element_Hidden('customerID');
$formCustomerID->setValue($customerID);
if($this->contactID != null)
{
$formContactID = new Zend_Form_Element_Hidden('ContactID');
$formContactID->setValue($this->contactID);
}
// FORM SELECT
$formSelectAddress = new Zend_Form_Element_Select('custAddress');
$pos = 0;
while($pos < count($this->customerAddressArray))
{
$formSelectAddress->addMultiOption($this->customerAddressArray[$pos]['custAddressID'], $this->customerAddressArray[$pos]['Description']);
$pos++;
}
$formSelectAddress->setValue(array($this->contactDetails['custAddressID']));
$formSelectAddress->setRequired()->setLabel('Default Address For this Contact:');
// END FORM SELECT
$this->setMethod('post');
$this->setName('FormCustomerEdit');
$formSubmit = new Zend_Form_Element_Submit('ContactSubmit');
$formSubmit->setLabel('Save Contact');
$this->setName('CustomerContactForm');
$this->setMethod('post');
$this->addElements(array($FormDescription, $formfirstname, $formlastname,
$FormPosition, $formPhone, $formFax, $FormDefault,
$formEmail, $formSelectAddress, $formContactID, $formCustomerID, $formSubmit));
$this->addElements(array($formSubmit));
}
Maybe you've already fixed, but just in case.
I was having the same issue and the problem was the name of certain attributes within the form. In your case you have:
if($this->contactID != null){
$formContactID = new Zend_Form_Element_Hidden('ContactID');
$formContactID->setValue($this->contactID);
}
In the moment that you have added $formContactID to the form a new internal attribute has been created for the form object, this being 'ContactID'. So now we have $this->ContactID and $this->contactID.
According to PHP standards this shouldn't be a problem because associative arrays keys and objects attribute names are case sensitive but I just wanted to use your code to illustrate the behaviour of Zend Form.
Revise the rest of the code in your form to see that you are not overriding any Zend Element. Sorry for the guess but since you didn't post all the code for the form file it's a bit more difficult to debug.
Thanks and I hope it helps.
I think the problem is on $this->addElements when $formContactID is missing because of if($this->contactID != null) rule.
You can update your code to fix the problem:
.....
$this->addElements(array($FormDescription, $formfirstname, $formlastname,
$FormPosition, $formPhone, $formFax, $FormDefault,
$formEmail, $formSelectAddress, $formCustomerID, $formSubmit));
if(isset($formContactID)) {
$this->addElements(array($formContactID));
}
......