Download as pdf or txt
Download as pdf or txt
You are on page 1of 244

Development

environment
1

www.oroinc.com
Goal

● Equal understanding of the basic tools


● Share our approach to application
development

www.oroinc.com
PhpStorm IDE

● PHP and JS editor


○ DB, SQL, HTML
● Autocomplete
● Code standard checks
● Code version control
● Debug
● Tests

● and much more...

www.oroinc.com
PhpStorm Symfony Plugin

● Services autocomplete
○ Type hinting

○ Entities autocomplete
○ EntityRepository
(find/findOneBy/findAll/findBy)

● Templates autocomplete
● Routes autocomplete
● Translations autocomplete

www.oroinc.com
PhpStorm ORO Plugin


○ Layout updates, api.yml, datagrids.yml,
etc..

○ Actions, Conditions,
mass_action_provider, etc.

○ Eg. label in mass_actions

www.oroinc.com
PHP Code Sniffer in PhpStorm


○ PSR-2

● Automatic check and highlight


● Suppression
○ // phpcs:ignoreFile
○ // phpcs:disable and // phpcs:enable

Demonstration >>>
www.oroinc.com
Xdebug

● Debugger
● Profiler (not recommended)
● Configurable
● Supports remote debugging
○ https://xdebug.org/docs/remote

● Quick way to enable/disable xdebug


○ phpenmod / phpdismod xdebug + restart
○ bash script

Demonstration >>>
www.oroinc.com
Xdebug in PhpStorm

● Debug from web browser


○ Chrome extensions, eg. Xdebug helper
● Debug from CLI
○ export XDEBUG_CONFIG="remote_enable=on
idekey=PHPSTORM remote_host=127.0.0.1
remote_port=9000 remote_handler=dbgp" && export
PHP_IDE_CONFIG="serverName=YOUR_SERVER_NAME"

Demonstration >>>
www.oroinc.com
PHPUnit in PhpStorm

● Configuration
● Easy run using right click
● Debug

Demonstration >>>
www.oroinc.com
PHP Mess Detector in PhpStorm


● Configuration
● Rule sets
○ https://phpmd.org/rules/index.html
● Automatic check and highlight
● Suppression
○ @SuppressWarnings(PHPMD)

Demonstration >>>
www.oroinc.com
Excluded directories in PhpStorm




○ var/cache
■ var/cache/dev/oro_entities/Extend/Entity
○ var/logs
○ public/bundles

Demonstration >>>
www.oroinc.com
Assets via symlinks

● /console assets:install --symlink


Demonstration >>>
www.oroinc.com
Emails


○ https://mailcatcher.me/


○ mailer_transport: smtp
○ mailer_host: 127.0.0.1
○ mailer_port: 1025
○ mailer_encryption: null
○ mailer_user: null
○ mailer_password: null
Demonstration >>>
www.oroinc.com
Extras

● Terminator
○ Arrange terminals in a grid
○ Tabs, Drag and drop reordering of terminals
○ Super + g
● Grep for ERROR|CRITICAL
● Scripts for tedious tasks

Demonstration >>>
www.oroinc.com
Best Practices

● Use XDebug or any other debugger for


development, disable it if it is not needed

● Write shell scripts for often called command,


add them to /usr/bin/* to call them anywhere
(make sense only for dev environment)

www.oroinc.com
General
concepts
16

www.oroinc.com
Goal

● To get familiar with Oro applications


● How they are organized
● Components that are used

www.oroinc.com
Foundation

● Symfony Framework
○ No significant issues with adding
symfony-specific components to ORO
applications
● Doctrine ORM
○ Pay attention on the performance
● Some best practices aren’t used
○ Eg. bundles.yml / routing.yml

https://symfony.com/projects/orocrm
https://symfony.com/projects/orocommerce

www.oroinc.com
Oro applications

● OroCRM (Community and Enterprise)


● OroCommerce (Community and Enterprise)
● Akeneo PIM (external)
● Diamante Desk (external)
● Marello (external)
● All of them can* be used together, eg.
crm+commerce
● Features and differences between CE and EE
● Data volume, scalability, performance,
support and more

www.oroinc.com
Application environments

● dev
○ Symfony toolbar + ORO extensions
○ The slowest one
○ Good for debugging, mail catching etc.
○ System configuration
● prod
○ Performance optimized
○ Recommended for demo
● test
○ No demo data!

Demonstration >>>
www.oroinc.com
Application environments

● Best practices from ORO team


○ Dev env for development
○ Use prod for demo for the clients
○ Check features in prod env before
merging
○ Sometimes is worth to do clean install
○ In prod JS/assets are minified

www.oroinc.com
Structure
22

www.oroinc.com
Application directory structure

● Almost hard copy of Symfony


○ Show ORO customizations
● Customizations in /src or via composer
● /public
○ tracking.php

Demonstration >>>
www.oroinc.com
Applications and packages

● Package contains finished functionality


● Application requires one or more packages
● Packages may require other packages
● Composer package manager

www.oroinc.com
Main package dependencies

platform

platform-enterprise

crm commerce

crm-enterprise commerce-enterprise

commerce-crm
www.oroinc.com
Additional packages

● Plugins
● Integrations
● Additional functionality
● Marketplace
○ https://marketplace.orocommerce.com/
○ How to Manage Extensions

www.oroinc.com
Packages in OroCRM application

crm-application
crm
platform
crm-task-bundle
crm-call-bundle
calendar-bundle
marketing
platform-serialised-fields
crm-hangouts-call-bundle
crm-magento-embedded-contact-us
crm-dotmailer
crm-zendesk

www.oroinc.com
Dependencies of OroCRM
application

● https://github.com/oroinc/crm-application/blob/4.1/compo
ser.json#L18-L24
● https://github.com/oroinc/crm/blob/4.1/composer.json#L1
7-L21
● https://github.com/oroinc/platform/blob/4.1/composer.json
#L13-L78

www.oroinc.com
Packages and bundles

● Bundle contains finished code


● Package contains one or more bundles
○ eg. marketing
● No package manager for bundles

Demonstration >>>
www.oroinc.com
Bundle directory structure

● Resources/config/oro
● Migrations
● .md files
● and more

Demonstration code>>>
www.oroinc.com
Components and bridges

● Component
○ Abstract functionality (library)
○ No bundle dependencies
● Bridge
○ Connects several bundles

Demonstration >>>
www.oroinc.com
Relational DBMSes

● MySQL
○ Not strict SQL
○ Suitable for small applications - up to
1M of entities
● PostgreSQL
○ Strict SQL
○ Suitable for big applications - more
than 1M of entities
○ Supported only in Enterprise Edition

www.oroinc.com
Search engines
● ORM
○ Suitable for small applications
○ Stores data in the application DB
○ Implements EAV
● Elasticsearch
○ Suitable for big applications
○ Allows to configure search behaviour
○ Document based engine (NoSQL)
○ Efficient aggregation, geo queries, REST, and
more
○ Supported only in Enterprise Edition
[Admin guide]
www.oroinc.com
Message queue engines

● DBAL
○ Suitable for small applications
○ Stores data in the application DB
○ Emulates queue
○ Better for debugging
● AMQP (RabbitMQ)
○ Suitable for big applications
○ RabbitMQ allows better scaling
○ Supported only in Enterprise Edition
[Docs] & [Admin guide]

www.oroinc.com
Application configuration: Files

● Symfony
● config/config.yml ; parameters.yml
● config/security.yml
● config/routing.yml
● ORO
● <bundle>/Resources/config/oro/app.yml
● <bundle>/Resources/config/oro/routing.yml
● and others...
https://github.com/oroinc/platform/tree/4.1/src/Oro/Bundle/PlatformBundle
https://github.com/oroinc/platform/tree/4.1/src/Oro/Bundle/DistributionBundle

www.oroinc.com
Application configuration: UI

● Global: System > Configuration


● Scoped:
○ User
○ Website (EE only)
○ Organization (EE only)
● Docs

Demonstration >>>

www.oroinc.com
Best Practices & Principles

● SOLID

● GRASP (General Responsibility Assignment Software Patterns)

● KISS (Keep It Simple, Stupid)

● DRY (Don’t Repeat Yourself)

● YAGNI (You Aren't Gonna Need It)

www.oroinc.com
Application installation: CLI

● bin/console oro:install
● Additional parameters
● Might take up to 5 minutes
● Supports different environments
● Can be used in Continuous Integration
[Docs]

Demonstration >>>
www.oroinc.com
Application upgrade

● Maintenance mode
● Turn off application processes (cron, MQ)
● Create backups of your db and source code
● Get new code
● Composer install
● Remove var/cache/<environment>
● bin/console oro:platform:update
● Return everything back

[Docs]

www.oroinc.com
Cron

● bin/console oro:cron
● Triggers other commands
● Has to be executed every minute
● */1 * * * *
● It has to be prefixed with oro:cron
[Docs]

