cant update user attributes in installData - magento

I create custom module.
After i try to add custom attribute in InstallData.php
I remove my module from setup_module to run install data however i don`t see any results nor error.
I try run setup:upgrade c:c c:f
I want to add custom attribute to user information. To update that information after user is register account. Also I want after to have ability to change it from admin area and from front settings. But for now i cant make work to see it in admin.
Should I add any additional code to run this ?
<?php
namespace Vendor\RewardPoints\Setup;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Customer\Model\Customer;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
/**
* #codeCoverageIgnore
*/
class InstallData implements InstallDataInterface
{
/**
* #var CustomerSetupFactory
*/
protected $customerSetupFactory;
/**
* #var AttributeSetFactory
*/
private $attributeSetFactory;
private $eavSetupFactory;
/**
* Init
*
* #param EavSetupFactory $eavSetupFactory
*/
public function __construct(EavSetupFactory $eavSetupFactory, CustomerSetupFactory $customerSetupFactory, AttributeSetFactory $attributeSetFactory)
{
$this->eavSetupFactory = $eavSetupFactory;
$this->customerSetupFactory = $customerSetupFactory;
$this->attributeSetFactory = $attributeSetFactory;
}
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
/* Create customer attribute for front-end builder*/
/** #var CustomerSetup $customerSetup */
$customerSetup = $this->customerSetupFactory->create(['setup' => $setup]);
$customerEntity = $customerSetup->getEavConfig()->getEntityType('customer');
$attributeSetId = $customerEntity->getDefaultAttributeSetId();
/** #var $attributeSet AttributeSet */
$attributeSet = $this->attributeSetFactory->create();
$attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId);
$customerSetup->addAttribute(Customer::ENTITY, 'my_telephone', [
'type' => 'int',
'label' => 'My telephone',
'input' => 'text',
'required' => false,
'visible' => true,
'user_defined' => true,
'sort_order' => 1000,
'is_used_in_grid' => 1,
'is_visible_in_grid' => 1,
'is_filterable_in_grid' => 1,
'is_searchable_in_grid' => 1,
'position' => 1000,
'default' => 0,
'system' => 0,
]);
$attribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'my_telephone')
->addData([
'attribute_set_id' => $attributeSetId,
'attribute_group_id' => $attributeGroupId,
'used_in_forms' => ['adminhtml_customer'],
]);
$attribute->save();
}
}

In the article Magento 2: How to make customer attribute? describe it step by step.
Customer attributes can be used in different forms, this example will show customer attribute at the admin customer edit page. You can also use also other forms. For example:
“used_in_forms” => [‘adminhtml_customer_address’, ‘customer_address_edit’, ‘customer_register_address’]

Related

How to fix this issue? Couldn't open stream {imap.gmail.com:993/imap/ssl}. [AUTHENTICATIONFAILED] Invalid credentials

I am using laravel-IMAP to integrate Gmail with my laravel project and package I follow is Webklex/laravel-imap.
Issue is when i test my code the error poped-up, I followed to many links to figure-out my issue, one solution i find is to enable IMAP access: Enable IMAP, but it is not a solution for all the users, I want to fetch the emails of that user's those who will use this application with doing enable imap access. Is there any other solution to overcome this problem?
Controller
class TestController extends Controller
{
public function index(){
$oClient = new Client([
'host' => 'imap.gmail.com',
'port' => 993,
'encryption' => 'ssl',
'validate_cert' => true,
'username' => '**********',
'password' => '**********',
'protocol' => 'imap'
]);
/* Alternative by using the Facade
$oClient = Webklex\IMAP\Facades\Client::account('default');
*/
//Connect to the IMAP Server
$oClient->connect();
//Get all Mailboxes
/** #var \Webklex\IMAP\Support\FolderCollection $aFolder */
$aFolder = $oClient->getFolders();
//Loop through every Mailbox
/** #var \Webklex\IMAP\Folder $oFolder */
foreach($aFolder as $oFolder){
//Get all Messages of the current Mailbox $oFolder
/** #var \Webklex\IMAP\Support\MessageCollection $aMessage */
$aMessage = $oFolder->messages()->all()->get();
/** #var \Webklex\IMAP\Message $oMessage */
foreach($aMessage as $oMessage){
echo $oMessage->getSubject().'<br />';
echo 'Attachments: '.$oMessage->getAttachments()->count().'<br />';
echo $oMessage->getHTMLBody(true);
}
}
}
}

FormType & method repository

I have a problem with my FormType. I want to display data and thanks to the querybuilder make a distinction. Problem when I call my method with a -> select ('t.nomVern') I have "Warning: spl_object_hash () expects parameter 1 to be object, string given" as an error message.
I do not understand why.
My FormType ObservationType:
<?php
namespace ObservationBundle\Form;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Vich\UploaderBundle\Form\Type\VichImageType;
use ImportBundle\Repository\TaxrefRepository;
use ImportBundle\Entity\Taxref;
class ObservationType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('date', DateType::class, array(
'widget' => 'single_text',
'html5' => false,
'attr' => array(
'placeholder' => 'Choisir la date de l\'observation',
)
))
->add('latitude', TextType::class, array(
'attr' => array(
'placeholder' => 'Latitude ex : 31.85322'
)
))
->add('longitude', TextType::class, array(
'attr' => array(
'placeholder' => 'Longitude ex : 33.55555'
)
))
->add('nombre', IntegerType::class)
->add('imageFile', VichImageType::class, array(
'required' => false,
'allow_delete' => false, // not mandatory, default is true
'download_link' => false, // not mandatory, default is true
'attr' => array(
'placeholder' => 'Votre image'
)
))
->add('valide', HiddenType::class)
->add('commentaire', HiddenType::class)
->add('gpsAffiche', HiddenType::class)
->add('meteo', HiddenType::class)
->add('saison', HiddenType::class)
->add('typeSaisie', HiddenType::class)
->add('precipitation', HiddenType::class)
->add('periode', HiddenType::class)
->add('environnement', HiddenType::class)
->add('sensibilite', HiddenType::class)
->add('comportement', HiddenType::class)
->add('species', EntityType::class, array(
'label' => 'Espèce observée :',
'class' => 'ImportBundle\Entity\Taxref',
'choice_label' => 'nomVern',
'query_builder' => function(TaxrefRepository $qb){
return $qb->distinctTaxref();
}
))
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'ObservationBundle\Entity\Observation'
));
}
/**
* #return string
*/
public function getBlockPrefix()
{
return 'observationbundle_observation';
}
}
And my repository :
<?php
namespace ImportBundle\Repository;
use Doctrine\DBAL\Query\QueryBuilder;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class TaxrefRepository extends EntityRepository
{
/**
* Pagination liste des especes
* #param int $page
* #param int $max
* #return Paginator
*/
public function findByPage($page = 1, $max = 8)
{
if(!is_numeric($page)) {
throw new \InvalidArgumentException(
'$page must be an integer ('.gettype($page).' : '.$page.')'
);
}
if(!is_numeric($page)) {
throw new \InvalidArgumentException(
'$max must be an integer ('.gettype($max).' : '.$max.')'
);
}
$dql = $this->createQueryBuilder('t');
$dql->orderBy('t.id', 'DESC');
$firstResult = ($page - 1) * $max;
$query = $dql->getQuery();
$query->setFirstResult($firstResult);
$query->setMaxResults($max);
$paginator = new Paginator($query);
if(($paginator->count() <= $firstResult) && $page != 1) {
throw new NotFoundHttpException('Page not found');
}
return $paginator;
}
/**
* #return \Doctrine\ORM\QueryBuilder
*/
public function distinctTaxref()
{
return $this
->createQueryBuilder('t')
->select('t.nomVern')
->distinct(true)
->orderBy('t.nomVern', 'ASC');
}
}
Thank you in advance for your help and sorry for my bad english :/
Try this part of code
return $this
->createQueryBuilder('t')
->select(array('t.nomVern'))
->distinct(true)
->orderBy('t.nomVern', 'ASC');
I believe that, since you're using EntityType, Symfony expects to have an array of objects, whereas you select a single column which produces an array of strings.
Can you try selecting an object as a whole:
return $this
->createQueryBuilder('t')
->select('t')
->distinct(true)
->orderBy('t.nomVern', 'ASC');
Does this work?

Yii2: call custom method in class User from view

I would like to extend my own user model, with a function called getFirstname.
The function should return a custom field in the database.
But when I extend the user model. It says "Calling unknown method: yii\web\User::getFirstname()"
My user model in app\models\user.
I have removed methods in the file, that are not relevant for this problem.
<?php
namespace app\models;
use Yii;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
/**
* User model
*
*/
class User extends ActiveRecord implements IdentityInterface
{
/**
* #inheritdoc
*/
public static function tableName()
{
return '{{%user}}';
}
/**
* #inheritdoc
*/
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
/**
* #inheritdoc
*/
public function rules()
{
return [];
}
/**
* Finds user by email
*
* #param string $email
* #return static|null
*/
public static function findByEmail($username)
{
return static::findOne(['user_email' => $username]);
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->getPrimaryKey();
}
public function getFirstname()
{
return $this->user_firstname;
}
}
My config file:
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'components' => [
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => 'thepaXucufrE2pefRethaxetrusacRu3',
],
'cache' => [
'class' => 'yii\caching\FileCache',
],
'user' => [
'identityClass' => 'app\models\User',
'loginUrl' => ['login/sign-in'],
'enableAutoLogin' => true,
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
'useFileTransport' => true,
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'db' => require(__DIR__ . '/db.php'),
],
];
And in my view file:
<?= Yii::$app->user->getFirstname() ?>
What am I doing wrong here?
Try this:
<?= Yii::$app->user->identity->getFirstname() ?>
<!-- or -->
<?= Yii::$app->user->identity->firstname ?>
With Yii::$app->user you just get the user component. The User component class comment tells you:
User is the class for the "user" application component that manages
the user authentication status.
So it is not the actual user that you get with Yii::$app->user, it is the managing component. With identity or getIdentity() of this class you get the user object that is implementing the IdentityInterface. And when you have a look: your User class implements this interface. And in your configuration you tell the user component that it should use exactly your User class.
The User class with the getFirstname method is in the \app\models namespace, but the one being called in your view is in the yii\web namespace. You should change the code to use \app\models\User.

How to create different Magento categories for main and mobile store view on one domain name

I am looking solutions for using different categories for main and mobile Magento store view. I have configure mobile store view as new theme with user agent string and exception.
How can I do show one categories on main store view and another one categories on mobile store view. Both store views use by one domain name.
What I will suggest it create an category attribute with dropdown. Following Script will help you to do so :
SQL Setup file :
<?php
$installer = $this;
$installer->startSetup();
$installer->addAttribute("catalog_category", "wheretoshow", array(
"type" => "int",
"backend" => "",
"frontend" => "",
"label" => "Where to Show",
"input" => "select",
"class" => "",
"source" => "modulename/eav_entity_attribute_source_categoryoptions",
"global" => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
"visible" => true,
"required" => false,
"user_defined" => false,
"default" => "Main Website",
"searchable" => false,
"filterable" => false,
"comparable" => false,
"visible_on_front" => false,
"unique" => false,
"note" => ""
));
$installer->endSetup();
Model/Categoryoptions.php
<?php
class class Packagename_Modulename_Model_Eav_Entity_Attribute_Source_Categoryoptions extends Mage_Eav_Model_Entity_Attribute_Source_Abstract
{
/**
* Retrieve all options array
*
* #return array
*/
public function getAllOptions()
{
if (is_null($this->_options)) {
$this->_options = array(
array(
"label" => Mage::helper("eav")->__("Mobile Website"),
"value" => 1
),
array(
"label" => Mage::helper("eav")->__("Main Website"),
"value" => 2
),
);
}
return $this->_options;
}
/**
* Retrieve option array
*
* #return array
*/
public function getOptionArray()
{
$_options = array();
foreach ($this->getAllOptions() as $option) {
$_options[$option["value"]] = $option["label"];
}
return $_options;
}
/**
* Get a text for option value
*
* #param string|integer $value
* #return string
*/
public function getOptionText($value)
{
$options = $this->getAllOptions();
foreach ($options as $option) {
if ($option["value"] == $value) {
return $option["label"];
}
}
return false;
}
/**
* Retrieve Column(s) for Flat
*
* #return array
*/
public function getFlatColums()
{
$columns = array();
$columns[$this->getAttribute()->getAttributeCode()] = array(
"type" => "tinyint(1)",
"unsigned" => false,
"is_null" => true,
"default" => null,
"extra" => null
);
return $columns;
}
/**
* Retrieve Indexes(s) for Flat
*
* #return array
*/
public function getFlatIndexes()
{
$indexes = array();
$index = "IDX_" . strtoupper($this->getAttribute()->getAttributeCode());
$indexes[$index] = array(
"type" => "index",
"fields" => array($this->getAttribute()->getAttributeCode())
);
return $indexes;
}
/**
* Retrieve Select For Flat Attribute update
*
* #param int $store
* #return Varien_Db_Select|null
*/
public function getFlatUpdateSelect($store)
{
return Mage::getResourceModel("eav/entity_attribute")
->getFlatUpdateSelect($this->getAttribute(), $store);
}
}
While Fetching the categories on frontend, filter those by this attribute depending on your website.

Creating Custom Options on a Product using the Magento API

How do I add custom options to a product like you can in the backend, using the API.
Im using C# but if you know how do to this in Php, that would be helpful too.
I noticed that product has this:
var product = new catalogProductCreateEntity();
product.options_container = "blah";
And there is this:
catalogAttributeOptionEntity optionEntity = new catalogAttributeOptionEntity();
optionEntity.value = "sds";
optionEntity.label = "ere";
But I cant see a way of utilizing them, im not sure how to make a container, and the catalogAttributeOptionEntity does not have all the properties needed to make a custom option.
Look at the admin product controller. Yes it is possible.
/**
* Initialize data for configurable product
*/
if (($data = $this->getRequest()->getPost('configurable_products_data')) && !$product->getConfigurableReadonly()) {
$product->setConfigurableProductsData(Zend_Json::decode($data));
}
if (($data = $this->getRequest()->getPost('configurable_attributes_data')) && !$product->getConfigurableReadonly()) {
$product->setConfigurableAttributesData(Zend_Json::decode($data));
}
$product->setCanSaveConfigurableAttributes((bool)$this->getRequest()->getPost('affect_configurable_product_attributes') && !$product->getConfigurableReadonly());
/**
* Initialize product options
*/
if (isset($productData['options']) && !$product->getOptionsReadonly()) {
$product->setProductOptions($productData['options']);
}
This is not documented anywhere (else), but at least in Magento 1.6 one can find the appropriate API methods for product options in the source code. (I don 't know since which version that feature exists.)
The API itself is defined in: app/code/core/Mage/Catalog/etc/api.xml
<catalog_product_custom_option translate="title" module="catalog">
<title>Catalog product custom options API</title>
<model>catalog/product_option_api</model>
<acl>catalog/product/option</acl>
<methods>
<add translate="title" module="catalog">
<title>Add new custom option into product</title>
<acl>catalog/product/option/add</acl>
</add>
<update translate="title" module="catalog">
<title>Update custom option of product</title>
<acl>catalog/product/option/update</acl>
</update>
<types translate="title" module="catalog">
<title>Get list of available custom option types</title>
<acl>catalog/product/option/types</acl>
</types>
<info translate="title" module="catalog">
<title>Get full information about custom option in product</title>
<acl>catalog/product/option/info</acl>
</info>
<list translate="title" module="catalog">
<title>Retrieve list of product custom options</title>
<acl>catalog/product/option/list</acl>
<method>items</method>
</list>
<remove translate="title" module="catalog">
<title>Remove custom option</title>
<acl>catalog/product/option/remove</acl>
</remove>
</methods>
</catalog_product_custom_option>
The called functions are defined in: app/code/core/Mage/Catalog/Model/Product/Option/Api.php
class Mage_Catalog_Model_Product_Option_Api extends Mage_Catalog_Model_Api_Resource
{
/**
* Add custom option to product
*
* #param string $productId
* #param array $data
* #param int|string|null $store
* #return bool $isAdded
*/
public function add( $productId, $data, $store = null )
/**
* Update product custom option data
*
* #param string $optionId
* #param array $data
* #param int|string|null $store
* #return bool
*/
public function update( $optionId, $data, $store = null )
/**
* Read list of possible custom option types from module config
*
* #return array
*/
public function types()
/**
* Get full information about custom option in product
*
* #param int|string $optionId
* #param int|string|null $store
* #return array
*/
public function info( $optionId, $store = null )
/**
* Retrieve list of product custom options
*
* #param string $productId
* #param int|string|null $store
* #return array
*/
public function items( $productId, $store = null )
/**
* Remove product custom option
*
* #param string $optionId
* #return boolean
*/
public function remove( $optionId )
/**
* Check is type in allowed set
*
* #param string $type
* #return bool
*/
protected function _isTypeAllowed( $type )
}
The $data-array also is a bit tricky, since it's keys partly depend on the selected option type. The basic $data-array looks like:
$data = array (
'is_delete' => 0,
'title' => 'Custom Option Label',
'type' => 'text',
'is_require' => 0,
'sort_order' => 1,
'additional_fields' => array (
0 => array (
'price' => '10.0000',
'price_type' => 'fixed', // 'fixed' or 'percent'
'sku' => '',
),
),
);
The additional_fields always conatin at least one row with at least the columns price, price_type and sku. More additional fields (maf: …) may be added depending on the type. The types in the group select may have more than one row specified in additional_fields. The custom option types/type-groups are:
text (maf: 'max_characters')
field
area
file (maf: 'file_extension', 'image_size_x', 'image_size_y')
file
select (maf: 'value_id', 'title', 'sort_order')
drop_down
radio
checkbox
multiple
date
date
date_time
time
Examples for complete option data arrays:
// type-group: select, type: checkbox
$data = array (
'is_delete' => 0,
'title' => 'extra Option for that product',
'type' => 'checkbox',
'is_require' => 0,
'sort_order' => 1,
'additional_fields' => array (
0 => array (
'value_id' => '3',
'title' => 'Yes',
'price' => 10.00,
'price_type' => 'fixed',
'sku' => NULL,
'sort_order' => 1,
),
1 => array (
'value_id' => 3,
'title' => 'No',
'price' => 0.00,
'price_type' => 'fixed',
'sku' => NULL,
'sort_order' => 2,
),
),
);
// type-group: text, type: field
$data = array (
'is_delete' => 0,
'title' => 'Custom Option Label',
'type' => 'text',
'is_require' => 0,
'sort_order' => 1,
'additional_fields' => array (
0 => array (
'price' => 10.00,
'price_type' => 'fixed',
'sku' => NULL,
'max_characters' => 150,
),
),
);
In the end I decided it cant be done via the API and went to the database directly.

Resources