?> berliozd, Author at Addeos

Author Archive

Generating PDF from Markdown with Grip

Markdown is a popular lightweight markup language used for formatting plain text documents. While Markdown excels in simplicity and ease of use, there are scenarios where the need arises to convert Markdown files to more portable and shareable formats, such as PDF. PDFs provide a consistent and printable representation of documents, making them an ideal choice for sharing content across various platforms.

However, when working with Markdown files containing images, the process of converting them to PDF can sometimes become challenging. The inclusion of images adds an extra layer of complexity to the conversion process, as certain tools may not seamlessly handle the transition from Markdown to PDF.

In this tutorial, we'll explore the use of Grip, a Markdown previewer, to generate a PDF file from a Markdown document. Additionally, we'll address the common concerns associated with images in Markdown files and provide solutions to ensure a smooth conversion process.

Whether you're looking to share documentation, create presentation materials, or simply preserve the formatting of your Markdown content for offline use, the ability to generate PDFs becomes invaluable. Let's dive into the step-by-step guide to harnessing Grip's capabilities for this purpose, and learn how to overcome challenges related to images in the Markdown-to-PDF conversion process.

Step 1: Install Grip

Grip is a lightweight GitHub-flavored Markdown previewer. You can install it using Python's pip package manager:

pip install grip

Step 2: Create a Markdown File

Create a Markdown file (e.g., example.md) containing your content. You can use any text editor to create and edit this file.

Step 3: Preview with Grip

Run Grip to preview your Markdown file:

grip example.md

This command will start a local server and provide you with a URL (e.g., http://localhost:6419). Open this URL in your web browser to see how your Markdown file will be rendered.

Step 4: Save as PDF

After previewing your Markdown file, you can save the rendered HTML as a PDF using your browser's print functionality.

In Google Chrome:

  • Click on the three dots in the top-right corner.
  • Select "Print..."
  • Change the destination to "Save as PDF."
  • Click "Save" to save the PDF file.

In Firefox:

  • Click on the three horizontal lines in the top-right corner.
  • Select "Print..."
  • Choose "Save to File" as the printer.
  • Click "Print" and save the PDF file.

Conclusion

Now you have successfully generated a PDF file from your Markdown file using Grip and printed it as a PDF.

berliozd

Enhancing Magento 2 JavaScript Modules with Mixins: A Guide

Introduction:

Magento 2 provides a robust and extensible architecture that allows developers to customize and extend functionality easily. One powerful feature for extending JavaScript modules is the use of mixins. In this article, we will explore how to add a mixin to an existing JavaScript module in Magento 2, drawing parallels to the familiar concept of writing PHP plugins for adding specific treatments after, before or around existing functions.

Understanding Mixins in Magento 2:

Mixins in Magento 2 JavaScript development enable developers to add or override methods in existing classes. This approach promotes code reusability and allows for seamless customization without modifying the core codebase. Just as PHP plugins can extend and modify the behavior of existing PHP classes, mixins empower JavaScript developers to enhance the functionality of JavaScript modules in a clean and modular way.

Prerequisites:

Before diving into the mixin implementation, ensure you have a basic understanding of Magento 2 JavaScript development and are familiar with the structure of the module you intend to extend.

Step 1: Create Your Mixin File:

In your custom module, create a JavaScript mixin file. This file should follow the naming convention "vendor/namespace/view/frontend/web/js/mixin-name-mixin.js". This file will contain the code for your mixin.

Let's say my module vendor and namespace is Addeos_MyModule.

And I want to create a mixin for this core file : vendor/magento/module-checkout/view/frontend/web/js/model/shipping-save-processor/default.js

I am going to create this file:
app/code/Addeos/MyModule/view/frontend/web/js/checkout/model/shipping-save-processor/default-mixin.js
I respect the same folder hierachy.

Here is the content of that file:

define(['jquery', 'mage/utils/wrapper'], function ($, wrapper) {
    'use strict';

    return function (defaultShippingSaveProcessor) {
        defaultShippingSaveProcessor.saveShippingInformation = wrapper.wrapSuper(
            defaultShippingSaveProcessor.saveShippingInformation,
            function () {
                console.log('here, I can do want I want.');
                return this._super();
            }
        );
        return defaultShippingSaveProcessor;
    };
});

Step 2: Apply the Mixin to the Target Module:

To apply the mixin to the target module, create a requirejs-config.js file in your module's view/frontend directory.

var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/model/shipping-save-processor/default': {
                'Addeos_MyModule/js/checkout/model/shipping-save-processor/default-mixin': true,
            },
        },
    },
};