Demonstration UI + console >>>


www.oroinc.com
Message queue consumer

● bin/console oro:message-queue:consume
● -vvv for more verbosity
● Supervisor
● Message limit
● Time limit
● Memory limit

Demonstration console >>>

www.oroinc.com
Logger

● Use everywhere
● Use in critical places
● Use in the integrations
● Correct logging level
● Context

[Example]

www.oroinc.com
How to find required code

● Search by labels
● Search by HTML (tags, classes)
● Use Symfony Profiler
● Set breakpoints
● Regex in Phpstorm

Demonstration >>>

www.oroinc.com
Best Practices
● Make sure your application can be installed from scratch
unless there is no other way but use DB dumps (make sense
only for development to have an easy way to reinstall an app)

● Make local dev environment as close to prod as possible - i.e.


use the same DBMS, cache storage, search engine and
message queue

● It is recommended to use dev environment for development


and when task/feature is finished it has to be checked in prod
environment

● Never use production servers for development purpose!

www.oroinc.com
Best Practices
● If you are planning to use the same code in multiple projects
then it is recommended to put it to the separate bundle /
component and add it using composer.json, use company name
as first part of the namespace - e.g. Oro/Bundle/UserBundle

● Define bundle/component responsibility in README file and


make sure to follow this definition

● If bundle / component is used to override existing functionality


from another bundle / component - call it the same, e.g.
AcmeCompany/Bundle/UserBundle may override pieces of
Oro/Bundle/UserBundle

www.oroinc.com
Best Practices
● Write documentation based on the experience of the
developers who will work with the code; if they are
seniors - mention only very unusual solutions (maybe
only as a comments in code), if they are juniors -
document bundle / component responsibility, relations
to other bundles, structure, algorithms, entities, API
calls, layout structure and providers etc.

● Do not spend extra time on documentation unless it’s


really necessary

www.oroinc.com
Documentation

● Documentation in bundles
● https://doc.oroinc.com
● https://www.slideshare.net/OroCRM/present
ations
● https://www.youtube.com/channel/UC9ougJg
KzJd-ZxrLuvBqZLg
● Use Google

www.oroinc.com
Testing
48

www.oroinc.com
Goal

● Show you what type of tests we have in ORO


codebase

Q: why do we need tests?

www.oroinc.com
Why do we need tests?

● Reliability
● Better code quality
● Coverage of business use cases
● Continuous integration

www.oroinc.com
Types of tests in Oro application

● Unit tests
● Functional tests
● Behat tests

www.oroinc.com
Unit tests
● Tests for separate PHP classes
● No interaction with storages
● Mocks
● Minimum environment setup
● Do not require installed application
● Validate behaviour on class level
● Very fast (milliseconds)
● <bundle>/Tests/Unit

www.oroinc.com
Functional tests
● Tests for backend functionality
● Interactions with storages (DB, search index)
● Minimum number of mocks
● Require application installed in test mode
● Validate behaviour on bundle and
component levels
● Average speed (seconds)
● <bundle>/Tests/Functional

www.oroinc.com
Behat tests

● Test for whole application


● Real application
● Real business use cases
● Require application installed in prod mode
○ Recommendation: separate application
● Validate behavior on the application level
● Slow (seconds-minutes)
● <bundle>/Tests/Behat

Demonstration >>>
www.oroinc.com
How to run tests

● PHPUnit
● Run from CLI
● Run from PhpStorm
● Integration with PhpStorm

Demonstration >>>
www.oroinc.com
Good tests

● Isolated, do not depend on each other


● Validate initial state
● Validate result
● Validate state after operation
● Covers positive and negative cases
● One operation at a time
● Describe what they are testing

[Example]

www.oroinc.com
Bad tests

● Not isolated
● Don’t validate state or result
● Lots operations in one test
● Hard to read
● Hard to change
● Coupled

www.oroinc.com
Code review

● Ensures quality of the code


● Indicates common issues
● Improves qualification of developers
● Experience sharing
● “Live review”
● Separate application for code review

[Best practices]
[Tips and FAQ]

www.oroinc.com
Code review workflow

www.oroinc.com
Code review checklist

● Functional review
● Architectural review
● Implementation review
● Automated tests
● Documentation

[Full checklist]

www.oroinc.com
Best Practices

● Set up Continuous Integration as soon as you’ll


have time for it, test application in production
environment there
● Write behat tests if possible, use existing
elements and contexts from Oro as much as
possible
● Cover critical parts of the functionality with
unit and functional test to guarantee that they
work properly

www.oroinc.com
Extend functionality
with bundles

www.oroinc.com
Service/parameter overriding

