Magneto 2 Admin grid custom column filter is not working in my module - magento2

create a module for custom column but still filter is not working
namespace Vendore\Modulename\Model\ResourceModel\modulename\Grid;
use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as FetchStrategy;
use Magento\Framework\Data\Collection\EntityFactoryInterface as EntityFactory;
use Magento\Framework\Event\ManagerInterface as EventManager;
use Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult;
use Psr\Log\LoggerInterface as Logger;
class Collection extends SearchResult
public function __construct(
EntityFactory $entityFactory,
Logger $logger,
FetchStrategy $fetchStrategy,
EventManager $eventManager,
$mainTable = 'unicommerce_sync_order',
$resourceModel = 'vendorename\modulename\Model\ResourceModel\modulename',
$identifierName = null,
$connectionName = null
) {
parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel, $identifierName, $connectionName);
}
/**
* #return Collection|void
*/
protected function _initSelect()
{
$this->addFilterToMap('created_at', 'salesOrder.created_at');
parent::_initSelect();
}
protected function _renderFiltersBefore()
{
$this->getSelect()
->joinLeft(
['salesOrder' => $this->getConnection()->getTableName('sales_order')],
'main_table.magento_order_id = salesOrder.entity_id',
['created_at'=>'salesOrder.created_at']
);
//echo $this->getSelect();
parent::_renderFiltersBefore();
}
Note : create_at column date get proper but filter is not working
please check my code and let me know if any issue
Thanks

Related

After updating Laravel to version 9, I can't sign an email inside a Mailable class

After updating Laravel to version 9, I can't sign an email inside a Mailable class.
my code in Laravel 6 worked:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class NotificationEmail extends Mailable
{
use Queueable, SerializesModels;
protected $person;
protected $data = [];
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($person, $data)
{
$this->person = $person;
$this->data = $data;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('mail.notification.senat')
->replyTo('noreply#example.com')
->subject('Test subject')
->with([
'person' => $this->person,
'data' => $this->data
])
->withSwiftMessage(function ($message){
$smimeSigner = new \Swift_Signers_SMimeSigner(
config('mail.sign_cert'),
[config('mail.sign_key'), config('mail.sign_key_password')]
);
$message->attachSigner($smimeSigner);
});
}
}
my code in Laravel 9 does not work:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Symfony\Component\Mime\Crypto\SMimeSigner;
use Symfony\Component\Mime\Email;
use Illuminate\Support\Facades\Log;
class NotificationEmail extends Mailable
{
use Queueable, SerializesModels;
protected $person;
protected $data = [];
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($person, $data)
{
$this->person = $person;
$this->data = $data;
}
/**
* Build the message.
*
* #return $this
*/
public function build(): NotificationEmail {
return $this->view('mail.notification.senat')
->replyTo('noreply#example.com')
->subject('Test subject')
->with([
'person' => $this->person,
'data' => $this->data
])
->withSymfonyMessage(function (Email $message){
$certPath = storage_path(env('MAIL_SIGN_CERT'));
$keyPath = storage_path(env('MAIL_SIGN_KEY'));
// see: https://symfony.com/doc/current/mailer.html#signing-and-encrypting-messages
$signer = new SMimeSigner($certPath, $keyPath, env('MAIL_SIGN_KEY_PASSWORD'));
$signer->sign($message);
})
;
}
}
I know that Laravel 9 works with Symfony Mailer. However, the description does not use a Laravel Mailable environment.... See: https://symfony.com/doc/current/mailer.html#signing-and-encrypting-messages
The Laravel9 doc shows the way to customize: https://laravel.com/docs/9.x/mail#customizing-the-symfony-message
But my solution does not work. I get an error, line 48 "$signer->sign($message);"
A message must have a text or an HTML part or attachments.
Do you have a clue and can you help?
I would suggest an event listener for any outbound mail to achieve signing for all outbound mails with Laravel 9 / Symfony Mailer.
<?php
namespace App\Listeners\Mail;
use Illuminate\Mail\Events\MessageSending;
use Symfony\Component\Mime\Crypto\SMimeSigner;
use Symfony\Component\Mime\Email;
class MessageSendingListener
{
public function handle(MessageSending $event)
{
$signer = new SMimeSigner('/path/to/certificate.pem', 'path/to/private.key');
$signedMessage = $signer->sign($event->message);
$event->message->setHeaders($signedMessage->getHeaders());
$event->message->setBody($signedMessage->getBody());
}
}
Full explanation with the Event Service Provider:
https://laracasts.com/discuss/channels/laravel/laravel-9-outbound-smime-messages
Symfony Docs S/MIME:
https://symfony.com/doc/current/mailer.html#s-mime-signer
Cheers :)