Conclusion:

Adding a mixin to an existing JavaScript module in Magento 2 is a powerful way to customize functionality without modifying core code. Drawing parallels to PHP plugins, mixins offer a clean and modular approach to extending JavaScript modules, ensuring maintainability and ease of future upgrades. Incorporate this technique into your Magento 2 development toolkit to create flexible and scalable solutions.

berliozd

Magento 2 Security Best Practices

Safeguarding Your E-Commerce Store

Introduction

In the ever-evolving landscape of e-commerce, ensuring the security of your Magento 2 store is paramount. This article will guide you through essential security best practices, helping you protect your online business and instill confidence in your customers.

1. Keep Magento 2 Updated

Regularly updating your Magento 2 installation is the first line of defense against potential vulnerabilities. Magento frequently releases security patches and updates to address known issues. Make it a practice to stay current with the latest versions.

Check the published versions of Adobe Commerce here. It contains the release dates of each minor, patch, and security release, as well as the end of support dates.

Take a look at the lifecycle policy here.

2. Secure Admin Access

  • Unique Admin URL: Change the default admin URL to reduce the risk of brute-force attacks.
  • Strong Passwords: Enforce strong password policies for admin accounts, including a combination of letters, numbers, and special characters.

3. SSL Implementation

Ensure that your Magento 2 store uses Secure Socket Layer (SSL) to encrypt data transmission. This is crucial for securing sensitive information such as customer details and payment transactions.

4. Regular Security Audits

Performing regular security audits is essential to identify vulnerabilities and address them promptly. Consider employing third-party security tools or services to conduct thorough assessments.

5. File Permissions and Ownership

Set appropriate file permissions and ownership for your Magento 2 installation. Limit access to critical files and directories, reducing the likelihood of unauthorized access or modification.

6. Web Application Firewall (WAF)

Implement a Web Application Firewall to protect your store from common web threats. A WAF can filter and monitor HTTP traffic between a web application and the Internet, providing an additional layer of security.

7. Two-Factor Authentication (2FA)

Enforce Two-Factor Authentication for admin accounts to add an extra layer of security. This ensures that even if login credentials are compromised, an additional verification step is required.

8. Regular Backups

Frequently back up your Magento 2 store, including databases and media files. In the event of a security breach or data loss, having recent backups can significantly reduce downtime and data loss.

9. Extension Security

Carefully vet and only install reputable extensions from trusted sources. Regularly update installed extensions to benefit from security patches and improvements.

10. Educate Your Team

Security is a collective effort. Educate your team members on security best practices, including recognizing phishing attempts, safeguarding login credentials, and reporting suspicious activities promptly.

Conclusion

By implementing these Magento 2 security best practices, you fortify your e-commerce store against potential threats and build a foundation of trust with your customers. Stay vigilant, stay secure, and keep your online business thriving in a secure digital environment.

berliozd

Exciting News: My First Magento Extension is Now Live on the Marketplace!

I am thrilled to share some exciting news with you! Today marks a significant milestone for me as I proudly announce the deployment of my very first extension on the Adobe Magento Marketplace.

This extension empowers you to anonymize your database with a new CLI command, ensuring that sensitive customer privacy details are obfuscated for enhanced security and GDPR compliance.

I wrote an article in the past. Here it is : https://www.addeos.com/magento-2-database-anonymization-module

The module is still available on packagist here : https://packagist.org/packages/addeos/anonymize

And you can find it on the Adobe Magento Marketplace here: https://commercemarketplace.adobe.com/addeos-anonymize.html

berliozd

Magento 2 – Adding Custom Configuration – Quick Tutorial

Welcome to our comprehensive Magento 2 custom configurations guide.