● Define service/parameter with the same name


● Only the latest definition is used

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/EntityB
undle/Resources/config/services.yml#L2-L7

Demonstration code, e.g. in customization >>>

www.oroinc.com
Service decoration

● Decorates original service


● Can inject original service into decorator
● Most of the time, the decorator should be
declared private

https://github.com/oroinc/orocommerce/blob/4.1/src/Oro/Bundle/
WebsiteSearchBundle/Resources/config/services.yml#L90-L96

www.oroinc.com
Compiler passes
● Dynamic manipulations with services and
parameters
● Allows to add custom logic during the
compilation of DIC
● Examples
○ Add method call
○ Change class

www.oroinc.com
Overriding at the application level

● Allows to override parts where bundle based paths


are used (e.g. @OroUserBundle)
○ Controllers
○ Templates
● All custom files have to be at the
src/Resources/<bundle> directory

[Symfony Doc on overriding a part of a bundle]


[Override templates in ORO]

www.oroinc.com
Routes overriding
● Define routes with the same name
● The latest route wins
● Might be used to override controllers

www.oroinc.com
Template inheritance

● Uses {% extends %} tag


● Allows to redefine or extend blocks
● parent()
● Use ! when you extend template that you override

{% extends '!OroUI/actions/update.html.twig' %}

www.oroinc.com
Template placeholders

● New twig token parser


○ extends \Twig_TokenParser
● Uses {% placeholder %} tag
● Allows to inject required blocks at the defined
positions (similar to events)

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UIBun
dle/Resources/views/actions/view.html.twig#L51-L58

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/DataA
uditBundle/Resources/config/oro/placeholders.yml

www.oroinc.com
Twig extensions
● Filters
○ ‘label’|trans
● Functions
○ oro_currency_name(currency)
● Tests
○ value is defined
● Operators
○ value == value
● Globals
https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/Entit
yBundle/Twig/EntityExtension.php

www.oroinc.com
Form extensions

● Add features on top of existing types


○ Add specific feature to a single type
○ Add generic feature to several types
● Cases
○ Add new fields to forms
○ Process submitted data
○ Modify existing form behaviour

[Symfony documentation]

www.oroinc.com
Configuration files

● config/config.yml
● <bundle>/Resources/config/oro/app.yml
● bin/console debug:config --help

https://github.com/oroinc/orocommerce-application/blob/4.1/co
nfig/config.yml#L37-L43

https://github.com/oroinc/orocommerce/blob/4.1/src/Oro/Bundl
e/CMSBundle/Resources/config/oro/app.yml

www.oroinc.com
Events

● Presented in all components


● Allow to change data or behaviour
● ORO Events, eg. Datagrid, Import, UI
○ <bundle>/Event
● Doctrine Events, eg. Lifecycle
● Symfony Events, eg. Form, Kernel

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/D
ataGridBundle/Datagrid/Builder.php#L89-L90

www.oroinc.com
Best Practices
● It’s faster to override service instead of fixing the
arguments with Compiler Pass
● You may enable autowiring and autoconfiguration for
endpoint application
● Do not use bundle inheritance
● If you need to override only one route - create new
controller and define route with the same name

www.oroinc.com
Best Practices

● If you need to override whole controller - extend original


controller class and override routing resource that was
used to define the original controller class
● If controller is defined as a service - you may override
whole service
● If some business logic is needed inside the template and
there is no easy way to call if from controller or model
layer then create twig extension to proxy calls of service
methods

www.oroinc.com
Extend functionality
with bundles:
Practice session
76

www.oroinc.com
● add bundle Training/UserNamingBundle

● decorate Oro\Bundle\LocaleBundle\
Provider\EntityNameProvider service

● render name of a User using custom format -


"<LastName> <FirstName> <MiddleName>"

● (optional) add block to User view page and render


there full name and all name parts (prefix, first name,
middle name, last name, suffix)

www.oroinc.com
Entities
and their data

www.oroinc.com
Entities

● PHP classes and objects


● Used to map data by ORM
● Have related repositories
● Define metadata using Doctrine annotations
● Might contain data storage logic
● Might contain lifecycle callbacks (events)
● Usually stored at <bundle>/Entity

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserB
undle/Entity/Group.php

www.oroinc.com
Entity repositories

● Used to find and retrieve entities via ORM


● Might contain custom methods
● Usually stored at <bundle>/Entity/Repository
● Has to be requested from entity manager
● Default repository is Doctrine\ORM\EntityRepository
● LoadClassMetadataEventArgs
○ Useful for customizations

[Example]
www.oroinc.com
Quiz
$this
->getDoctrine()
->getManager()
->getRepository(Config::class)
->findAll();

● What will be the result of such a call?

Demonstration >>>
www.oroinc.com
Entity managers

● Used to manage ORM data (including entities


and repositories)
● One entity manager per DB connection
● Has to be requested from ManagerRegistry

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/Platfor
mBundle/Resources/config/oro/app.yml

www.oroinc.com
Avoid using default manager

$this
->getDoctrine()
->getManager()
->getRepository(Config::class)
->findAll();

● The class
'Oro\Bundle\ConfigBundle\Entity\Config' was
not found in the chain configured namespaces

Demonstration >>>
www.oroinc.com
Get entity using
ManagerRegistry

www.oroinc.com
Get entity using
DoctrineHelper

www.oroinc.com
Entity configuration

● Stores metadata related to entities and entity fields


○ Eg. attachments, auditable (field)
● Data is stored into fields grouped into scopes
○ Resources/config/oro/entity_config.yml
● Defined using Oro annotations @Config and
@ConfigField
● Developer may add custom scopes and fields

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/ContactBundle/
Entity/Contact.php

www.oroinc.com
Entity configuration: CLI commands

● bin/console oro:entity-config:update
○ Updates configuration data for entities.

● bin/console oro:entity-config:cache:clear
○ Clears the entity config cache.

● bin/consol oro:entity-config:cache:warmup
○ Warms up the entity config cache.

www.oroinc.com
Entity configuration: UI

● Attachments
○ Contact entity - view page
○ Enable attachments
○ Update schema + (optional) show DB
○ Add attachment to Contact
● Auditable
○ Edit firstName
○ Show change history
○ Disable auditable
○ Show change history

www.oroinc.com
Extended entities

● Allow to add custom fields and relations to existing


entities
● Intermediate layer with custom data is represented
by a class in <bundle>/Model/
● Real auto generated classes are stored at
var/cache/<env>/oro_entities/Extend/Entity

[Video presentation]

www.oroinc.com
Extended entities: Code

● Examples
○ Add field to an extended entity
○ Add relation to an extended entity
● Extend extension

www.oroinc.com
Extended entities: UI