get settings in validator - typo3

I have an extension with backend configuration options.I need to validate a phone number in AddAction and UpdateAction.I can configure the phone number format in backend (say us phone number/indian phone number etc).How can i get the settings in validator?
I have a custom validator to validate phone numbers.Here is my code
<?php
namespace vendor\Validation\Validator;
class UsphonenumberValidator extends \TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator
{
protected $supportedOptions = array(
'pattern' => '/^([\(]{1}[0-9]{3}[\)]{1}[ ]{1}[0-9]{3}[\-]{1}[0-9]{4})$/'
);
public function isValid($property) {
$settings = $this->settings['phone'];
$pattern = $this->supportedOptions['pattern'];
$match = preg_match($pattern, $property);
if ($match >= 1) {
return TRUE;
} else {
$this->addError('Phone number you are entered is not valid.', 1451318887);
return FALSE;
}
}
}
$settings returns null
In cases where the extbase configuration of your extension isn't implemented by default you should retrieve it yourself by using the \TYPO3\CMS\Extbase\Configuration\ConfigurationManager.
Here is an example how you can obtain the settings of your extension:
<?php
namespace MyVendor\MyExtName\Something;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Extbase\Object\ObjectManager;
class Something {
/**
* #var string
*/
static protected $extensionName = 'MyExtName';
/**
* #var null|array
*/
protected $settings = NULL;
/**
* Gets the Settings
*
* #return array
*/
public function getSettings() {
if (is_null($this->settings)) {
$this->settings = [];
/* #var $objectManager \TYPO3\CMS\Extbase\Object\ObjectManager */
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/* #var $configurationManager \TYPO3\CMS\Extbase\Configuration\ConfigurationManager */
$configurationManager = $objectManager->get(ConfigurationManager::class);
$this->settings = $configurationManager->getConfiguration(
ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS,
self::$extensionName
);
}
return $this->settings;
}
}
I recommend that you implement such functionality in general. So you could retrieve any configuration of any extension as a Service inside your extension or something similar to this.
Good luck!

Symfony3: Service not able to get arguments