In this tutorial, we'll walk you through the essential steps to seamlessly integrate and manage personalized settings for your e-commerce store. Unlock the full potential of your Magento 2 experience with our expert insights and easy-to-follow instructions.

Follow these steps to integrate your custom configuration effortlessly:

Step 1: Create your custom module

Develop a custom module if you haven't already. This typically involves setting up the necessary files and directories. Check this post for creating your first module : https://www.addeos.com/magento-2-creating-a-magento-module-a-beginners-guide

Step 2: Create system.xml file

Inside your module's etc folder, create a system.xml file. This file will define your custom configuration fields.

Step 3: Define configuration fields

Within system.xml, define your custom configuration fields using XML tags like <section>, <group>, and <field>. Specify field types, labels, and other attributes.

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <section id="custom_section" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Custom Section</label>
            <tab>general</tab>
            <resource>Magento_Config::config</resource>
            <group id="custom_group" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Custom Group</label>
                <field id="custom_field" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Custom Field</label>
                    <comment>Some description for your custom field.</comment>
                    <validate>validate-number</validate>
                </field>
            </group>
        </section>
    </system>
</config>

Step 4: Run setup upgrade command

After defining your configuration, run the setup upgrade command to apply changes:

php bin/magento setup:upgrade

Step 5: Access Configuration in the Admin Panel

Navigate to Stores > Configuration in the Admin Panel. Your custom configuration section and fields should be visible for modification.

Congratulations! You've successfully added custom configuration settings to Magento 2 through your custom module. Adjust these steps according to your specific requirements.

berliozd

Magento 2 – Creating a Magento Module: A Beginner’s Guide

Magento's modular architecture empowers developers to customize and extend functionality. In this tutorial, we'll guide you through the essential steps to create a basic Magento module.

Here is our Magento module creation guide.

Step 1: Set Up Your Development Environment

Ensure you have a Magento instance for development. Familiarize yourself with Magento's file structure and basic module concepts.
If you need to set it up quickly check Mark Shust solution : https://github.com/markshust/docker-magento

Step 2: Create the Module Directory Structure

Navigate to the app/code directory and create the directory structure for your module. For instance, if your module is named MyModule, the path should be app/code/Vendor/MyModule.

Step 3: Define Module Configuration

Inside your module directory, create a registration.php file to register your module:

<?php 
\Magento\Framework\Component\ComponentRegistrar::register( 
    \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Vendor_MyModule', __DIR__ 
);

Step 4: Create Module Configuration File

Create a module.xml file in app/code/Vendor/MyModule/etc:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_MyModule" setup_version="1.0.0"/>
</config>

Step 5: Enable the Module

Run the following command in the Magento root directory to enable your module:

php bin/magento module:enable Vendor_MyModule

Step 6: Verify Your Module

Check the enabled modules by running:

php bin/magento module:status

Your module, Vendor_MyModule, should appear in the list.

Congratulations! You've created a minimal Magento module using our Magento module creation guide. While this module doesn't include a custom controller, you can build upon this foundation to add more features and functionality as needed. Happy coding!

berliozd

Magento 2 – New logging function compatible with version 2.4.3

Magento 2 debug log 

In a previous article, I explained how I add temporary debug logs with magento 2 in my code while coding. It can be very useful, it saves me time and does not require installing additional tools. You just have to remember that this solution is used temporarily and must not be committed in the code.

The complete post is here : https://www.addeos.com/magento-2-adding…n-when-debugging

Please the read the post again to understand how to add this as a live template in phpStorm which is the IDE I am using all the time.

With Magento version 2.4.3, I now use the following function which is still working.

The logging function has to be updated to :

<?php
private function log($str)
{
    $str = 'CLASS : ' . str_pad(__CLASS__, 50, ' ')
        . ' - LINE : ' . debug_backtrace()[0]['line']
        . ' - FUNCTION : ' . str_pad(debug_backtrace()[1]['function'], 15, ' ')
        . ' - STR : ' . $str;
    $filesystem = new \Magento\Framework\Filesystem\Driver\File();
    $handler = new \Magento\Framework\Logger\Handler\Base($filesystem, 'var/log/', 'custom_logs.log');
    $loggerHandlers = ['debug' => $handler];
    $logger = new \Monolog\Logger('customlogger', $loggerHandlers);
    $logger->addDebug($str);
}