● Contact - UI
○ Create field products (one-to-many to Product)
○ Edit any Contact -> add products
● Contact - code
○ cache

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/ContactBundle/
Entity/Contact.php

www.oroinc.com
Custom entities

● Allow to add completely new entities with


custom fields and relations
● Custom entities work the same way as extended
entities
● Simple CRUD out of the box

www.oroinc.com
Custom entities: UI

● Create new entity


● Show CRUD
● Create relation Contact -> New entity (many-to-one)
● Assign to Contact
● Show view, grid, inline edit
● Show cache
● Show DB

www.oroinc.com
Migrations

www.oroinc.com
Bundle installation

● Tool for DB structure and data migrations


○ Only “up” method (Migration interface)
● Bundle version
○ OroPlatformBundle v1_1
● Installer
● Migrations
● Data fixtures
● Demo data fixtures

Demonstration >>>
www.oroinc.com
Bundle version

v1_0 Installer v1_0

Installer v1_1
v1_1 Migration v1_1

Installer v1_2
v1_2 Migration v1_1 Migration v1_2

www.oroinc.com
Installer

● Contains version (preferably the latest one)


● Set up DB schema for a bundle
● Might contain queries and extensions
● No interaction with ORM
● Migrations/Schema/<bundle>Installer.php
○ MigrationsLoader
○ MigrationExecutor

https://github.com/oroinc/orocommerce/blob/4.1/src/Oro/Bundle/Pro
ductBundle/Migrations/Schema/OroProductBundleInstaller.php

www.oroinc.com
Migrations

● Adjust existing DB schema


● Might contain queries and extensions
● No interaction with ORM
● Migrations/Schema/<version>/<file>.php
● OrderedMigrationInterface
● preQueries and postQueries
● bin/console oro:migration:load

https://github.com/oroinc/orocommerce/blob/4.1/src/Oro/Bundle/P
roductBundle/Migrations/Schema/v1_9/MakeVisibleDefaultProductA
ttributes.php
www.oroinc.com
Data fixtures

● Doctrine DataFixtures
● No version (usually)
● Interaction with ORM
● Types
○ Dependent, ordered, versioned
● Migrations/Data/ORM/<file>.php
● bin/console oro:migration:data:load

https://github.com/oroinc/orocommerce/blob/4.1/src/Oro/Bundle
/ProductBundle/Migrations/Data/ORM/LoadProductUnitData.php

www.oroinc.com
Demo data fixtures

● Load demo entities


○ Useful for demo with the client
○ Show the features with generated data
● Migrations/Data/Demo/ORM/<file>.php
● bin/console oro:migration:data:load
--fixtures-type=demo

https://github.com/oroinc/orocommerce/blob/4.1/src/Oro/Bund
le/ProductBundle/Migrations/Data/Demo/ORM/LoadProductDe
moData.php

www.oroinc.com
MigrationBundle

● https://doc.oroinc.com/backend/bundles/platf
orm/MigrationBundle/
● https://doc.oroinc.com/backend/entities-data-
management/data-fixtures/

www.oroinc.com
Datagrid

www.oroinc.com
Datagrid

● Table oriented representation of some data


from some datasource
● Several data sources (including ORM)
● Builds ORM query based on configuration
● Applies filtering, sorting and pagination
● Supports inline editing
● Allows to execute single and mass actions

Demonstration UI >>>
www.oroinc.com
Configuration of datagrid
● ORM query - select, from, where, groupBy
● Columns - label, frontend type
● Filters - type, data name
● Sorters - data name, default
● Properties
● Single actions and mass actions
● Resources/config/oro/datagrids.yml

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserB
undle/Resources/config/oro/datagrids.yml

www.oroinc.com
Customization of datagrid

● Merge grid configuration - be careful


● Grid extends grid
● Grid events
○ Builder - buildBefore, buildAfter
○ Datasource - resultBefore, resultAfter
● Grid extensions
https://github.com/oroinc/orocommerce/blob/4.1/src/Oro/Bundle/C
atalogBundle/EventListener/DatagridListener.php#L50-L54

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/EntityP
aginationBundle/Datagrid/EntityPaginationExtension.php

www.oroinc.com
Datagrid - exercise

● Disable firstName filter from Contacts grid


● You can use the easiest way

PS. You don’t need to clear the cache :)

www.oroinc.com
Entity index page

● Route without parameters


● Contains datagrid and actions for all entities
● Uses index template

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserB
undle/Controller/GroupController.php#L70-L75

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserB
undle/Resources/views/Group/index.html.twig

www.oroinc.com
Entity CRUD

● Create
● Read
● Update
● Delete

www.oroinc.com
Read: Code

● Get specific entity from a repository


● EntityRepository::find*
● Read entities are stored in UnitOfWork

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/DemoData
Bundle/Migrations/Data/Demo/ORM/LoadGroupData.php#L77

www.oroinc.com
Read: Controller

● Route with entity ID


● Entity is passed as an argument
● Uses view template

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserBu
ndle/Controller/UserController.php#L40-L46

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserBu
ndle/Resources/views/User/view.html.twig

www.oroinc.com
Create: Code
● Create entity object
● EntityManager::persist
● EntityManager::flush
● Created entities are stored in UnitOfWork

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/ContactBu
ndle/Migrations/Data/ORM/LoadSourceData.php

www.oroinc.com
Create: Controller

● Route without parameters


● Create new entity object and submit form
● Usually uses update template

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserB
undle/Controller/UserController.php#L121-L126

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserB
undle/Resources/views/User/update.html.twig

www.oroinc.com
Update: Code
● Get entity
● Change entity
● EntityManager::persist
● EntityManager::flush

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserB
undle/Migrations/Data/ORM/UpdateUserEntitiesWithOrganization.p
hp#L39-L56

www.oroinc.com
Update: Controller

● Route with entity ID


● Entity is passed as argument
● Uses update template

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserBu
ndle/Controller/UserController.php#L143-L146

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserBu
ndle/Resources/views/User/update.html.twig

www.oroinc.com
Delete: Code

● Get entity
● EntityManager::remove
● EntityManager::flush
● Deleted entities are removed from UnitOfWork

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserBu
ndle/Entity/BaseUserManager.php#L119-L121

www.oroinc.com
Delete: Controller

● No need to have it
● Actions added automatically
○ or via API, e.g. oro_api_delete_contact
○ [More info]

www.oroinc.com
Menu

● Uses KnpMenuBundle
● ORO: NavigationBundle
● Represented by a tree structure
● Label
● Route
● Position
● Resources/config/oro/navigation.yml

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserB
undle/Resources/config/oro/navigation.yml

www.oroinc.com
Customization of menu
● UI
● Config - Resources/config/oro/navigation.yml
● ConfigureMenuEvent
○ oro_menu.configure.<menu_name>
● Menu extension
○ oro_navigation.menu_extension
● Menu builder
○ oro_menu.builder
● + page titles