I have made a service to get Doctrine connection in my models (Not sure if it is a nice approach but I dont want to pass connection from controller to model constructor each time).
So lets say I want products in my controller
public function getProductsAction(Request $request) {
$product_model = new ProductModel();
return $product_model->getProducts();
}
I have Product model Which will access a helper to get "database_connection"
use AppBundle\Helper\ContainerHelper;
class ProductModel {
function getProducts() {
$helper = new ContainerHelper();
$db = $helper->getDoctrine();
$query = "SELECT * FROM customer_products;";
$statement = $db->prepare($query);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
}
Now this helper is defined in src/AppBundle/Helper/ContainerHelper.php
namespace AppBundle\Helper;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
class ContainerHelper {
private $container;
public function __construct(Container $container) {
$this->container = $container;
}
public static function getDoctrine() {
$database_connection = $this->container->get('database_connection');
return $database_connection;
}
}
Lets say this service needs "service container" so in app/config/services.yml
services:
app.container_helper:
class: AppBundle\Helper\ContainerHelper
arguments: ['#service_container']
But it gives me error:
Catchable Fatal Error: Argument 1 passed to
AppBundle\Helper\ContainerHelper::__construct() must implement
interface Symfony\Component\DependencyInjection\ContainerInterface,
none given, called in \src\AppBundle\Model\ProductModel.php
on line 148 and defined
While I believe that I have implemented it correctly according to http://symfony.com/doc/current/book/service_container.html and http://anjanasilva.com/blog/injecting-services-in-symfony-2/, its certain that I have missed something or just got the whole bad idea. I need to know if it is a correct concept or what I have missed
While #pavlovich is trying to fix your existing code, I really think you are making this much more convoluted than it has to be. ProductModel itself should be a service with your database connection injected into it.
class ProductModel {
public function __construct($conn) {
$this->conn = $conn;
}
public function getProducts() {
$stmt = $this->conn->executeQuery('SELECT * FROM customer_products');
return $stmt->fetchAll();
}
services:
product_model:
class: AppBundle\...\ProductModel
arguments: ['#database_connection']
// controller.php
$productModel = $this->get('product_model'); // Pull from container
$products = $productModel->getProducts();
Rather than using helpers, I'd recommend using constructor injection and autowiring. It's more safe, future proof and easier to extend and test.
In such case, you'd have to create ProductRepository (more common and standard name for ProductModel) and pass it to controller.
1. Controller
<?php
class SomeController
{
/**
* #var ProductRepository
*/
private $productRepository;
public function __construct(ProductRepository $productRepository)
{
$this->productRepository = $productRepository;
}
public function getProductsAction()
{
return $this->productRepository->getProducts();
}
}
If you have difficulties to register controller as a service, just use Symplify\ControllerAutowire bundle.
2. ProductRepository
// src/AppBundle/Repository/ProductRepository.php
namespace AppBundle\Repository;
class ProductRepository
{
/**
* #var Doctrine\DBAL\Connection
*/
private $connection;
public function __construct(Doctrine\DBAL\Connection $connection)
{
$this->connection = $connection;
}
public function fetchAll()
{
$query = "SELECT * FROM customer_products;";
$statement = $this->connection->prepare($query);
$statement->execute();
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
}
3. Service registration
# app/cofig/servies.yml
services:
product_repository:
class: AppBundle\Repository\ProductRepository
autowire: true
For more you can see similar question with answer here: Symfony 3 - Outsourcing Controller Code into Service Layer
With new version of Symfony 3.3, a new feature is added (Auto-wired Services Dependencies)
https://symfony.com/doc/current/service_container/autowiring.html
https://symfony.com/doc/current/service_container/3.3-di-changes.html
Using this feature, I solved this issue in following way:
Added a new directory /src/AppBundle/Model
Added my model classes in this directory
namespace AppBundle\Modal;
use Doctrine\ORM\EntityManagerInterface;
class ProductModal
{
private $em;
// We need to inject this variables later.
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}
// We need to inject this variables later.
public function getProducts()
{
$statement = $this->em->getConnection()->prepare("SELECT * FROM product WHERE 1");
$statement->execute();
$results = $statement->fetchAll();
return $results;
}
}
Added in my app/config/services.yml
AppBundle\Modal\:
resource: '../../src/AppBundle/Modal/*'
public: true
In my controller I can use it like
$products = $this->get(ProductModal::class)->getProducts();
P.S. Dont forget to add use AppBundle\Entity\Product\Product; in controller

phpunit: How do I pass values between tests?

I'm really running into a brick wall with this. How do you pass class values between tests in phpunit?
Test 1 -> sets value,
Test 2 -> reads value
Here is my code:
class JsonRpcBitcoinTest extends PHPUnit_Framework_TestCase
{
public function setUp(){
global $configRpcUser, $configRpcPass, $configRpcHost, $configRpcPort;
$this->bitcoindConn = new JsonRpcBitcoin($configRpcUser, $configRpcPass, $configRpcHost, $configRpcPort);
$this->blockHash = '';
}
/**
* #depends testCanAuthenticateToBitcoindWithGoodCred
*/
public function testCmdGetBlockHash()
{
$result = (array)json_decode($this->bitcoindConn->getblockhash(20));
$this->blockHash = $result['result'];
$this->assertNotNull($result['result']);
}
/**
* #depends testCmdGetBlockHash
*/
public function testCmdGetBlock()
{
$result = (array)json_decode($this->bitcoindConn->getblock($this->blockHash));
$this->assertEquals($result['error'], $this->blockHash);
}
}
testCmdGetBlock() is not getting the value of $this->blockHash that should be set in testCmdGetBlockHash().
Help in understanding what is wrong would be greatly appreciated.
The setUp() method is always called before tests, so even if you set up a dependency between two tests, any variables set in setUp() will be overwritten. The way PHPUnit data passing works is from the return value of one test to the parameter of the other:
class JsonRpcBitcoinTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
global $configRpcUser, $configRpcPass, $configRpcHost, $configRpcPort;
$this->bitcoindConn = new JsonRpcBitcoin($configRpcUser, $configRpcPass, $configRpcHost, $configRpcPort);
$this->blockHash = '';
}
public function testCmdGetBlockHash()
{
$result = (array)json_decode($this->bitcoindConn->getblockhash(20));
$this->assertNotNull($result['result']);
return $result['result']; // the block hash
}
/**
* #depends testCmdGetBlockHash
*/
public function testCmdGetBlock($blockHash) // return value from above method
{
$result = (array)json_decode($this->bitcoindConn->getblock($blockHash));
$this->assertEquals($result['error'], $blockHash);
}
}
So if you need to save more state between tests, return more data in that method. I would guess that the reason PHPUnit makes this annoying is to discourage dependent tests.
See the official documentation for details.
You can use a static variable within a function...
PHP annoyingly shares static variables of class methods with all the instances... But in this cas it can help :p
protected function &getSharedVar()
{
static $value = null;
return $value;
}
...
public function testTest1()
{
$value = &$this->getSharedVar();
$value = 'Hello Test 2';
}
public function testTest2()
{
$value = &$this->getSharedVar();
// $value should be ok
}
NB: this is NOT the good way but it helps if you need some data in all your tests...
Another option is to use static variables.
Here is an example (for Symfony 4 functional tests):
namespace App\Tests\Controller\Api;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Hautelook\AliceBundle\PhpUnit\RefreshDatabaseTrait;
use Symfony\Component\HttpFoundation\AcceptHeader;
class BasicApiTest extends WebTestCase
{
// This trait provided by HautelookAliceBundle will take care of refreshing the database content to a known state before each test
use RefreshDatabaseTrait;
private $client = null;
/**
* #var string
*/
private const APP_TOKEN = 'token-for-tests';
/**
* #var string
*/
private static $app_user__email = 'tester+api+01#localhost';
/**
* #var string
*/
private static $app_user__pass = 'tester+app+01+password';
/**
* #var null|string
*/
private static $app_user__access_token = null;
public function test__Authentication__Login()
{
$this->client->request(
Request::METHOD_POST,
'/api/login',
[],
[],
[
'CONTENT_TYPE' => 'application/json',
'HTTP_App-Token' => self::APP_TOKEN
],
'{"user":"'.static::$app_user__email.'","pass":"'.static::$app_user__pass.'"}'
);
$response = $this->client->getResponse();
$this->assertEquals(Response::HTTP_OK, $response->getStatusCode());
$content_type = AcceptHeader::fromString($response->headers->get('Content-Type'));
$this->assertTrue($content_type->has('application/json'));
$responseData = json_decode($response->getContent(), true);
$this->assertArrayHasKey('token', $responseData);
$this->static = static::$app_user__access_token = $responseData['token'];
}
/**
* #depends test__Authentication__Login
*/
public function test__SomeOtherTest()
{
$this->client->request(
Request::METHOD_GET,
'/api/some_endpoint',
[],
[],
[
'CONTENT_TYPE' => 'application/json',
'HTTP_App-Token' => self::APP_TOKEN,
'HTTP_Authorization' => 'Bearer ' . static::$app_user__access_token
],
'{"user":"'.static::$app_user__email.'","pass":"'.static::$app_user__pass.'"}'
);
$response = $this->client->getResponse();
$this->assertEquals(Response::HTTP_OK, $response->getStatusCode());
$content_type = AcceptHeader::fromString($response->headers->get('Content-Type'));
$this->assertTrue($content_type->has('application/json'));
//...
}
}
Another (simpler) example using static variables as pointed out by BoĊĦtjan Biber:
class ClientTest extends \PHPUnit\Framework\TestCase
{
protected $client;
protected static $testClient;
// Before a test method is run, a template method called setUp() is invoked.
public function setUp() :void
{
$this->client = new \Application\models\Clients;
}
public function testInsertCustomer()
{
$testclient = array(
'name' => 'Test Client',
'responsible' => 'Responsible Test',
'payment' => 'Test payment',
'email' => 'Test Email',
'phone' => '123-456-789'
);
$this->assertTrue($this->customer->insertCustomer($CustomerTest));
}
public function testGetCustomers()
{
$this->assertIsArray($this->customer->getCustomers());
$this->assertNotEmpty($this->customer->getCustomers());
// Save test client for other methods
$clients = $this->client->getClients();
static::$testCustomer = end($customers);
}
public function testGetClient()
{
$this->assertIsArray($this->customer->getCustomer(static::$customerTest['customer_id']));
$this->assertNotEmpty($this->customer->getCustomer(static::$customerTest['customer_id']));
}
}
You can use a static variable using the method setUpBeforeClass:
protected static $sharedId;
public static function setUpBeforeClass(): void
{
self::$sharedId = random_int(100,10000);
}
And access it in you tests like this:
public function testCreateLocation() {
echo 'Shared variable = ' . self::$sharedId;
// Use the variable in your test code and asserts...
}
/The Schwartz
This worked for me perfectly fine across all tests: $this->varablename
class SignupTest extends TestCase
{
private $testemail = "registerunittest#company.com";
private $testpassword = "Mypassword";
public $testcustomerid = 123;
private $testcountrycode = "+1";
private $testphone = "5005550000";
public function setUp(): void
{
parent::setUp();
}
public function tearDown(): void
{
parent::tearDown();
}
public function testSignup()
{
$this->assertEquals("5005550000", $this->testphone;
}
}

In extbase, how to access item by another value than uid

In a custom extbase extension, I need to call a show action, passing it another value than uid (this is a continuation of Use other than primary key as RealURL id_field).
As the value "other than uid" is not resolved, it results in the exception http://wiki.typo3.org/Exception/CMS/1297759968
EDIT: here's the current working (but ugly) Controller code:
/**
* ItemController
*/
class ItemController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
/**
* itemRepository
*
* #var \STUBR\Weiterbildung\Domain\Repository\ItemRepository
* #inject
*/
protected $itemRepository = NULL;
/**
* action list
*
* #return void
*/
public function listAction(\STUBR\Weiterbildung\Domain\Model\Item $item=null) {
if (!empty(\TYPO3\CMS\Core\Utility\GeneralUtility::_GET('tx_weiterbildung_pi1'))){
$this->forward('show');
}
$items = $this->itemRepository->findAll();
$this->view->assign('items', $items);
}
/**
* action show
*
* #param \STUBR\Weiterbildung\Domain\Model\Item $item
* #return void
*/
public function showAction(\STUBR\Weiterbildung\Domain\Model\Item $item=null) {
$tx_weiterbildung_pi1_get = \TYPO3\CMS\Core\Utility\GeneralUtility::_GET('tx_weiterbildung_pi1');
if (!empty($tx_weiterbildung_pi1_get)){
$dfid = intval($tx_weiterbildung_pi1_get['durchfuehrungId']);
}
$items = $this->itemRepository->findByDurchfuehrungId($dfid);
// helpful:
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($item);
$this->view->assign('item', $items[0]);
}
}
PS here are the 5 lines that could be used in the Repository if the magical method wouldn't work:
//public function findByDurchfuehrungId($dfid) {
// $query = $this->createQuery();
// $query->matching($query->equals('durchfuehrungId', $dfid));
// return $query->execute();
//}
Yes, when you're using actions with model binding in param it will always look for object by field defined as ID - in our case it's always uid, but remember, that you do not need to bind model automatically, as you can retrive it yourself.
Most probably you remember, that some time ago I advised to use <f:link.page additionalParams="{originalUid:myObj.originalUid}"Click here</f:link.page> instead of <f:link.action...>
In that case your show action would look like this:
public function showAction() {
$item = $this->itemRepository->findByOriginalUid(intval(GeneralUtility::_GET('originalUid')));
$this->view->assign('item', $item);
}
Where findByOriginalUid should work magically without declaration, but even if it doesn't it's just matter of 5 lines in the repo ;)
Other sample
According to the code you pasted I'd use it rather like this, in this case listAction gets a role of dispatcher for whole plugin:
public function listAction() {
// access get param in array
$tx_weiterbildung_pi1_get = \TYPO3\CMS\Core\Utility\GeneralUtility::_GET('tx_weiterbildung_pi1');
$dfId = intval($tx_weiterbildung_pi1_get['durchfuehrungId']);
if ($dfId > 0) { // tx_weiterbildung_pi1 exists and is positive, that means you want to go to showAction
$item = $this->itemRepository->findByDurchfuehrungId($dfId);
if (!is_null($item)) { // Forward to showAction with found $item
$this->forward('show', null, null, array('item' => $item));
}else { // Or redirect to the view URL after excluding single item ID from GET params
$this->redirectToUri($this->uriBuilder->setArgumentsToBeExcludedFromQueryString(array('tx_weiterbildung_pi1'))->build());
}
}
// No `tx_weiterbildung_pi1` param, so it should be displayed as a listAction
$items = $this->itemRepository->findAll();
$this->view->assign('items', $items);
}
/**
* #param \STUBR\Weiterbildung\Domain\Model\Item $item
*/
public function showAction(\STUBR\Weiterbildung\Domain\Model\Item $item = null) {
$this->view->assign('item', $item);
}
Your finder should also getFirst() object if possible:
public function findByDurchfuehrungId($DfId) {
$query = $this->createQuery();
$query->matching($query->equals('durchfuehrungId', $DfId));
return $query->execute()->getFirst();
}