berliozd

Magento 2 – Development environment

I just made available on github a project that allows you to install a local development environment with a working version of magento within it.

Here is the url of its repo : https://github.com/berliozd/magento-env

Description

After cloning the project, you will have to execute two commands.

The first one should be executed from your local machine and will allow you to build the necessary docker containers which are described in the docker-compose.yml file.

6 docker containers will be needed:

  • php
  • nginx
  • mysql
  • redis
  • rabbitmq
  • elasticsearch

The second command must be executed from the php container.
It will create the magento project using composer. The latest version of magento (aka Adobe commerce) will be installed. At this time the latest version is 2.4.
As the magento source code is downloaded from the repository https://repo.magento.com/, you will be asked for access keys. To obtain these keys, you must have a magento developper account and access the magento marketplace at this page https://marketplace.magento.com/customer/accessKeys/.
Once the magento project is created, the script will continue with the magento installation itself.

Once this is finished, you will be able to access your new magento instance.

Step by step guide

  • clone the git projet
    git clone git@github.com:berliozd/magento-env.git .
  • run pre.sh from your local machine et the root of the git project
    docker/pre.sh
  • run bash inside the PHP container
    docker-compose -f docker-compose.mac.yml run php bash
  • run init.sh from the PHP container
    docker/php/init.sh

That's all.

You can now use that development environment to test some tutorial I wrote : https://www.addeos.com/magento-2-tutorial-adding-a-new-model-part-1-creating-the-db-table

Conclusion

It is with this solution that I am currently working on my Magento projects.
It allows me to quickly install a new instance of Magento.
I would be interested to know what solutions are used by magento developers around the world. Feel free to share in the comments how you work and how you configure your work environment.

berliozd

Magento 2 – Tutorial : new model – Part 2 – creating the PHP classes

Introduction

This article is the 2nd part of a series in which I go through the procedure to create a new model in magento 2, with its own magento 2 admin grid in the Back Office.

You can go back to the first part if you wish.

As a preamble, I have to say that this tutorial series has been developed and tested with Magento version 2.4.2.

I remind you that for the purpose of the article I am going to create a "provider" model and that our code will be contained in an "Addeos_ModelTutorial" module.

In the first part I have explained how to create the DB table using declarative XML. In this second part, I will create the PHP classes :

  • the API data interface
  • the model that implements the interface
  • the resource model
  • the collection resource model

Creating the API data interface

If we want to respect the concept of service contracts which is a good thing and recommanded by Magento, I need to create some PHP interfaces first. Here is some more details about service contracts.

By convention, these PHP interfaces have to be in an Api folder and a Data folder for data interfaces.

The first interface to create is the ProviderInterface : Api/Data/ProviderInterface.php.

Here is the code :

<?php

declare(strict_types=1);

namespace Addeos\ModelTutorial\Api\Data;

/**
 * @api
 */
interface ProviderInterface
{
    const ENTITY_ID = 'entity_id';
    const CREATED_AT = 'created_at';
    const UPDATED_AT = 'updated_at';
    const NAME = 'name';
    const DESCRIPTION = 'description';

    public function getEntityId(): ?int;

    public function setEntityId(int $entityId);

    public function getName(): ?string;

    public function setName(string $name);

    public function getDescription(): ?string;

    public function setDescription(string $description);

    public function getCreatedAt(): ?string;

    public function setCreatedAt(string $createdAt);

    public function getUpdatedAt(): ?string;

    public function setUpdatedAt(string $updatedAt);

}

Creating the PHP model

I then need to create the PHP model that will implement the interface we have just created. This PHP class will extend \Magento\Framework\Model\AbstractModel.

Here is the code :

<?php
declare(strict_types=1);

namespace Addeos\ModelTutorial\Model;

use Addeos\ModelTutorial\Api\Data\ProviderInterface;
use Magento\Framework\Model\AbstractModel;

class Provider extends AbstractModel implements ProviderInterface
{

    public function getName(): ?string
    {
        return $this->getData(self::NAME);
    }

    public function setName(string $name)
    {
        $this->setData(self::NAME, $name);
    }