[example]

www.oroinc.com
Menu - exercise

● Add via navigation.yml new menu item


● Label: ‘My custom contacts’
● Position: just before ‘Contacts’
● Route: oro_contact_index

www.oroinc.com
Validation

● Validates entity data


● Can be assigned to fields or whole entity
● Developer might add custom constraints
● Triggered automatically on form submission
● Can be triggered using validator service
● Resources/config/validation.yml

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/ContactBu
ndle/Resources/config/validation.yml

www.oroinc.com
Search

● Creates search index for entities and allows to


perform search using this index
● Specify fields and relations used to search
● Allows to add custom/modify data
○ oro_search.prepare_entity_map
● Allows to build custom queries
○ example
● Resources/config/oro/search.yml
○ example

www.oroinc.com
Search demo
● UI - quick search
● API - simple + advanced
○ search=Debra from=oro_contact
○ select firstName from oro_contact where
firstName ~ 'Debra'
● DB - structure
● bin/console oro:search:reindex
○ --scheduled !!!
● QueryBuilder
○ Oro\Bundle\SecurityBundle\Search\AclHel
per::apply

www.oroinc.com
Search docs

● https://doc.oroinc.com/backend/bundles/platform/S
earchBundle/
● Search Component Architecture
● Configuration file structure

www.oroinc.com
Autocomplete

● Uses search index as a data source by default


● Can be customized by developer
● Used by form type to select entities
○ Form type example
○ Autocomplete handler example

Demonstration >>>
www.oroinc.com
Name provider

● Direct text representation of entity object


● DQL string to get text representation from DB
● Used all over the system
● Developer can add custom name providers

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/ContactBun
dle/Provider/ContactEntityNameProvider.php

www.oroinc.com
Name provider demo

● UI - contact
● ContactEntityNameProvider
● Twig: entity|oro_format_name

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/Locale
Bundle/Resources/doc/reference/name-formatting.md

https://doc.oroinc.com/user/back-office/system/localization/

www.oroinc.com
Entity aliases

● Simple and elegant way of referring to entities


● Text representation of entity class
● Have singular and plural forms
● Used all over the system
○ API, dictionaries, pass entity class via URL
● Resources/config/oro/entity.yml

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/EntityBundle
/Resources/doc/entity_aliases.md

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/UserBundle/
Resources/config/oro/entity.yml

www.oroinc.com
Virtual fields and relations

● Additional fields or relations


● Can be used only to view data
● Good for reports or API
● Resources/config/oro/entity.yml

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/ContactBu
ndle/Resources/config/oro/entity.yml#L2-L38

www.oroinc.com
Best Practices
● Use standard Doctrine fields, relations and entities
instead of the extended ones if possible
● If you need bidirectional relations to Oro core entity - use
extended relations
● If you need to work with entities really fast (e.g. import
them very fast) - use plain SQL through Doctrine DBAL
(e.g. Doctrine\DBAL\Query\QueryBuilder) instead of
Doctrine ORM, but remember that in this case all
functionality that works on Doctrine events (data audit,
search reindexation) will not work and you have to handle
it manually

www.oroinc.com
Best Practices
● Avoid Doctrine object hydration if you work with lots of
entities (performance issue), use array hydration instead
● You may add or modify Doctrine annotations of an
existing entity class or an existing field with
LoadClassMetadata event
● You may disable some event listeners completely (by
removing the specific services) or temporary (see
OptionalListenerInterface and --disabled-listeners CLI
command option)
● Do not define repository as a service

www.oroinc.com
Best Practices
● New section to datagrid configuration (column,
filter, sorter, action etc) can be added using
datagrids.yml file only - configuration sections
are simply merged there
● Make sure that all visible static values are
translated - e.g. field labels
● Make sure that all visible dynamic values are
localized - e.g. date/times, decimal / money
values, localizable values

www.oroinc.com
Security and
Access Control
Lists

www.oroinc.com
General information

● Permissions are assigned to user roles


● Each user has one or more roles
● Users are grouped in business units
● Business units have hierarchy
● Business units relate to organization

https://doc.oroinc.com/backend/security/example/

www.oroinc.com
Ownership
● Entity may have an owner
● Owner is represented by one of the entities:
○ User
○ Business Unit
○ Organization (EE only)
● Owner is used to check permissions
● Specified at the entity configuration

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/ContactBun
dle/Entity/Contact.php#L51-L57

www.oroinc.com
Security

● Two types of ACLs:


○ Entity based
○ Action based (capabilities)

Demonstration >>>

www.oroinc.com
Entity permissions

● Permissions
○ VIEW, CREATE, EDIT, DELETE, ASSIGN, …
○ permissions.yml
● Access levels without ownership
○ None, Global
● Access levels with ownership
○ None, User, Business Unit, Division,
Organization, Global

[Documentation]
www.oroinc.com
Entity permissions

● ACL can be enabled using entity configuration


○ security scope
● Make sure to run
○ bin/console oro:entity-config:update

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/ContactBu
ndle/Entity/Contact.php#L58-L62
www.oroinc.com
Ownership Access Levels

Global

Organization

Division

Business Unit

User

None
www.oroinc.com
How to define entity permissions

● Controller annotations
○ [example]
● Resources/config/oro/acls.yml
○ [example]

www.oroinc.com
How to check entity permissions

// PHP code
$checker = $this->container->get('security.authorization_checker');
$checker = $this->container->get(AuthorizationCheckerInterface::class);

if ($checker->isGranted('VIEW', $entity)) {

.yml
acl_resource: acl_name

{# Twig template #}

{% if is_granted('VIEW', entity) %}

{% endif %}

www.oroinc.com
Example: Call center
Administrator

Manager of organization

Manager of call center

Manager of Department Manager of Department Manager of Department


A B C

Operato Operato Operato Operato Operato Operato


rA1 rA2 rB1 rB2 rC1 rC2

www.oroinc.com
Example: Operator

● Requirement: Operator must be able to see only


contacts assigned directly to him

www.oroinc.com
Example: Operator

● Requirement: Operator must be able to see only


contacts assigned directly to him
● Contact owner: User (Operator)
● ACL:
○ Permission=VIEW
○ Level=User

www.oroinc.com
Example: Manager of department

● Requirement: Manager of department must be able


to see contacts assigned to operators in his
departments

www.oroinc.com
Example: Manager of department

● Requirement: Manager of department must be


able to see contacts assigned to operators in
his departments
● ACL:
○ Permission=VIEW
○ Level=Business Unit
● Manager of department and all operators has
to be in the same business unit

www.oroinc.com
Example: Manager of call center

● Requirement: Manager of call center must be able


to see all contacts processed by call center

www.oroinc.com
Example: Manager of call center

● Requirement: Manager of call center must be


able to see all contacts processed by call center
● ACL:
○ Permission=VIEW
○ Level=Division
● Business unit of manager of call center must
include all department business units

www.oroinc.com
Example: Manager of organization

● Requirement: Manager of call center organization


must see all contacts in his organization

www.oroinc.com
Example: Manager of organization

● Requirement: Manager of call organization


must see all contacts in his organization
● ACL:
○ Permission=VIEW
○ Level=Organization
● Manager and department business units must
be in the same organization

www.oroinc.com
Example: Administrator

● Requirement: Administrator must see all contacts

www.oroinc.com
Example: Administrator

● Requirement: Administrator must see all contacts


● ACL:
○ Permission=VIEW
○ Level=Global

www.oroinc.com
Example: Call center with hierarchy
Administrator

Organization: Random Inc.


Manager of organization

BU: Call center


Manager of call center

BU: Department A BU: Department B BU: Department C

Manager of Manager of Manager of


Department A Department B Department C

Operator Operator Operator Operator Operator Operator


A1 A2 B1 B2 C1 C2

www.oroinc.com
Action permissions (capabilities)

● Binary values - On/Off


● No action access levels (User, …, Global)
● No permissions (VIEW, EDIT, …)

Demonstration UI >>>

www.oroinc.com
How to define action permissions

● Controller annotations - example


● Resources/config/oro/acls.yml - example

www.oroinc.com
How to check action permissions
// PHP code
$checker = $this->container->get('security.authorization_checker');
$checker = $this->container->get(AuthorizationCheckerInterface::class);

if ($checker->isGranted('capability_name')) {

.yml
acl_resource: capability_name

{# Twig template #}

{% if is_granted('capability_name') %}

{% endif %}

www.oroinc.com
More

● Workflow permissions
● Field based ACL

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bridge/TaskCRM/
Migrations/Data/ORM/CrmRoles/workflows.yml

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/Secur
ityBundle/Resources/doc/field-acl.md
www.oroinc.com
Docs
https://doc.oroinc.com/user/back-office/system/user-management/roles/

https://doc.oroinc.com/backend/security/

www.oroinc.com
Best Practices

● Almost all controller actions, links and buttons


have to be covered with ACL checks
● Feel free to add new ACL capability for each
unusual operation

www.oroinc.com
Security and
Access Control Lists:
Practice session
159

www.oroinc.com
● add security section to UserNamingType entity
○ no ownership

● apply ACL resources


○ to controller
○ to both datagrids (types and related users)
○ make sure they work (e. g. manually create role from
UI and check)

● (optional) show grid of related users on type view page


only if user has VIEW permission for User entity

● (optional) add ACL capability to allow showing of naming


information at user view page

www.oroinc.com
Import and Export
of Entities

www.oroinc.com
General information

● Uses AkeneoBatchBundle
● Works asynchronously (via consumer)
● Executed in parallel
● Used by integrations with data sync

https://docs.spring.io/spring-batch/trunk/reference/html/do
main.html

www.oroinc.com
Jobs

● Used to trigger import and export


● Consist of three parts:
○ Reader
○ Processor
○ Writer
● Resources/config/batch_jobs.yml

https://github.com/oroinc/platform/blob/4.1/src/Oro/Bundle/Import
ExportBundle/Resources/config/batch_jobs.yml

www.oroinc.com
Reader > Processor > Writer
Reader
● reads data rows from data source
● returns one data row at a time

Processor
● processes one data row
● returns one processed data row at a time

Writer
● receives batch of data rows
● saves data rows to data source
www.oroinc.com
Processors

● Accept, process and return one data row


● DIC tag oro_importexport.processor
● Consist of following parts:
○ Data converter
○ Serializer
○ Strategy (optional)

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/ContactBu
ndle/Resources/config/importexport.yml

www.oroinc.com
Data Converters

● Convert header of import/export file to


complex array
● Extend [AbstractTableDataConverter] to create
custom data converters

[Custom Data Converter]

[Custom Data Converter - definition]

[Default Data Converter]

www.oroinc.com
Normalizers

● Responsible for normalization and


denormalization of entity
● Normalization -> convert entity object to array
● Denormalization -> convert array to entity
object
● Default serializer [ConfigurableNormalizer]

[Symfony serializer]

[Custom Normalizer example]

www.oroinc.com
Import Strategy

● Responsible for the import logic processing,


such as adding new records or updating the
existing ones.

● Default strategy [ConfigurableAddOrReplace]

[Custom Strategy]
[Custom Strategy - definition]

www.oroinc.com
Processor types
● import_validation
● import
● export_template
● export

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/ContactBun
dle/Resources/config/importexport.yml

www.oroinc.com
Import Validation
CSV File Reader

Import Processor
● Data converter
● Serializer
● Strategy

Null Writer

www.oroinc.com
Import
CSV File Reader

Import Processor
● Data converter
● Serializer
● Strategy

Entity Writer

www.oroinc.com
Export template
Template Fixture Reader

Export Processor
● Data converter
● Serializer

CSV File Writer

www.oroinc.com
Export
Entity Reader

Export Processor
● Data converter
● Serializer

CSV File Writer

www.oroinc.com
Entity field configuration

● @ConfigField annotation
● Section/scope: importexport
● Fields:
○ header
○ order
○ identity
○ excluded
○ short
● UI

www.oroinc.com
Entity field configuration: Example

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/SalesBundle/Entit
y/Lead.php

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/SalesBundle/Res
ources/config/importexport.yml

www.oroinc.com
Import and Export buttons

● OroImportExportBundle:ImportExport:
○ buttons.html.twig
○ buttons_from_configuration.html.twig
● Pass entity class and processor aliases
● Usually placed at index page

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/SalesBundl
e/Resources/views/Lead/index.html.twig#L9-L11

https://doc.oroinc.com/backend/integrations/import-export/

www.oroinc.com
Potential issues

● Configuration:
○ Problem: Need to use custom data format
○ Solution: Implement custom data converter,
serializer, strategy or whole processor
● Performance:
○ Problem: Too slow (because of ORM)
○ Solution: Work directly with DBAL

www.oroinc.com
Best Practices

● If you need to import small amount of entities


(up to 5k-50k) and Oro has built-in CSV import
with all required fields - convert data to Oro
format and use built-in import
● If you need to do import only once (initial
import) and Oro has no built-in import - write
CLI command and import entities using
standard Doctrine features, do not use
ImportExportBundle functionality

www.oroinc.com
Best Practices

● If you need to implement new import/export processor


and you’re not planning to reuse existing data converters /
normalizers / strategies - put all your logic inside the
processor class instead of splitting it into three layers
(KISS)
● If you’re using custom import - don’t forget to trigger
validation of entities
● Standard configurable import/export is pretty easy to set
up for a new entity with scalar fields and simple relations,
but it’s quite hard to customize and it’s not very fast

www.oroinc.com
Import and Export
of Entities:
Practice session
180

www.oroinc.com
● Add simple import and export for UserNamingType
entity
○ available from index page
○ use default data converter, serializer and strategy
○ use buttons_from_configuration.html.twig macro
to display buttons

● (optional) Add UserNamingType entity validation


○ title and format must not be empty and have
proper length

● (optional) Add import template

www.oroinc.com
API

www.oroinc.com
General information

● FOSRestBundle and NelmioApiDocBundle


● JSON.API specification
○ http://jsonapi.org/
● Supported authentication methods
○ WSSE (OOTB)
○ oAuth2 (via extension) - recommended
● Supports HATEOAS
● Requires User API Key
● Custom entities, dictionaries and enum
accessible by default

www.oroinc.com
General information
● Based on the ChainProcessor
○ Organizes data processing flow
● Commands
○ oro:wsse:generate-header
○ oro:api:cache:clear
○ oro:api:doc:cache:clear
○ oro:api:debug
○ more
● Sandbox (/admin/api/doc & /api/doc)
● Plain API is outdated!!
Demonstration UI - sandbox >>>

www.oroinc.com
Authentication - oAuth2
● Generate private/public keys - configuration
○ var/oauth_private.key & var/oauth_public.key
● Add application

www.oroinc.com
Authentication - oAuth2
● Copy Client ID and Client secret

www.oroinc.com
Authentication - oAuth2
● Generate token
(e.g. using
Postman)

○ Endpoint:
/oauth2-token

www.oroinc.com
Authentication - oAuth2
● Add generated token to request header

www.oroinc.com
Actions

● Get - GET <entity>/<id>


● Get list - GET <entity>
● Create - POST <entity>
● Update - PATCH <entity>/<id>
● Delete - DELETE <entity>/<id>
● Delete list - DELETE <entity>

www.oroinc.com
General configuration

● Entity based
● Generated automatically for specified entities
● Custom entity aliases
● Excluded entities and fields
● Filters
● Sorters
● Validation
● X-Include header

www.oroinc.com
Entity configuration

● May be excluded
● Documentation (!)
● Max results
● Default order
● Form to process create and edit
● Delete handler

[Documentation]

www.oroinc.com
Field configuration

● May be excluded
● Data type
● May refer to other property (property path)
● Symfony Form Data transformers are used
● Form to process create and edit
● Meta property

[Documentation]
www.oroinc.com
Filters configuration
● May be excluded
● Data type
● Multiple values
○ allow_array: true + comma separated (see: notes)
● May refer to other property (property path)
● Operators
● Custom filters + custom options: config
● Added for fields with indexes by default

[Documentation]

www.oroinc.com
Sorters configuration

● May be excluded
● May refer to other property (property path)
● Added for fields with indexes by default

[Documentation]

www.oroinc.com
Actions configuration

● May exclude some actions


● ACL protection
● Page size
● Fields
● Form to process create and edit
● If an option exists in both entity and action
configurations the action option wins

[Documentation]

www.oroinc.com
Processors

● Custom processing for API requests


● May contain business logic of Data API
● May change configuration and data
● DIC tag oro.api.processor
● Conditions
○ Action
○ Group
○ Class
● Priority
[Documentation] & [Example]

www.oroinc.com
Context
● Stores configuration, metadata, request and result
● Action specific
● Passed to all processors
● Data can be changed
○ Example

[Documentation]
www.oroinc.com
Processor Groups

● Action specific
● Executed one by one
● Processors inside the same group are
executed according to their priority
● bin/console oro:api:debug

[Documentation]

www.oroinc.com
X-Include header

● Returns additional information


● Developer may add custom includes

[Documentation]

www.oroinc.com
Example
https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/SalesBundle/Res
ources/config/oro/api.yml

www.oroinc.com
Documentation

● How to
○ Add a custom controller
○ Expose an API for non-entity resource
○ Enable custom API

www.oroinc.com
API:
Practice
session
202

www.oroinc.com
● add default API for UserNamingType entity

● (optional) add filter and sorter by title

● (optional) set custom alias for whole application


(not only for API)

● (optional) add example of formatted name as a meta


field to get and get_list requests
○ has to be done using processors

https://doc.oroinc.com/backend/api/configuration/#fields-config

www.oroinc.com
Integrations

www.oroinc.com
What is integration?

● Interaction with 3rd party application


● Credentials
● RPC, SOAP, REST
● Import and export of entities

During implementation - find a balance


between cost and performance

www.oroinc.com
Ways to integrate

● Simple controller or CLI command with


hardcoded configuration
● Simple controller or CLI command with
configuration in the system configuration
● Proper implementation with configuration at
the system configuration
● Proper implementation with configuration at
the integration channel

www.oroinc.com
Simple controller or CLI command with
hardcoded configuration

+ Easy to build
+ Quick implementation
- Not configurable
- Not flexible
- Hard to support
- Only one instance

www.oroinc.com
Simple controller or CLI command with
configuration at the system configuration

+ Easy to build
+ Quick implementation
+ Configurable
- Not flexible
- Hard to support
- Only one instance

www.oroinc.com
Proper implementation with configuration at the
system configuration

+ Configurable
+ Flexible
+ Easy to support
- Hard to build
- Slow implementation
- Only one instance

www.oroinc.com
Proper implementation with
configuration at the integration channel

+ Configurable
+ Flexible
+ Easy to support
+ Multiple instances
- Hard to build
- Slow implementation

www.oroinc.com
Configuration sources

● System configuration
○ One on the global level
○ One per each scoped entity
■ (ex. Organization -> MS Exchange) todo:
remove
● Integration channels
○ Any amount of integrations
○ Ability to trigger data synchronization
○ Log
Demonstration UI >>>

www.oroinc.com
Integration (sync)

● Import and export via connectors


● Asynchronous (via message queue)
○ But only on a single integration level
○ All connectors and batches run in a single
process
● Request history (statuses)
● oro:cron:integration:sync
● Runs automatically every 5 minutes

Demonstration UI + console >>>


www.oroinc.com
Integration flow (direct sync)

● Sync from (ex. manually click sync button)


● MQ
● SyncProcessor::process()
● Iterate over all connectors
● Execute Import job
○ Reader - connector (uses transport to call
external source)
○ Processor
○ Writer

Demonstration code >>>


www.oroinc.com
Integration flow (reverse sync)

● Sync to (ex. listening to changes)


● MQ
● ReverseSyncProcessor::process()
● Execute Export job
○ Reader
○ Processor
○ Writer - uses transport to send data

www.oroinc.com
Integration consists of...

● Channel type
● Transport
○ Settings entity
○ Settings form type
● Connectors

www.oroinc.com
Channel Type

● Represents integration type


● Contains label and icon
● DIC tag oro_integration.channel
● [Zendesk example]

www.oroinc.com
Transport

● Represents communication gateway


● Contains reference to integration settings
(entity and form type)
● May contain methods to interact with 3rd
party application
● DIC tag oro_integration.transport
● [Zendesk example]

www.oroinc.com
Transport Settings: Entity

● Extends OroIntegrationBundle:Transport
● Uses single table inheritance - Doctrine docs
○ Remember about a migration
● Contains settings
● Returns list of settings using ParameterBag
● [Zendesk example]

www.oroinc.com
Transport Settings: Form type

● Works with settings entity


● Describes how settings are rendered
● Rendered at the integration create/edit page
● [Zendesk example]

www.oroinc.com
Connector

● Represents import and export of entities


● One-way - only import
● Two-way - both import and export
● DIC tag oro_integration.connector
● [Zendesk example - TicketConnector]

www.oroinc.com
Overall schema

Channel type

Transport Connector 1

Settings entity Connector 2

Settings form
Connector 3
type

www.oroinc.com
Integration types

● Data based
○ Import and export of entities
○ Connectors
○ Synchronization (sync)
● Operation based
○ Operation calls (local or RPC)
○ No connectors
○ No synchronizations
● Combined

www.oroinc.com
Possible issues

● Performance (data based integrations)


○ Same as for import/export
● No failure tolerance to 3rd party system on a
global level
○ E. g. when the other side becomes not
available
○ Needs to be implemented within integration
level

www.oroinc.com
Best Practices

● If only one instance of the integration is


required then credentials and configuration can
be put to the system configuration, just don’t
forget to use encryption to secure information
● Isolate work with the API at the separate layer
(transport layer)
● Inject logger and use it at all critical places (API
calls, important entity creation, error processing
etc)

www.oroinc.com
Docs
● https://doc.oroinc.com/user/back-office/system/integrations/
● https://doc.oroinc.com/backend/integrations/
● https://github.com/oroinc/platform/tree/4.1/src/Oro/Bundle/In
tegrationBundle

www.oroinc.com
Workflows

www.oroinc.com
Overview
● Representation of a business process
○ checkout with approval, closing opportunity, status

www.oroinc.com
General information

● State machine
● Assigned to entity
● States = steps
● Internal data = attributes
● Changes of states = transitions
● Actions and conditions = transition definitions
● Data restrictions = entity restrictions

Demonstration UI + CLI >>>

www.oroinc.com
Workflow Definition

● Resources/config/oro/workflows.yml
○ Includes are allowed (imports)
● oro:workflow:definitions:load
● oro:debug:workflow:definitions
● WorkflowDefinition entity
● Translations for labels are in a separate file
○ oro:workflow:translations:dump
● User may add simple definitions from UI
● Developer may add custom definitions from YML

www.oroinc.com
Workflow Item

● Represents started workflow on an entity


● Stores all data not related to entity
● Data is serialized
● WorkflowItem entity

Demonstration >>>
UI -> manually start workflow
DB -> new record

www.oroinc.com
Steps

● Represent state of a workflow


● WorkflowStep entity
● Steps are ordered
● Steps know about possible transitions
● Workflow may have one start step
● Workflow may have one or more final steps

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/SalesBundl
e/Resources/config/oro/workflows/opportunity_flow/steps.yml

www.oroinc.com
Attributes

● Represent data of workflow


● Data is stored inside WorkflowItem
● Main entity has an attribute
● Attributes might be separate or refer to a field
of an entity (via property path)

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/SalesBundl
e/Resources/config/oro/workflows/opportunity_flow/attributes.yml

www.oroinc.com
Attributes
● $.data.status
○ attribute “status”
● $status
○ attribute “status” (same as above)
● $.result.status
○ temporary data (not persistent), useful for
dependent actions but in case when there is no need
to store this information in an attribute
● $.status
○ PropertyAccessor->getValue(WorkflowItem, status)
○ Will throw exception

www.oroinc.com
Variables
● Changeable configuration ● Accessed like
values on a workflow level attributes
○ Data is serialized ● [example]
● [docs]

www.oroinc.com
Entity Restrictions
● Restrict modification of attribute fields
● Might be assigned to step
○ restriction will be applied only in this step
● Mode: full, disallow, allow
○ Default: full
● Example
● Docs

www.oroinc.com
Transitions
● Represent change of state
● Lead to one workflow step
● Workflow has one or more start transitions
● Might have a form with attribute fields
● Might have ACL restriction
● Might have assigned conditions
● Might have related actions

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/SalesBundle/Res
ources/config/oro/workflows/opportunity_flow/transitions.yml

www.oroinc.com
Transition Definitions

● Represent transition conditions and actions


● Pre-actions, pre-conditions (can be displayed)
● Actions, conditions (can be performed)
● Might be empty
● Several transitions might use the same
transition definition

https://github.com/oroinc/crm/blob/4.1/src/Oro/Bundle/SalesBundl
e/Resources/config/oro/workflows/opportunity_flow/transition_defi
nitions.yml
www.oroinc.com
Actions

● Small block of functionality


● Might have parameters
● Might have conditions
● Developers might add custom actions
○ DIC tag oro_action.action
● List of all actions
○ debug:container --tag="oro_action.action"

[Example] & [Documentation]

www.oroinc.com
Conditions

● Small check that returns true/false


● Might have parameters
● Developers might add custom conditions
○ DIC tag oro_action.condition
● List of all contions
○ debug:container
--tag="oro_action.condition"

[Example] & [Documentation]

www.oroinc.com
Translations

● workflows translation domain


○ Resources/translations/workflows.<en>.yml
● Translation for steps, attributes and transitions
● [example]

www.oroinc.com
Operations

● Provide possibility to assign any interaction with


user
● Can be added to specific routes or datagrids
● Use actions and conditions

[Documentation] & [Diagram]

www.oroinc.com
Processes

● Executed on:
○ Create, update, delete of entity or specific field
○ Cron
● Can be delayed with `time_shift`
● Use actions and conditions

[Documentation]

www.oroinc.com
Additional features

● Scopes
○ Documentation

www.oroinc.com
Best Practices

● Sometimes it’s easier and faster to create new big action


/ condition instead of writing huge YAML configuration
that does the same thing
● Sometimes it may be faster to write a process instead of
creation of a new PHP event listener (e.g. email
notifications with custom conditions)
● Copy whole workflow if you want to customize it - this
way you’ll not face BC issues during the update to a next
version
● You may dump whole configuration of an existing
workflow using command
oro:debug:workflow:definitions

www.oroinc.com

You might also like