    public function getDescription(): ?string
    {
        return $this->getData(self::DESCRIPTION);
    }

    public function setDescription(string $description)
    {
        $this->setData(self::DESCRIPTION, $description);
    }

    public function getCreatedAt(): ?string
    {
        return $this->getData(self::CREATED_AT);
    }

    public function setCreatedAt(string $createdAt)
    {
        $this->setData(self::CREATED_AT, $createdAt);
    }

    public function getUpdatedAt(): ?string
    {
        return $this->getData(self::CREATED_AT);
    }

    public function setUpdatedAt(string $updatedAt)
    {
        $this->setData(self::UPDATED_AT, $updatedAt);
    }
}

Creating the resource model

I now need to create resource model.

The file is Model/ResourceModel/Provider.php.

Here is the code :

<?php
declare(strict_types=1);

namespace Addeos\ModelTutorial\Model\ResourceModel;

use Magento\Framework\Model\ResourceModel\Db\AbstractDb;

class Provider extends AbstractDb
{
    protected function _construct()
    {
        $this->_init('addeos_provider', 'entity_id');
    }
}

Creating the collection resource model

I now need to create the provider collection resource model.

The file is ModelResourceModel/Provider/Collection.php.

Her is the code :

<?php

namespace Addeos\ModelTutorial\Model\ResourceModel\Provider;

use Addeos\ModelTutorial\Model\Provider;
use Addeos\ModelTutorial\Model\ResourceModel\Provider as ProviderResourceModel;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;

class Collection extends AbstractCollection
{
    protected $_idFieldName = 'entity_id';
    protected $_eventPrefix = 'addeos_provider_collection';
    protected $_eventObject = 'addeos_provider_collection';

    protected function _construct()
    {
        $this->_init(Provider::class, ProviderResourceModel::class);
    }
}

And that's all. From that point we have all the necessary classes for now.

In next post, I will explain now how to create the grid in Back Office to visualize the data of our new table.

berliozd

Magento 2 – Tutorial : adding a new model – Part 1 – creating the DB table

Introduction

Here is the first post of a series during which I will got through all the procedure to create a new model in magento 2, with its own grid in the Back Office.

Here are the steps we will have to through :

  1. Creating the DB table
  2. Creating the API data object
  3. Creating the model
  4. Creating the resource model
  5. Creating the collection resource model
  6. Creating the grid

I will cover all these steps in a series of posts.

As a preamble, I have to say that this tutorial series has been developed and tested with Magento version 2.4.2.

For the purpose of the series, we will create a simple model for a "provider" entity with the following columns :

  • id : the provider unique identifier
  • created_at : the date the provider was created
  • updated_at : the date the provider was updated
  • name : the provider name
  • description : the provider description

We will assume that our code will be held in a module Addeos_ModelTutorial.

Creating the table in DB

Rather than using InstallSchema.php file we can now use XML declarative schema definition for creating new tables, or even updating existing tables. This is available since Magento version 2.3.

We will create a db_schema.xml file.

He is the content of the file:

<?xml version="1.0"?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="addeos_provider" resource="default" engine="innodb" comment="Porviders">
        <column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="true"
                comment="Entity ID"/>
        <column xsi:type="timestamp" name="created_at" on_update="false" nullable="false" default="CURRENT_TIMESTAMP"
                comment="Created At"/>
        <column xsi:type="timestamp" name="updated_at" on_update="false" nullable="false" default="CURRENT_TIMESTAMP"
                comment="Updated At"/>
        <column xsi:type="varchar" name="name" nullable="true" comment="Name" length="50"/>
        <column xsi:type="varchar" name="description" nullable="true" comment="Description" length="50"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="entity_id"/>
        </constraint>
        <index referenceId="ADDEOS_PROVIDER_ENTITY_ID" indexType="btree">
            <column name="entity_id"/>
        </index>
    </table>
</schema>

More information on declarative schema can be found here.

Once this file is in place, you will simply need to run a setup upgrade command from your magento installation root directory :

bin/magento setup:upgrade --keep-generated

Once this is done, your new table will be present in DB.

And this is all for that first step.

In the next post I explain the different PHP classes we need to create.

berliozd