SlideShare a Scribd company logo
Ruling Drupal 8
with
#d8rules
Josef Dabernig, Amazee Labs
@dasjo
• Facet API Pretty Paths
• Geocluster
• Drupal Centroamerica,
Austria, Switzerland, ++
• Deputy Head Technology
@ Amazee Labs
twitter.com/dasjo
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
• fago (Rules creator)
• klausi (co-maintainer)
• dasjo (communication)
• fubhy (developer)
• nico grienauer (design)
• steve purkiss
(developer)
#d8rules team
Rules
Rules
Rules
Rules
• Build flexible workflows
using events, condition &
actions
• Send customized mails to
notify your users
• Create custom redirections,
system messages,
breadcrumbs
Rules
• Build flexible workflows
using events, condition &
actions
• Send customized mails to
notify your users
• Create custom redirections,
system messages,
breadcrumbs
• 300.000+ reported installs
(30% of all Drupal 7 sites)
• Hundreds of integration
modules
• Entity API, Fields, Views,
Webform, Context, Features,
Search API, Tokens, Paths,
Menus, Queue,
Field formatter conditions, ...
Drupal 8 wins
Drupal 8 wins
• OOP, Dependency
Injection
• APIs
• PHPUnit
• Symfony2
• Removed legacy
modules
• Web services built in
• Front-end, responsive,
...
Drupal 8 for Rules
• Plug-in API
• Entity & Typed Data API
• Conditions API
• (Actions API -> forked)
• Context API shared w/ Core, Page Manager
• Configuration Management (CMI, YAML)
Reusable components (“rtools”)
• Tokens (automatic, based on typed data)
• Typed data widgets & formatters
• Extended Context API
• Embeddable Rules UI components
• Actions & Conditions
• Rules data selector for tokens, contexts
Reusable components (“rtools”)
Site building
• Admin UI usability improvements
• (Simple Views Bulk operations in core)
• “Inline Rules” instead of Rule sets / Rules
conditional
• Deployable configuration
Campaign
#d8rules goals
• Accelerate Drupal 8 uptake by ensuring that
Rules as a key contributed module is ready,
early enough.
• Enable flexible workflows in Drupal 8 sites
that are easily configurable & reusable.
• Make Drupal contributions sustainable by
funding contributed code used on hundreds
of thousands of sites.
drupalfund.us
Sponsors
Funding state
Rules 8.x
development status
Rules 8.x M1
Rules core API fundamentals
✓ Rules core engine, plugin types
✓ Align Rules condition & action APIs with core
✓ Parameter configuration & Context mapping
Rules 8.x M2
Rules core completion with basic UI
✓ Completed Rules engine features
✓ Completed Rules plugins (Events, Loops, API)
✓ Configuration entity, CMI and integrity checks
✓ Basic UI and autocomplete functionality
✓ API for embedding the Rules UI
✓ Twig-style token replacements
Rules 8.x M3
Rules release
❏ Stable Rules 8.x-3.0 Release
❏ Rules Engine follow-ups
❏ Complete Rules UI
❏ Rules scheduler port
❏ Port existing integrations (almost done!)
Rules 8.x
Roadmap
https://www.drupal.org/node/2245015
Sprints, trainings & sessions
Szeged, Portoroz, Austin, Drupalaton, Amsterdam,
Zurich, Bogotá, Vienna, Milano, Montpellier, Bratislava,
Sunderland, Barcelona, Mumbai, Heidelberg, Granada, ..
http://d8rules.org/events
Contribution
• 114 forks, 40 contributors
• paranoik, stevepurkiss, scuts, jibran, chindris,
omissis, ndewhurst, jzavrl, MegaChriz, bbujisic,
dawehner, torenware, bartfeenstra, M1r1k, rinasek,
joashuataylor, lokapujya, icanblink, bojanz, a.
milkovsky, mariancalinro, pjezek,czigor, mikl, nlisgo,
nielsdefeyter, ...
• 427 closed pull requests, Thank you all!
Getting started
• Setup Drupal 8
• Fork Rules 8.x on github:
• https://github.com/fago/rules
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
Diving into Rules 8.x
Writing
Conditions, Actions &
Events
Plug-ins
• OOP
• Annotations
• Auto-loading
• Discovery
• Derivatives
Provide conditions
• hook_rules_condition_info()
-> ?
Provide conditions
• hook_rules_condition_info
-> Implement a Condition plug-in
/**
* Provides a 'Node is sticky' condition.
*
* @Condition(
* id = "rules_node_is_sticky",
* label = @Translation("Node is sticky"),
* category = @Translation("Node"),
* context = {…}
* )
*/
class NodeIsSticky extends RulesConditionBase {
/**
* {@inheritdoc}
*/
public function evaluate() {
$node = $this->getContextValue('node');
return $node->isSticky();
}
}
Provide actions
• hook_rules_action_info
-> Implement an Action plug-in
/**
* Provides a 'Delete entity' action.
*
* @Action(
* id = "rules_entity_delete",
* label = @Translation("Delete entity"),
* category = @Translation("Entity"),
* context = {…}
* )
*/
class EntityDelete extends RulesActionBase {
/**
* {@inheritdoc}
*/
public function execute() {
$entity = $this->getContextValue('entity');
$entity->delete();
}
}
Provide events
• hook_rules_event_info
-> Specify Symfony event metadata in *.
rules.events.yml
rules_user_login:
label: 'User has logged in'
category: 'User'
context:
account:
type: 'entity:user'
label: 'Logged in user'
Event example from rules.rules.events.yml
Event invocation
/**
* Implements hook_user_login().
*/
function rules_user_login($account) {
// Set the account twice on the event: as the main subject but also in the
// list of arguments.
$event = new UserLoginEvent($account, ['account' => $account]);
$event_dispatcher = Drupal::service('event_dispatcher');
$event_dispatcher->dispatch(UserLoginEvent::EVENT_NAME, $event);
}
Event invocation
/**
* Implements hook_user_login().
*/
function rules_user_login($account) {
// Set the account twice on the event: as the main subject but also in the
// list of arguments.
$event = new UserLoginEvent($account, ['account' => $account]);
$event_dispatcher = Drupal::service('event_dispatcher');
$event_dispatcher->dispatch(UserLoginEvent::EVENT_NAME, $event);
}
Context
Context
● Defining context for a plug-in
/**
* Provides a 'Delete entity' action.
*
* @Action(
* id = "rules_entity_delete",
* label = @Translation("Delete entity"),
* category = @Translation("Entity"),
* context = {…}
* )
*/
class EntityDelete extends RulesActionBase {
/**
* {@inheritdoc}
*/
public function execute() {
$entity = $this->getContextValue('entity');
$entity->delete();
}
}
/**
* Provides a 'Delete entity' action.
*
* @Action(
* id = "rules_entity_delete",
* label = @Translation("Delete entity"),
* category = @Translation("Entity"),
* context = {
* "entity" = @ContextDefinition("entity",
* label = @Translation("Entity"),
* description = @Translation("Specifies the entity,
which should be deleted permanently.")
* )
* }
* )
*/
class EntityDelete extends RulesActionBase {...}
Context
● Defining context for a plug-in
● Using context within a plug-in
class EntityDelete extends RulesActionBase {
/**
* Executes the action with the given context.
*/
public function doExecute(EntityInterface $entity) {
$entity->delete();
}
}
class EntityDelete extends RulesActionBase {
/**
* Executes the action with the given context.
*/
public function doExecute(EntityInterface $entity) {
$entity->delete();
}
}
class FetchEntityById extends RulesActionBase implements
ContainerFactoryPluginInterface {
/**
* Executes the action with the given context.
*/
public function doExecute($entity_type, $entity_id) {
$storage = $this->entityManager->getStorage($entity_type);
$entity = $storage->load($entity_id);
$this->setProvidedValue('entity', $entity);
}
}
class FetchEntityById extends RulesActionBase implements
ContainerFactoryPluginInterface {
/**
* Executes the action with the given context.
*/
public function doExecute($entity_type, $entity_id) {
$storage = $this->entityManager->getStorage($entity_type);
$entity = $storage->load($entity_id);
$this->setProvidedValue('entity', $entity);
}
}
Context
● Defining context for a plug-in
● Using context within a plug-in
● Passing context to the plug-in
class ListCountIsTest extends RulesIntegrationTestBase {
/**
* Tests evaluating the condition.
*
* @covers ::evaluate()
*/
public function testConditionEvaluation() {
// Test that the list count is greater than 2.
$this->condition
->setContextValue('list', [1, 2, 3, 4])
->setContextValue('operator', '>')
->setContextValue('value', '2');
$this->assertTrue($condition->evaluate());
}
}
class ListCountIsTest extends RulesIntegrationTestBase {
/**
* Tests evaluating the condition.
*
* @covers ::evaluate()
*/
public function testConditionEvaluation() {
// Test that the list count is greater than 2.
$this->condition
->setContextValue('list', [1, 2, 3, 4])
->setContextValue('operator', '>')
->setContextValue('value', '2');
$this->assertTrue($condition->evaluate());
}
}
Storing configuration
Storing configuration
• D7: Entity exportables
• Rules:
• RulesPlugin->export()
-> ?
• RulesEntityController->import()
-> ?
Storing configuration
• D7: Entity exportables
• Rules:
• RulesPlugin->export()
-> RulesExpression::getConfiguration()
• RulesEntityController->import()
-> RulesExpression::setConfiguration()
Drupal 8: CMI
● Rules leverages the Config System
● Two types of config entities:
○ Reaction Rules (WIP)
○ Components
● Inherit features from CMI
○ Config deployment / import&export / sync
○ Config Translation (instead of Entity i18n)
○ Default config
Provide default rule configs
• hook_default_rules_configuration()
-> ?
Provide default rule configs
• hook_default_rules_configuration()
-> rules.reaction.*.yml
-> rules.component.*.yml
langcode: en
status: true
dependencies: {}
id: rules_test_default_component
label: Rules test default component
module: rules
description: 'Tests adding Rules component by
default.'
tag: 'test'
core: 8.x
expression_id: rules_rule
configuration:
...
configuration:
id: rules_rule
context:
user:
type: 'entity:user'
label: User
conditions:
id: rules_and
conditions: {}
actions:
id: rules_action_set
actions:
- id: rules_action
action_id: rules_system_message
context_mapping:
message: 'user:mail:value'
Executing the component
$config_entity = RulesComponent::load
('rules_test_default_component');
$expression = $config_entity->getExpression();
$expression
->setContextValue('user', Drupal::currentUser())
->execute();
Describe data to Rules
Drupal 7
• hook_rules_data_info()
-> ?
• hook_entity_property_info_alter
-> ?
Typed Data API
• Consistent way of interacting
with any data based on metadata
• Part of Drupal 8 & Entity Fields
• Defines a type system for PHP:
○ Primitive types (integer, float, string, dates, ..)
○ Complex types
○ Lists (with items of a specified type)
Data types
● any
● string, integer,
uri, float, ...
○ email
○ timestamp,
datetime_iso8601
○ timespan,
duration_iso8601
● entity
○ entity:node
○ entity:comment
● field_item
○ field_item:string
○ field_item:text
○ field_item:image
/**
* The float data type.
*
* The plain value of a float is a regular PHP float. For setting the value
* any PHP variable that casts to a float may be passed.
*
* @DataType(
* id = "float",
* label = @Translation("Float")
* )
*/
class FloatData extends PrimitiveBase implements FloatInterface {
/**
* {@inheritdoc}
*/
public function getCastedValue() {
return (float) $this->value;
}
}
/**
* The float data type.
*
* The plain value of a float is a regular PHP float. For setting the value
* any PHP variable that casts to a float may be passed.
*
* @DataType(
* id = "float",
* label = @Translation("Float")
* )
*/
class FloatData extends PrimitiveBase implements FloatInterface {
/**
* {@inheritdoc}
*/
public function getCastedValue() {
return (float) $this->value;
}
}
/**
* Plugin implementation of the 'link' field type.
*
* @FieldType(
* id = "link",
* label = @Translation("Link"),
* description = @Translation(“..."),
* default_widget = "link_default",
* default_formatter = "link",
* constraints = {"LinkType" = {}}
* )
*/
class LinkItem extends FieldItemBase implements LinkItemInterface {
public static function propertyDefinitions(
FieldStorageDefinitionInterface $field_definition) {
$properties['url'] = DataDefinition::create('string')
->setLabel(t('URL'));
…
return $properties;
}
/**
* Plugin implementation of the 'link' field type.
*
* @FieldType(
* id = "link",
* label = @Translation("Link"),
* description = @Translation(“..."),
* default_widget = "link_default",
* default_formatter = "link",
* constraints = {"LinkType" = {}}
* )
*/
class LinkItem extends FieldItemBase implements LinkItemInterface {
public static function propertyDefinitions(
FieldStorageDefinitionInterface $field_definition) {
$properties['url'] = DataDefinition::create('string')
->setLabel(t('URL'));
…
return $properties;
}
Describe data to rules
• hook_rules_data_info()
-> ?
• hook_entity_property_info_alter
-> ?
Describe data to rules
• hook_rules_data_info()
-> Data type plugins, Typed Data
• hook_entity_property_info_alter
-> hook_data_type_info_alter()
-> hook_entity_base_field_info/alter()
-> hook_entity_bundle_field_info/alter()
-> FieldItem::propertyDefintions()
Every content entity & field type
in Drupal 8 is supported
by Rules out-of-the box!
[META] Rules 8.x UI
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
Lists & Multiple values
● list<foo> notation is gone
● “list” data type & per data type class
● Separate data definitions for lists vs. list
items
● Mark context as “multiple”
Creating a Rule with context
$rule = $this->expressionManager->createRule([
'context_definitions' => [
'test' => [
'type' => 'string',
'label' => 'Test string',
],
],
]);
$rule = $this->expressionManager->createRule([
'context_definitions' => [
'test' => [
'type' => 'string',
'label' => 'Test string',
],
],
]);
$rule->addCondition('rules_test_string_condition',
ContextConfig::create()
->map('text', 'test')
);
$rule = $this->expressionManager->createRule([
'context_definitions' => [
'test' => [
'type' => 'string',
'label' => 'Test string',
],
],
]);
$rule->addCondition('rules_test_string_condition',
ContextConfig::create()
->map('text', 'test')
);
$rule->addAction('rules_test_log');
$rule = $this->expressionManager->createRule([
'context_definitions' => [
'test' => [
'type' => 'string',
'label' => 'Test string',
],
],
]);
$rule->addCondition('rules_test_string_condition',
ContextConfig::create()
->map('text', 'test')
);
$rule->addAction('rules_test_log');
$rule->setContextValue('test', 'test value');
$rule = $this->expressionManager->createRule([
'context_definitions' => [
'test' => [
'type' => 'string',
'label' => 'Test string',
],
],
]);
$rule->addCondition('rules_test_string_condition',
ContextConfig::create()
->map('text', 'test')
);
$rule->addAction('rules_test_log');
$rule->setContextValue('test', 'test value');
$rule->execute();
Mapping required and provided
context
$rule = $this->expressionManager->createRule();
$rule = $this->expressionManager->createRule();
// Condition provides a "provided_text" variable.
$rule->addCondition('rules_test_provider');
$rule = $this->expressionManager->createRule();
// Condition provides a "provided_text" variable.
$rule->addCondition('rules_test_provider');
// Action provides a "concatenated" variable.
$rule->addAction('rules_test_string',
ContextConfig::create()
->provideAs('text', 'provided_text')
);
$rule = $this->expressionManager->createRule();
// Condition provides a "provided_text" variable.
$rule->addCondition('rules_test_provider');
// Action provides a "concatenated" variable.
$rule->addAction('rules_test_string',
ContextConfig::create()
->provideAs('text', 'provided_text')
);
// Same action again now provides "concatenated2"
$rule->addAction('rules_test_string',
ContextConfig::create()
->map(text, 'concatenated')
->provideAs('concatenated', 'concatenated2')
);
$rule = $this->expressionManager->createRule();
// Condition provides a "provided_text" variable.
$rule->addCondition('rules_test_provider');
// Action provides a "concatenated" variable.
$rule->addAction('rules_test_string',
ContextConfig::create()
->provideAs('text', 'provided_text')
);
// Same action again now provides "concatenated2"
$rule->addAction('rules_test_string',
ContextConfig::create()
->map(text, 'concatenated')
->provideAs('concatenated', 'concatenated2')
);
Advanced / under the hood
Provide other Rules plugins
• hook_rules_plugin_info
-> Implement a RulesExpression plugin
Provide input evaluators
• hook_rules_evaluator_info
-> Implement a RulesDataProcessor
plugin
/**
* A data processor for applying numerical offsets.
*
* The plugin configuration must contain the following entry:
* - offset: the value that should be added.
*
* @RulesDataProcessor(
* id = "rules_numeric_offset",
* label = @Translation("Apply numeric offset")
* )
*/
class NumericOffset extends PluginBase implements
RulesDataProcessorInterface {
/**
* {@inheritdoc}
*/
public function process($value) {
return $value + $this->configuration['offset'];
}
Automated testing
Automated testing
• RulesUnitTestBase extends UnitTestCase
• Internal unit tests such as RuleTest, RulesAndTest,
RulesContextTraitTest, …
Automated testing
• RulesUnitTestBase extends UnitTestCase
• Internal unit tests such as RuleTest, RulesAndTest,
RulesContextTraitTest, …
• RulesIntegrationTestBase
• use ActionManager, ConditionManager,
TypedDataManager, …
class DataListCountIs extends RulesConditionBase {
/**
* {@inheritdoc}
*/
public function evaluate() {
$list = $this->getContextValue('list');
$operator = $this->getContextValue('operator');
$value = $this->getContextValue('value');
switch ($operator) {
case '==':
return count($list) == $value;
case '<';
return count($list) < $value;
case '>';
return count($list) > $value;
}
/**
* Tests evaluating the condition.
*
* @covers ::evaluate()
*/
public function testConditionEvaluation() {
// Test that the list count is greater than 2.
$condition = $this->condition
->setContextValue('list', [1, 2, 3, 4])
->setContextValue('operator', '>')
->setContextValue('value', '2');
$this->assertTrue($condition->evaluate());
// Test that the list count is not equal to 0.
$condition = $this->condition
->setContextValue('list', [1, 2, 3])
->setContextValue('operator', '==')
->setContextValue('value', '0');
$this->assertFalse($condition->evaluate());
}
Automated testing
• RulesUnitTestBase extends UnitTestCase
• Internal unit tests such as RuleTest, RulesAndTest,
RulesContextTraitTest, …
• RulesIntegrationTestBase
• use ActionManager, ConditionManager,
TypedDataManager, …
Automated testing
• RulesUnitTestBase extends UnitTestCase
• Internal unit tests such as RuleTest, RulesAndTest,
RulesContextTraitTest, …
• RulesIntegrationTestBase
• use ActionManager, ConditionManager,
TypedDataManager, …
• RulesEntityIntegrationTestBase
* @Condition(
* id = "rules_entity_is_of_type",
* label = @Translation("Entity is of type"),
* category = @Translation("Entity"),
* context = {
* "entity" = @ContextDefinition("entity",
* label = @Translation("Entity"),
* ),
* "type" = @ContextDefinition("string",
* label = @Translation("Type"),
* )
* }
* )
*/
class EntityIsOfType extends RulesConditionBase {
public function evaluate() {
$provided_entity = $this->getContextValue('entity');
$specified_type = $this->getContextValue('type');
$entity_type = $provided_entity->getEntityTypeId();
/**
* Tests evaluating the condition.
*
* @covers ::evaluate()
*/
public function testConditionEvaluation() {
$entity = $this->getMock('DrupalCoreEntityEntityInterface');
$entity->expects($this->exactly(2))
->method('getEntityTypeId')
->will($this->returnValue('node'));
// Add the test node to our context as the evaluated entity.
// First, test with a value that should evaluate TRUE.
$this->condition->setContextValue('entity', $entity)
->setContextValue('type', 'node');
$this->assertTrue($this->condition->evaluate());
// Then test with values that should evaluate FALSE.
$this->condition->setContextValue('type', 'taxonomy_term');
$this->assertFalse($this->condition->evaluate());
/**
* Tests evaluating the condition.
*
* @covers ::evaluate()
*/
public function testConditionEvaluation() {
$entity = $this->getMock('DrupalCoreEntityEntityInterface');
$entity->expects($this->exactly(2))
->method('getEntityTypeId')
->will($this->returnValue('node'));
// Add the test node to our context as the evaluated entity.
// First, test with a value that should evaluate TRUE.
$this->condition->setContextValue('entity', $entity)
->setContextValue('type', 'node');
$this->assertTrue($this->condition->evaluate());
// Then test with values that should evaluate FALSE.
$this->condition->setContextValue('type', 'taxonomy_term');
$this->assertFalse($this->condition->evaluate());
/**
* Tests evaluating the condition.
*
* @covers ::evaluate()
*/
public function testConditionEvaluation() {
$entity = $this->getMock('DrupalCoreEntityEntityInterface');
$entity->expects($this->exactly(2))
->method('getEntityTypeId')
->will($this->returnValue('node'));
// Add the test node to our context as the evaluated entity.
// First, test with a value that should evaluate TRUE.
$this->condition->setContextValue('entity', $entity)
->setContextValue('type', 'node');
$this->assertTrue($this->condition->evaluate());
// Then test with values that should evaluate FALSE.
$this->condition->setContextValue('type', 'taxonomy_term');
$this->assertFalse($this->condition->evaluate());
/**
* Tests evaluating the condition.
*
* @covers ::evaluate()
*/
public function testConditionEvaluation() {
$entity = $this->getMock('DrupalCoreEntityEntityInterface');
$entity->expects($this->exactly(2))
->method('getEntityTypeId')
->will($this->returnValue('node'));
// Add the test node to our context as the evaluated entity.
// First, test with a value that should evaluate TRUE.
$this->condition->setContextValue('entity', $entity)
->setContextValue('type', 'node');
$this->assertTrue($this->condition->evaluate());
// Then test with values that should evaluate FALSE.
$this->condition->setContextValue('type', 'taxonomy_term');
$this->assertFalse($this->condition->evaluate());
RulesState
RulesState
• variables
• applyDataSelector
• autoSave
Traits
trait StringTranslationTrait {
/**
* The string translation service.
*
* @var DrupalCoreStringTranslationTranslationInterface
*/
protected $stringTranslation;
/**
* Translates a string to the current language or to a given language.
*
* See the t() documentation for details.
*/
protected function t($string, …) {
return $this->getStringTranslation()->translate($string, …);
}
}
class MyClass {
use StringTranslationTrait;
public function __construct(
TranslationInterface $string_translation) {
$this->stringTranslation = $string_translation;
}
/**
* Does something.
*/
public function doSth() {
// ...
$string = $this->t('Something');
// ...
}
}
Traits
• RulesContextTrait
• in addition to ContextAwarePluginBase
• used in RulesActionBase and RulesConditionBase
Outro
[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules
Sprint with us!
• Port actions & conditions
• https://www.drupal.org/node/2245015
Sprint with us!
• Port actions & conditions
• https://www.drupal.org/node/2245015
https://www.youtube.com/watch?v=gEH291mq48Y
Fluxkraft UI proposals
Rules Transformers
• https://www.drupal.org/node/2251267
NoFlo
Ad

More Related Content

What's hot (20)

Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency Injection
Philip Norton
 
«От экспериментов с инфраструктурой до внедрения в продакшен»​
«От экспериментов с инфраструктурой до внедрения в продакшен»​«От экспериментов с инфраструктурой до внедрения в продакшен»​
«От экспериментов с инфраструктурой до внедрения в продакшен»​
FDConf
 
Drupal 8 Services
Drupal 8 ServicesDrupal 8 Services
Drupal 8 Services
Philip Norton
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
Nick Lee
 
Planbox Backbone MVC
Planbox Backbone MVCPlanbox Backbone MVC
Planbox Backbone MVC
Acquisio
 
Backbone
BackboneBackbone
Backbone
Glenn De Backer
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.js
Bert Wijnants
 
Spring 4 - A&BP CC
Spring 4 - A&BP CCSpring 4 - A&BP CC
Spring 4 - A&BP CC
JWORKS powered by Ordina
 
Why Task Queues - ComoRichWeb
Why Task Queues - ComoRichWebWhy Task Queues - ComoRichWeb
Why Task Queues - ComoRichWeb
Bryan Helmig
 
IndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceIndexedDB - Querying and Performance
IndexedDB - Querying and Performance
Parashuram N
 
The Best (and Worst) of Django
The Best (and Worst) of DjangoThe Best (and Worst) of Django
The Best (and Worst) of Django
Jacob Kaplan-Moss
 
An Introduction To Testing In AngularJS Applications
An Introduction To Testing In AngularJS Applications An Introduction To Testing In AngularJS Applications
An Introduction To Testing In AngularJS Applications
Rohan Chandane
 
AngularJS - $http & $resource Services
AngularJS - $http & $resource ServicesAngularJS - $http & $resource Services
AngularJS - $http & $resource Services
Eyal Vardi
 
The JavaFX Ecosystem
The JavaFX EcosystemThe JavaFX Ecosystem
The JavaFX Ecosystem
Andres Almiray
 
Geodaten & Drupal 7
Geodaten & Drupal 7Geodaten & Drupal 7
Geodaten & Drupal 7
Michael Milz
 
Redux vs Alt
Redux vs AltRedux vs Alt
Redux vs Alt
Uldis Sturms
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS Architecture
Eyal Vardi
 
Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)
Ivan Chepurnyi
 
Drupal8Day: Demystifying Drupal 8 Ajax Callback commands
Drupal8Day: Demystifying Drupal 8 Ajax Callback commandsDrupal8Day: Demystifying Drupal 8 Ajax Callback commands
Drupal8Day: Demystifying Drupal 8 Ajax Callback commands
Michael Miles
 
Django Celery - A distributed task queue
Django Celery - A distributed task queueDjango Celery - A distributed task queue
Django Celery - A distributed task queue
Alex Eftimie
 
Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency Injection
Philip Norton
 
«От экспериментов с инфраструктурой до внедрения в продакшен»​
«От экспериментов с инфраструктурой до внедрения в продакшен»​«От экспериментов с инфраструктурой до внедрения в продакшен»​
«От экспериментов с инфраструктурой до внедрения в продакшен»​
FDConf
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
Nick Lee
 
Planbox Backbone MVC
Planbox Backbone MVCPlanbox Backbone MVC
Planbox Backbone MVC
Acquisio
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.js
Bert Wijnants
 
Why Task Queues - ComoRichWeb
Why Task Queues - ComoRichWebWhy Task Queues - ComoRichWeb
Why Task Queues - ComoRichWeb
Bryan Helmig
 
IndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceIndexedDB - Querying and Performance
IndexedDB - Querying and Performance
Parashuram N
 
The Best (and Worst) of Django
The Best (and Worst) of DjangoThe Best (and Worst) of Django
The Best (and Worst) of Django
Jacob Kaplan-Moss
 
An Introduction To Testing In AngularJS Applications
An Introduction To Testing In AngularJS Applications An Introduction To Testing In AngularJS Applications
An Introduction To Testing In AngularJS Applications
Rohan Chandane
 
AngularJS - $http & $resource Services
AngularJS - $http & $resource ServicesAngularJS - $http & $resource Services
AngularJS - $http & $resource Services
Eyal Vardi
 
Geodaten & Drupal 7
Geodaten & Drupal 7Geodaten & Drupal 7
Geodaten & Drupal 7
Michael Milz
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS Architecture
Eyal Vardi
 
Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)
Ivan Chepurnyi
 
Drupal8Day: Demystifying Drupal 8 Ajax Callback commands
Drupal8Day: Demystifying Drupal 8 Ajax Callback commandsDrupal8Day: Demystifying Drupal 8 Ajax Callback commands
Drupal8Day: Demystifying Drupal 8 Ajax Callback commands
Michael Miles
 
Django Celery - A distributed task queue
Django Celery - A distributed task queueDjango Celery - A distributed task queue
Django Celery - A distributed task queue
Alex Eftimie
 

Similar to [Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules (20)

Web automation with #d8rules (European Drupal Days 2015)
Web automation with #d8rules (European Drupal Days 2015)Web automation with #d8rules (European Drupal Days 2015)
Web automation with #d8rules (European Drupal Days 2015)
Eugenio Minardi
 
Php on the Web and Desktop
Php on the Web and DesktopPhp on the Web and Desktop
Php on the Web and Desktop
Elizabeth Smith
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
Lukas Smith
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
Yared Ayalew
 
Developing your first application using FI-WARE
Developing your first application using FI-WAREDeveloping your first application using FI-WARE
Developing your first application using FI-WARE
Fermin Galan
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
Fabio Franzini
 
Staying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHPStaying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHP
Oscar Merida
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
Jonathan Wage
 
Developing your first application using FIWARE
Developing your first application using FIWAREDeveloping your first application using FIWARE
Developing your first application using FIWARE
FIWARE
 
The Naked Bundle - Tryout
The Naked Bundle - TryoutThe Naked Bundle - Tryout
The Naked Bundle - Tryout
Matthias Noback
 
Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2 Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2
3camp
 
droidQuery: The Android port of jQuery
droidQuery: The Android port of jQuerydroidQuery: The Android port of jQuery
droidQuery: The Android port of jQuery
PhDBrown
 
Practical AngularJS
Practical AngularJSPractical AngularJS
Practical AngularJS
Wei Ru
 
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
Miguel Gallardo
 
Do you know what your drupal is doing? Observe it!
Do you know what your drupal is doing? Observe it!Do you know what your drupal is doing? Observe it!
Do you know what your drupal is doing? Observe it!
Luca Lusso
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
Hugo Hamon
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
Hugo Hamon
 
Building AOL's High Performance, Enterprise Wide Mail Application With Silver...
Building AOL's High Performance, Enterprise Wide Mail Application With Silver...Building AOL's High Performance, Enterprise Wide Mail Application With Silver...
Building AOL's High Performance, Enterprise Wide Mail Application With Silver...
goodfriday
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
pootsbook
 
Staying Sane with Drupal (A Develper's Survival Guide)
Staying Sane with Drupal (A Develper's Survival Guide)Staying Sane with Drupal (A Develper's Survival Guide)
Staying Sane with Drupal (A Develper's Survival Guide)
Oscar Merida
 
Web automation with #d8rules (European Drupal Days 2015)
Web automation with #d8rules (European Drupal Days 2015)Web automation with #d8rules (European Drupal Days 2015)
Web automation with #d8rules (European Drupal Days 2015)
Eugenio Minardi
 
Php on the Web and Desktop
Php on the Web and DesktopPhp on the Web and Desktop
Php on the Web and Desktop
Elizabeth Smith
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
Lukas Smith
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
Yared Ayalew
 
Developing your first application using FI-WARE
Developing your first application using FI-WAREDeveloping your first application using FI-WARE
Developing your first application using FI-WARE
Fermin Galan
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
Fabio Franzini
 
Staying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHPStaying Sane with Drupal NEPHP
Staying Sane with Drupal NEPHP
Oscar Merida
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
Jonathan Wage
 
Developing your first application using FIWARE
Developing your first application using FIWAREDeveloping your first application using FIWARE
Developing your first application using FIWARE
FIWARE
 
The Naked Bundle - Tryout
The Naked Bundle - TryoutThe Naked Bundle - Tryout
The Naked Bundle - Tryout
Matthias Noback
 
Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2 Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2
3camp
 
droidQuery: The Android port of jQuery
droidQuery: The Android port of jQuerydroidQuery: The Android port of jQuery
droidQuery: The Android port of jQuery
PhDBrown
 
Practical AngularJS
Practical AngularJSPractical AngularJS
Practical AngularJS
Wei Ru
 
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
Code decoupling from Symfony (and others frameworks) - PHP Conference Brasil ...
Miguel Gallardo
 
Do you know what your drupal is doing? Observe it!
Do you know what your drupal is doing? Observe it!Do you know what your drupal is doing? Observe it!
Do you know what your drupal is doing? Observe it!
Luca Lusso
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
Hugo Hamon
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
Hugo Hamon
 
Building AOL's High Performance, Enterprise Wide Mail Application With Silver...
Building AOL's High Performance, Enterprise Wide Mail Application With Silver...Building AOL's High Performance, Enterprise Wide Mail Application With Silver...
Building AOL's High Performance, Enterprise Wide Mail Application With Silver...
goodfriday
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
pootsbook
 
Staying Sane with Drupal (A Develper's Survival Guide)
Staying Sane with Drupal (A Develper's Survival Guide)Staying Sane with Drupal (A Develper's Survival Guide)
Staying Sane with Drupal (A Develper's Survival Guide)
Oscar Merida
 
Ad

More from Srijan Technologies (20)

[Srijan Wednesday Webinar] How to Run Stateless and Stateful Services on K8S ...
[Srijan Wednesday Webinar] How to Run Stateless and Stateful Services on K8S ...[Srijan Wednesday Webinar] How to Run Stateless and Stateful Services on K8S ...
[Srijan Wednesday Webinar] How to Run Stateless and Stateful Services on K8S ...
Srijan Technologies
 
[Srijan Wednesday Webinars] How to Set Up a Node.js Microservices Architectur...
[Srijan Wednesday Webinars] How to Set Up a Node.js Microservices Architectur...[Srijan Wednesday Webinars] How to Set Up a Node.js Microservices Architectur...
[Srijan Wednesday Webinars] How to Set Up a Node.js Microservices Architectur...
Srijan Technologies
 
[Srijan Wednesday Webinars] How to Build a Cloud Native Platform for Enterpri...
[Srijan Wednesday Webinars] How to Build a Cloud Native Platform for Enterpri...[Srijan Wednesday Webinars] How to Build a Cloud Native Platform for Enterpri...
[Srijan Wednesday Webinars] How to Build a Cloud Native Platform for Enterpri...
Srijan Technologies
 
[Srijan Wednesday Webinars] Using Drupal as Data Pipeline for Digital Signage
[Srijan Wednesday Webinars] Using Drupal as Data Pipeline for Digital Signage[Srijan Wednesday Webinars] Using Drupal as Data Pipeline for Digital Signage
[Srijan Wednesday Webinars] Using Drupal as Data Pipeline for Digital Signage
Srijan Technologies
 
[Srijan Wednesday Webinars] New Recipe of Decoupling: Drupal 8, Symfony and S...
[Srijan Wednesday Webinars] New Recipe of Decoupling: Drupal 8, Symfony and S...[Srijan Wednesday Webinars] New Recipe of Decoupling: Drupal 8, Symfony and S...
[Srijan Wednesday Webinars] New Recipe of Decoupling: Drupal 8, Symfony and S...
Srijan Technologies
 
[Srijan Wednesday Webinars] Let’s Take the Best Route - Exploring Drupal 8 Ro...
[Srijan Wednesday Webinars] Let’s Take the Best Route - Exploring Drupal 8 Ro...[Srijan Wednesday Webinars] Let’s Take the Best Route - Exploring Drupal 8 Ro...
[Srijan Wednesday Webinars] Let’s Take the Best Route - Exploring Drupal 8 Ro...
Srijan Technologies
 
[Srijan Wednesday Webinars] Is Your Business Ready for GDPR
[Srijan Wednesday Webinars] Is Your Business Ready for GDPR[Srijan Wednesday Webinars] Is Your Business Ready for GDPR
[Srijan Wednesday Webinars] Is Your Business Ready for GDPR
Srijan Technologies
 
[Srijan Wednesday Webinars] Artificial Intelligence & the Future of Business
[Srijan Wednesday Webinars] Artificial Intelligence & the Future of Business[Srijan Wednesday Webinars] Artificial Intelligence & the Future of Business
[Srijan Wednesday Webinars] Artificial Intelligence & the Future of Business
Srijan Technologies
 
[Srijan Wednesday Webinars] How to Design a Chatbot that Works
[Srijan Wednesday Webinars] How to Design a Chatbot that Works[Srijan Wednesday Webinars] How to Design a Chatbot that Works
[Srijan Wednesday Webinars] How to Design a Chatbot that Works
Srijan Technologies
 
[Srijan Wednesday Webinars] Simplifying Migration to Drupal 8
[Srijan Wednesday Webinars] Simplifying Migration to Drupal 8[Srijan Wednesday Webinars] Simplifying Migration to Drupal 8
[Srijan Wednesday Webinars] Simplifying Migration to Drupal 8
Srijan Technologies
 
Final dependency presentation.odp
Final dependency presentation.odpFinal dependency presentation.odp
Final dependency presentation.odp
Srijan Technologies
 
[Srijan Wednesday Webinar] Leveraging the OGD Platform and Visualization Engine
[Srijan Wednesday Webinar] Leveraging the OGD Platform and Visualization Engine[Srijan Wednesday Webinar] Leveraging the OGD Platform and Visualization Engine
[Srijan Wednesday Webinar] Leveraging the OGD Platform and Visualization Engine
Srijan Technologies
 
[Srijan Wednesday Webinars] Why Adopt Analytics Driven Testing
[Srijan Wednesday Webinars] Why Adopt Analytics Driven Testing [Srijan Wednesday Webinars] Why Adopt Analytics Driven Testing
[Srijan Wednesday Webinars] Why Adopt Analytics Driven Testing
Srijan Technologies
 
[Srijan Wednesday Webinar] Key ingredients of a Powerful Test Automation System
[Srijan Wednesday Webinar] Key ingredients of a Powerful Test Automation System[Srijan Wednesday Webinar] Key ingredients of a Powerful Test Automation System
[Srijan Wednesday Webinar] Key ingredients of a Powerful Test Automation System
Srijan Technologies
 
[Srijan Wednesday Webinar] Building BPMN Web Portals with Camunda and Drupal
[Srijan Wednesday Webinar] Building BPMN Web Portals with Camunda and Drupal[Srijan Wednesday Webinar] Building BPMN Web Portals with Camunda and Drupal
[Srijan Wednesday Webinar] Building BPMN Web Portals with Camunda and Drupal
Srijan Technologies
 
[Srijan Wednesday Webinar] Decoupled Demystified: The Present & Future of Dr...
 [Srijan Wednesday Webinar] Decoupled Demystified: The Present & Future of Dr... [Srijan Wednesday Webinar] Decoupled Demystified: The Present & Future of Dr...
[Srijan Wednesday Webinar] Decoupled Demystified: The Present & Future of Dr...
Srijan Technologies
 
[Srijan Wednesday Webinars] Automating Visual Regression using ‘Galen’
[Srijan Wednesday Webinars] Automating Visual Regression using ‘Galen’[Srijan Wednesday Webinars] Automating Visual Regression using ‘Galen’
[Srijan Wednesday Webinars] Automating Visual Regression using ‘Galen’
Srijan Technologies
 
[Srijan Wednesday Webinars] NASA, Netflix, Tinder: Digital Transformation and...
[Srijan Wednesday Webinars] NASA, Netflix, Tinder: Digital Transformation and...[Srijan Wednesday Webinars] NASA, Netflix, Tinder: Digital Transformation and...
[Srijan Wednesday Webinars] NASA, Netflix, Tinder: Digital Transformation and...
Srijan Technologies
 
[Srijan Wednesday Webinars] Building a High Performance QA Team
[Srijan Wednesday Webinars] Building a High Performance QA Team[Srijan Wednesday Webinars] Building a High Performance QA Team
[Srijan Wednesday Webinars] Building a High Performance QA Team
Srijan Technologies
 
[Srijan Wednesday Webinar] Mastering Mobile Test Automation with Appium
[Srijan Wednesday Webinar] Mastering Mobile Test Automation with Appium[Srijan Wednesday Webinar] Mastering Mobile Test Automation with Appium
[Srijan Wednesday Webinar] Mastering Mobile Test Automation with Appium
Srijan Technologies
 
[Srijan Wednesday Webinar] How to Run Stateless and Stateful Services on K8S ...
[Srijan Wednesday Webinar] How to Run Stateless and Stateful Services on K8S ...[Srijan Wednesday Webinar] How to Run Stateless and Stateful Services on K8S ...
[Srijan Wednesday Webinar] How to Run Stateless and Stateful Services on K8S ...
Srijan Technologies
 
[Srijan Wednesday Webinars] How to Set Up a Node.js Microservices Architectur...
[Srijan Wednesday Webinars] How to Set Up a Node.js Microservices Architectur...[Srijan Wednesday Webinars] How to Set Up a Node.js Microservices Architectur...
[Srijan Wednesday Webinars] How to Set Up a Node.js Microservices Architectur...
Srijan Technologies
 
[Srijan Wednesday Webinars] How to Build a Cloud Native Platform for Enterpri...
[Srijan Wednesday Webinars] How to Build a Cloud Native Platform for Enterpri...[Srijan Wednesday Webinars] How to Build a Cloud Native Platform for Enterpri...
[Srijan Wednesday Webinars] How to Build a Cloud Native Platform for Enterpri...
Srijan Technologies
 
[Srijan Wednesday Webinars] Using Drupal as Data Pipeline for Digital Signage
[Srijan Wednesday Webinars] Using Drupal as Data Pipeline for Digital Signage[Srijan Wednesday Webinars] Using Drupal as Data Pipeline for Digital Signage
[Srijan Wednesday Webinars] Using Drupal as Data Pipeline for Digital Signage
Srijan Technologies
 
[Srijan Wednesday Webinars] New Recipe of Decoupling: Drupal 8, Symfony and S...
[Srijan Wednesday Webinars] New Recipe of Decoupling: Drupal 8, Symfony and S...[Srijan Wednesday Webinars] New Recipe of Decoupling: Drupal 8, Symfony and S...
[Srijan Wednesday Webinars] New Recipe of Decoupling: Drupal 8, Symfony and S...
Srijan Technologies
 
[Srijan Wednesday Webinars] Let’s Take the Best Route - Exploring Drupal 8 Ro...
[Srijan Wednesday Webinars] Let’s Take the Best Route - Exploring Drupal 8 Ro...[Srijan Wednesday Webinars] Let’s Take the Best Route - Exploring Drupal 8 Ro...
[Srijan Wednesday Webinars] Let’s Take the Best Route - Exploring Drupal 8 Ro...
Srijan Technologies
 
[Srijan Wednesday Webinars] Is Your Business Ready for GDPR
[Srijan Wednesday Webinars] Is Your Business Ready for GDPR[Srijan Wednesday Webinars] Is Your Business Ready for GDPR
[Srijan Wednesday Webinars] Is Your Business Ready for GDPR
Srijan Technologies
 
[Srijan Wednesday Webinars] Artificial Intelligence & the Future of Business
[Srijan Wednesday Webinars] Artificial Intelligence & the Future of Business[Srijan Wednesday Webinars] Artificial Intelligence & the Future of Business
[Srijan Wednesday Webinars] Artificial Intelligence & the Future of Business
Srijan Technologies
 
[Srijan Wednesday Webinars] How to Design a Chatbot that Works
[Srijan Wednesday Webinars] How to Design a Chatbot that Works[Srijan Wednesday Webinars] How to Design a Chatbot that Works
[Srijan Wednesday Webinars] How to Design a Chatbot that Works
Srijan Technologies
 
[Srijan Wednesday Webinars] Simplifying Migration to Drupal 8
[Srijan Wednesday Webinars] Simplifying Migration to Drupal 8[Srijan Wednesday Webinars] Simplifying Migration to Drupal 8
[Srijan Wednesday Webinars] Simplifying Migration to Drupal 8
Srijan Technologies
 
Final dependency presentation.odp
Final dependency presentation.odpFinal dependency presentation.odp
Final dependency presentation.odp
Srijan Technologies
 
[Srijan Wednesday Webinar] Leveraging the OGD Platform and Visualization Engine
[Srijan Wednesday Webinar] Leveraging the OGD Platform and Visualization Engine[Srijan Wednesday Webinar] Leveraging the OGD Platform and Visualization Engine
[Srijan Wednesday Webinar] Leveraging the OGD Platform and Visualization Engine
Srijan Technologies
 
[Srijan Wednesday Webinars] Why Adopt Analytics Driven Testing
[Srijan Wednesday Webinars] Why Adopt Analytics Driven Testing [Srijan Wednesday Webinars] Why Adopt Analytics Driven Testing
[Srijan Wednesday Webinars] Why Adopt Analytics Driven Testing
Srijan Technologies
 
[Srijan Wednesday Webinar] Key ingredients of a Powerful Test Automation System
[Srijan Wednesday Webinar] Key ingredients of a Powerful Test Automation System[Srijan Wednesday Webinar] Key ingredients of a Powerful Test Automation System
[Srijan Wednesday Webinar] Key ingredients of a Powerful Test Automation System
Srijan Technologies
 
[Srijan Wednesday Webinar] Building BPMN Web Portals with Camunda and Drupal
[Srijan Wednesday Webinar] Building BPMN Web Portals with Camunda and Drupal[Srijan Wednesday Webinar] Building BPMN Web Portals with Camunda and Drupal
[Srijan Wednesday Webinar] Building BPMN Web Portals with Camunda and Drupal
Srijan Technologies
 
[Srijan Wednesday Webinar] Decoupled Demystified: The Present & Future of Dr...
 [Srijan Wednesday Webinar] Decoupled Demystified: The Present & Future of Dr... [Srijan Wednesday Webinar] Decoupled Demystified: The Present & Future of Dr...
[Srijan Wednesday Webinar] Decoupled Demystified: The Present & Future of Dr...
Srijan Technologies
 
[Srijan Wednesday Webinars] Automating Visual Regression using ‘Galen’
[Srijan Wednesday Webinars] Automating Visual Regression using ‘Galen’[Srijan Wednesday Webinars] Automating Visual Regression using ‘Galen’
[Srijan Wednesday Webinars] Automating Visual Regression using ‘Galen’
Srijan Technologies
 
[Srijan Wednesday Webinars] NASA, Netflix, Tinder: Digital Transformation and...
[Srijan Wednesday Webinars] NASA, Netflix, Tinder: Digital Transformation and...[Srijan Wednesday Webinars] NASA, Netflix, Tinder: Digital Transformation and...
[Srijan Wednesday Webinars] NASA, Netflix, Tinder: Digital Transformation and...
Srijan Technologies
 
[Srijan Wednesday Webinars] Building a High Performance QA Team
[Srijan Wednesday Webinars] Building a High Performance QA Team[Srijan Wednesday Webinars] Building a High Performance QA Team
[Srijan Wednesday Webinars] Building a High Performance QA Team
Srijan Technologies
 
[Srijan Wednesday Webinar] Mastering Mobile Test Automation with Appium
[Srijan Wednesday Webinar] Mastering Mobile Test Automation with Appium[Srijan Wednesday Webinar] Mastering Mobile Test Automation with Appium
[Srijan Wednesday Webinar] Mastering Mobile Test Automation with Appium
Srijan Technologies
 
Ad

Recently uploaded (20)

Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
How analogue intelligence complements AI
How analogue intelligence complements AIHow analogue intelligence complements AI
How analogue intelligence complements AI
Paul Rowe
 
Role of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered ManufacturingRole of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered Manufacturing
Andrew Leo
 
Generative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in BusinessGenerative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in Business
Dr. Tathagat Varma
 
UiPath Community Berlin: Orchestrator API, Swagger, and Test Manager API
UiPath Community Berlin: Orchestrator API, Swagger, and Test Manager APIUiPath Community Berlin: Orchestrator API, Swagger, and Test Manager API
UiPath Community Berlin: Orchestrator API, Swagger, and Test Manager API
UiPathCommunity
 
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded DevelopersLinux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Toradex
 
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdfComplete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Software Company
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Linux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdfLinux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdf
RHCSA Guru
 
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In FranceManifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
chb3
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-UmgebungenHCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
panagenda
 
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
BookNet Canada
 
Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...
Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...
Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...
Aqusag Technologies
 
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath MaestroDev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
UiPathCommunity
 
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
Alan Dix
 
2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx
Samuele Fogagnolo
 
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptxIncreasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Anoop Ashok
 
Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)
Ortus Solutions, Corp
 
Build Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For DevsBuild Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For Devs
Brian McKeiver
 
Electronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploitElectronic_Mail_Attacks-1-35.pdf by xploit
Electronic_Mail_Attacks-1-35.pdf by xploit
niftliyevhuseyn
 
How analogue intelligence complements AI
How analogue intelligence complements AIHow analogue intelligence complements AI
How analogue intelligence complements AI
Paul Rowe
 
Role of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered ManufacturingRole of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered Manufacturing
Andrew Leo
 
Generative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in BusinessGenerative Artificial Intelligence (GenAI) in Business
Generative Artificial Intelligence (GenAI) in Business
Dr. Tathagat Varma
 
UiPath Community Berlin: Orchestrator API, Swagger, and Test Manager API
UiPath Community Berlin: Orchestrator API, Swagger, and Test Manager APIUiPath Community Berlin: Orchestrator API, Swagger, and Test Manager API
UiPath Community Berlin: Orchestrator API, Swagger, and Test Manager API
UiPathCommunity
 
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded DevelopersLinux Support for SMARC: How Toradex Empowers Embedded Developers
Linux Support for SMARC: How Toradex Empowers Embedded Developers
Toradex
 
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdfComplete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Software Company
 
Big Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur MorganBig Data Analytics Quick Research Guide by Arthur Morgan
Big Data Analytics Quick Research Guide by Arthur Morgan
Arthur Morgan
 
Linux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdfLinux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdf
RHCSA Guru
 
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In FranceManifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
chb3
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-UmgebungenHCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
panagenda
 
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
#StandardsGoals for 2025: Standards & certification roundup - Tech Forum 2025
BookNet Canada
 
Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...
Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...
Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...
Aqusag Technologies
 
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath MaestroDev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
UiPathCommunity
 
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
Alan Dix
 
2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx2025-05-Q4-2024-Investor-Presentation.pptx
2025-05-Q4-2024-Investor-Presentation.pptx
Samuele Fogagnolo
 
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptxIncreasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Anoop Ashok
 
Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)
Ortus Solutions, Corp
 
Build Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For DevsBuild Your Own Copilot & Agents For Devs
Build Your Own Copilot & Agents For Devs
Brian McKeiver
 

[Srijan Wednesday Webinars] Ruling Drupal 8 with #d8rules

  • 1. Ruling Drupal 8 with #d8rules Josef Dabernig, Amazee Labs @dasjo
  • 2. • Facet API Pretty Paths • Geocluster • Drupal Centroamerica, Austria, Switzerland, ++ • Deputy Head Technology @ Amazee Labs twitter.com/dasjo
  • 4. • fago (Rules creator) • klausi (co-maintainer) • dasjo (communication) • fubhy (developer) • nico grienauer (design) • steve purkiss (developer) #d8rules team
  • 8. Rules • Build flexible workflows using events, condition & actions • Send customized mails to notify your users • Create custom redirections, system messages, breadcrumbs
  • 9. Rules • Build flexible workflows using events, condition & actions • Send customized mails to notify your users • Create custom redirections, system messages, breadcrumbs • 300.000+ reported installs (30% of all Drupal 7 sites) • Hundreds of integration modules • Entity API, Fields, Views, Webform, Context, Features, Search API, Tokens, Paths, Menus, Queue, Field formatter conditions, ...
  • 11. Drupal 8 wins • OOP, Dependency Injection • APIs • PHPUnit • Symfony2 • Removed legacy modules • Web services built in • Front-end, responsive, ...
  • 12. Drupal 8 for Rules • Plug-in API • Entity & Typed Data API • Conditions API • (Actions API -> forked) • Context API shared w/ Core, Page Manager • Configuration Management (CMI, YAML)
  • 13. Reusable components (“rtools”) • Tokens (automatic, based on typed data) • Typed data widgets & formatters • Extended Context API • Embeddable Rules UI components • Actions & Conditions • Rules data selector for tokens, contexts
  • 15. Site building • Admin UI usability improvements • (Simple Views Bulk operations in core) • “Inline Rules” instead of Rule sets / Rules conditional • Deployable configuration
  • 17. #d8rules goals • Accelerate Drupal 8 uptake by ensuring that Rules as a key contributed module is ready, early enough. • Enable flexible workflows in Drupal 8 sites that are easily configurable & reusable. • Make Drupal contributions sustainable by funding contributed code used on hundreds of thousands of sites.
  • 22. Rules 8.x M1 Rules core API fundamentals ✓ Rules core engine, plugin types ✓ Align Rules condition & action APIs with core ✓ Parameter configuration & Context mapping
  • 23. Rules 8.x M2 Rules core completion with basic UI ✓ Completed Rules engine features ✓ Completed Rules plugins (Events, Loops, API) ✓ Configuration entity, CMI and integrity checks ✓ Basic UI and autocomplete functionality ✓ API for embedding the Rules UI ✓ Twig-style token replacements
  • 24. Rules 8.x M3 Rules release ❏ Stable Rules 8.x-3.0 Release ❏ Rules Engine follow-ups ❏ Complete Rules UI ❏ Rules scheduler port ❏ Port existing integrations (almost done!)
  • 26. Sprints, trainings & sessions Szeged, Portoroz, Austin, Drupalaton, Amsterdam, Zurich, Bogotá, Vienna, Milano, Montpellier, Bratislava, Sunderland, Barcelona, Mumbai, Heidelberg, Granada, .. http://d8rules.org/events
  • 27. Contribution • 114 forks, 40 contributors • paranoik, stevepurkiss, scuts, jibran, chindris, omissis, ndewhurst, jzavrl, MegaChriz, bbujisic, dawehner, torenware, bartfeenstra, M1r1k, rinasek, joashuataylor, lokapujya, icanblink, bojanz, a. milkovsky, mariancalinro, pjezek,czigor, mikl, nlisgo, nielsdefeyter, ... • 427 closed pull requests, Thank you all!
  • 28. Getting started • Setup Drupal 8 • Fork Rules 8.x on github: • https://github.com/fago/rules
  • 32. Plug-ins • OOP • Annotations • Auto-loading • Discovery • Derivatives
  • 35. /** * Provides a 'Node is sticky' condition. * * @Condition( * id = "rules_node_is_sticky", * label = @Translation("Node is sticky"), * category = @Translation("Node"), * context = {…} * ) */ class NodeIsSticky extends RulesConditionBase { /** * {@inheritdoc} */ public function evaluate() { $node = $this->getContextValue('node'); return $node->isSticky(); } }
  • 36. Provide actions • hook_rules_action_info -> Implement an Action plug-in
  • 37. /** * Provides a 'Delete entity' action. * * @Action( * id = "rules_entity_delete", * label = @Translation("Delete entity"), * category = @Translation("Entity"), * context = {…} * ) */ class EntityDelete extends RulesActionBase { /** * {@inheritdoc} */ public function execute() { $entity = $this->getContextValue('entity'); $entity->delete(); } }
  • 38. Provide events • hook_rules_event_info -> Specify Symfony event metadata in *. rules.events.yml
  • 39. rules_user_login: label: 'User has logged in' category: 'User' context: account: type: 'entity:user' label: 'Logged in user' Event example from rules.rules.events.yml
  • 40. Event invocation /** * Implements hook_user_login(). */ function rules_user_login($account) { // Set the account twice on the event: as the main subject but also in the // list of arguments. $event = new UserLoginEvent($account, ['account' => $account]); $event_dispatcher = Drupal::service('event_dispatcher'); $event_dispatcher->dispatch(UserLoginEvent::EVENT_NAME, $event); }
  • 41. Event invocation /** * Implements hook_user_login(). */ function rules_user_login($account) { // Set the account twice on the event: as the main subject but also in the // list of arguments. $event = new UserLoginEvent($account, ['account' => $account]); $event_dispatcher = Drupal::service('event_dispatcher'); $event_dispatcher->dispatch(UserLoginEvent::EVENT_NAME, $event); }
  • 44. /** * Provides a 'Delete entity' action. * * @Action( * id = "rules_entity_delete", * label = @Translation("Delete entity"), * category = @Translation("Entity"), * context = {…} * ) */ class EntityDelete extends RulesActionBase { /** * {@inheritdoc} */ public function execute() { $entity = $this->getContextValue('entity'); $entity->delete(); } }
  • 45. /** * Provides a 'Delete entity' action. * * @Action( * id = "rules_entity_delete", * label = @Translation("Delete entity"), * category = @Translation("Entity"), * context = { * "entity" = @ContextDefinition("entity", * label = @Translation("Entity"), * description = @Translation("Specifies the entity, which should be deleted permanently.") * ) * } * ) */ class EntityDelete extends RulesActionBase {...}
  • 46. Context ● Defining context for a plug-in ● Using context within a plug-in
  • 47. class EntityDelete extends RulesActionBase { /** * Executes the action with the given context. */ public function doExecute(EntityInterface $entity) { $entity->delete(); } }
  • 48. class EntityDelete extends RulesActionBase { /** * Executes the action with the given context. */ public function doExecute(EntityInterface $entity) { $entity->delete(); } }
  • 49. class FetchEntityById extends RulesActionBase implements ContainerFactoryPluginInterface { /** * Executes the action with the given context. */ public function doExecute($entity_type, $entity_id) { $storage = $this->entityManager->getStorage($entity_type); $entity = $storage->load($entity_id); $this->setProvidedValue('entity', $entity); } }
  • 50. class FetchEntityById extends RulesActionBase implements ContainerFactoryPluginInterface { /** * Executes the action with the given context. */ public function doExecute($entity_type, $entity_id) { $storage = $this->entityManager->getStorage($entity_type); $entity = $storage->load($entity_id); $this->setProvidedValue('entity', $entity); } }
  • 51. Context ● Defining context for a plug-in ● Using context within a plug-in ● Passing context to the plug-in
  • 52. class ListCountIsTest extends RulesIntegrationTestBase { /** * Tests evaluating the condition. * * @covers ::evaluate() */ public function testConditionEvaluation() { // Test that the list count is greater than 2. $this->condition ->setContextValue('list', [1, 2, 3, 4]) ->setContextValue('operator', '>') ->setContextValue('value', '2'); $this->assertTrue($condition->evaluate()); } }
  • 53. class ListCountIsTest extends RulesIntegrationTestBase { /** * Tests evaluating the condition. * * @covers ::evaluate() */ public function testConditionEvaluation() { // Test that the list count is greater than 2. $this->condition ->setContextValue('list', [1, 2, 3, 4]) ->setContextValue('operator', '>') ->setContextValue('value', '2'); $this->assertTrue($condition->evaluate()); } }
  • 55. Storing configuration • D7: Entity exportables • Rules: • RulesPlugin->export() -> ? • RulesEntityController->import() -> ?
  • 56. Storing configuration • D7: Entity exportables • Rules: • RulesPlugin->export() -> RulesExpression::getConfiguration() • RulesEntityController->import() -> RulesExpression::setConfiguration()
  • 57. Drupal 8: CMI ● Rules leverages the Config System ● Two types of config entities: ○ Reaction Rules (WIP) ○ Components ● Inherit features from CMI ○ Config deployment / import&export / sync ○ Config Translation (instead of Entity i18n) ○ Default config
  • 58. Provide default rule configs • hook_default_rules_configuration() -> ?
  • 59. Provide default rule configs • hook_default_rules_configuration() -> rules.reaction.*.yml -> rules.component.*.yml
  • 60. langcode: en status: true dependencies: {} id: rules_test_default_component label: Rules test default component module: rules description: 'Tests adding Rules component by default.' tag: 'test' core: 8.x expression_id: rules_rule configuration: ...
  • 61. configuration: id: rules_rule context: user: type: 'entity:user' label: User conditions: id: rules_and conditions: {} actions: id: rules_action_set actions: - id: rules_action action_id: rules_system_message context_mapping: message: 'user:mail:value'
  • 62. Executing the component $config_entity = RulesComponent::load ('rules_test_default_component'); $expression = $config_entity->getExpression(); $expression ->setContextValue('user', Drupal::currentUser()) ->execute();
  • 63. Describe data to Rules Drupal 7 • hook_rules_data_info() -> ? • hook_entity_property_info_alter -> ?
  • 64. Typed Data API • Consistent way of interacting with any data based on metadata • Part of Drupal 8 & Entity Fields • Defines a type system for PHP: ○ Primitive types (integer, float, string, dates, ..) ○ Complex types ○ Lists (with items of a specified type)
  • 65. Data types ● any ● string, integer, uri, float, ... ○ email ○ timestamp, datetime_iso8601 ○ timespan, duration_iso8601 ● entity ○ entity:node ○ entity:comment ● field_item ○ field_item:string ○ field_item:text ○ field_item:image
  • 66. /** * The float data type. * * The plain value of a float is a regular PHP float. For setting the value * any PHP variable that casts to a float may be passed. * * @DataType( * id = "float", * label = @Translation("Float") * ) */ class FloatData extends PrimitiveBase implements FloatInterface { /** * {@inheritdoc} */ public function getCastedValue() { return (float) $this->value; } }
  • 67. /** * The float data type. * * The plain value of a float is a regular PHP float. For setting the value * any PHP variable that casts to a float may be passed. * * @DataType( * id = "float", * label = @Translation("Float") * ) */ class FloatData extends PrimitiveBase implements FloatInterface { /** * {@inheritdoc} */ public function getCastedValue() { return (float) $this->value; } }
  • 68. /** * Plugin implementation of the 'link' field type. * * @FieldType( * id = "link", * label = @Translation("Link"), * description = @Translation(“..."), * default_widget = "link_default", * default_formatter = "link", * constraints = {"LinkType" = {}} * ) */ class LinkItem extends FieldItemBase implements LinkItemInterface { public static function propertyDefinitions( FieldStorageDefinitionInterface $field_definition) { $properties['url'] = DataDefinition::create('string') ->setLabel(t('URL')); … return $properties; }
  • 69. /** * Plugin implementation of the 'link' field type. * * @FieldType( * id = "link", * label = @Translation("Link"), * description = @Translation(“..."), * default_widget = "link_default", * default_formatter = "link", * constraints = {"LinkType" = {}} * ) */ class LinkItem extends FieldItemBase implements LinkItemInterface { public static function propertyDefinitions( FieldStorageDefinitionInterface $field_definition) { $properties['url'] = DataDefinition::create('string') ->setLabel(t('URL')); … return $properties; }
  • 70. Describe data to rules • hook_rules_data_info() -> ? • hook_entity_property_info_alter -> ?
  • 71. Describe data to rules • hook_rules_data_info() -> Data type plugins, Typed Data • hook_entity_property_info_alter -> hook_data_type_info_alter() -> hook_entity_base_field_info/alter() -> hook_entity_bundle_field_info/alter() -> FieldItem::propertyDefintions()
  • 72. Every content entity & field type in Drupal 8 is supported by Rules out-of-the box!
  • 77. Lists & Multiple values ● list<foo> notation is gone ● “list” data type & per data type class ● Separate data definitions for lists vs. list items ● Mark context as “multiple”
  • 78. Creating a Rule with context
  • 79. $rule = $this->expressionManager->createRule([ 'context_definitions' => [ 'test' => [ 'type' => 'string', 'label' => 'Test string', ], ], ]);
  • 80. $rule = $this->expressionManager->createRule([ 'context_definitions' => [ 'test' => [ 'type' => 'string', 'label' => 'Test string', ], ], ]); $rule->addCondition('rules_test_string_condition', ContextConfig::create() ->map('text', 'test') );
  • 81. $rule = $this->expressionManager->createRule([ 'context_definitions' => [ 'test' => [ 'type' => 'string', 'label' => 'Test string', ], ], ]); $rule->addCondition('rules_test_string_condition', ContextConfig::create() ->map('text', 'test') ); $rule->addAction('rules_test_log');
  • 82. $rule = $this->expressionManager->createRule([ 'context_definitions' => [ 'test' => [ 'type' => 'string', 'label' => 'Test string', ], ], ]); $rule->addCondition('rules_test_string_condition', ContextConfig::create() ->map('text', 'test') ); $rule->addAction('rules_test_log'); $rule->setContextValue('test', 'test value');
  • 83. $rule = $this->expressionManager->createRule([ 'context_definitions' => [ 'test' => [ 'type' => 'string', 'label' => 'Test string', ], ], ]); $rule->addCondition('rules_test_string_condition', ContextConfig::create() ->map('text', 'test') ); $rule->addAction('rules_test_log'); $rule->setContextValue('test', 'test value'); $rule->execute();
  • 84. Mapping required and provided context
  • 86. $rule = $this->expressionManager->createRule(); // Condition provides a "provided_text" variable. $rule->addCondition('rules_test_provider');
  • 87. $rule = $this->expressionManager->createRule(); // Condition provides a "provided_text" variable. $rule->addCondition('rules_test_provider'); // Action provides a "concatenated" variable. $rule->addAction('rules_test_string', ContextConfig::create() ->provideAs('text', 'provided_text') );
  • 88. $rule = $this->expressionManager->createRule(); // Condition provides a "provided_text" variable. $rule->addCondition('rules_test_provider'); // Action provides a "concatenated" variable. $rule->addAction('rules_test_string', ContextConfig::create() ->provideAs('text', 'provided_text') ); // Same action again now provides "concatenated2" $rule->addAction('rules_test_string', ContextConfig::create() ->map(text, 'concatenated') ->provideAs('concatenated', 'concatenated2') );
  • 89. $rule = $this->expressionManager->createRule(); // Condition provides a "provided_text" variable. $rule->addCondition('rules_test_provider'); // Action provides a "concatenated" variable. $rule->addAction('rules_test_string', ContextConfig::create() ->provideAs('text', 'provided_text') ); // Same action again now provides "concatenated2" $rule->addAction('rules_test_string', ContextConfig::create() ->map(text, 'concatenated') ->provideAs('concatenated', 'concatenated2') );
  • 90. Advanced / under the hood
  • 91. Provide other Rules plugins • hook_rules_plugin_info -> Implement a RulesExpression plugin
  • 92. Provide input evaluators • hook_rules_evaluator_info -> Implement a RulesDataProcessor plugin
  • 93. /** * A data processor for applying numerical offsets. * * The plugin configuration must contain the following entry: * - offset: the value that should be added. * * @RulesDataProcessor( * id = "rules_numeric_offset", * label = @Translation("Apply numeric offset") * ) */ class NumericOffset extends PluginBase implements RulesDataProcessorInterface { /** * {@inheritdoc} */ public function process($value) { return $value + $this->configuration['offset']; }
  • 95. Automated testing • RulesUnitTestBase extends UnitTestCase • Internal unit tests such as RuleTest, RulesAndTest, RulesContextTraitTest, …
  • 96. Automated testing • RulesUnitTestBase extends UnitTestCase • Internal unit tests such as RuleTest, RulesAndTest, RulesContextTraitTest, … • RulesIntegrationTestBase • use ActionManager, ConditionManager, TypedDataManager, …
  • 97. class DataListCountIs extends RulesConditionBase { /** * {@inheritdoc} */ public function evaluate() { $list = $this->getContextValue('list'); $operator = $this->getContextValue('operator'); $value = $this->getContextValue('value'); switch ($operator) { case '==': return count($list) == $value; case '<'; return count($list) < $value; case '>'; return count($list) > $value; }
  • 98. /** * Tests evaluating the condition. * * @covers ::evaluate() */ public function testConditionEvaluation() { // Test that the list count is greater than 2. $condition = $this->condition ->setContextValue('list', [1, 2, 3, 4]) ->setContextValue('operator', '>') ->setContextValue('value', '2'); $this->assertTrue($condition->evaluate()); // Test that the list count is not equal to 0. $condition = $this->condition ->setContextValue('list', [1, 2, 3]) ->setContextValue('operator', '==') ->setContextValue('value', '0'); $this->assertFalse($condition->evaluate()); }
  • 99. Automated testing • RulesUnitTestBase extends UnitTestCase • Internal unit tests such as RuleTest, RulesAndTest, RulesContextTraitTest, … • RulesIntegrationTestBase • use ActionManager, ConditionManager, TypedDataManager, …
  • 100. Automated testing • RulesUnitTestBase extends UnitTestCase • Internal unit tests such as RuleTest, RulesAndTest, RulesContextTraitTest, … • RulesIntegrationTestBase • use ActionManager, ConditionManager, TypedDataManager, … • RulesEntityIntegrationTestBase
  • 101. * @Condition( * id = "rules_entity_is_of_type", * label = @Translation("Entity is of type"), * category = @Translation("Entity"), * context = { * "entity" = @ContextDefinition("entity", * label = @Translation("Entity"), * ), * "type" = @ContextDefinition("string", * label = @Translation("Type"), * ) * } * ) */ class EntityIsOfType extends RulesConditionBase { public function evaluate() { $provided_entity = $this->getContextValue('entity'); $specified_type = $this->getContextValue('type'); $entity_type = $provided_entity->getEntityTypeId();
  • 102. /** * Tests evaluating the condition. * * @covers ::evaluate() */ public function testConditionEvaluation() { $entity = $this->getMock('DrupalCoreEntityEntityInterface'); $entity->expects($this->exactly(2)) ->method('getEntityTypeId') ->will($this->returnValue('node')); // Add the test node to our context as the evaluated entity. // First, test with a value that should evaluate TRUE. $this->condition->setContextValue('entity', $entity) ->setContextValue('type', 'node'); $this->assertTrue($this->condition->evaluate()); // Then test with values that should evaluate FALSE. $this->condition->setContextValue('type', 'taxonomy_term'); $this->assertFalse($this->condition->evaluate());
  • 103. /** * Tests evaluating the condition. * * @covers ::evaluate() */ public function testConditionEvaluation() { $entity = $this->getMock('DrupalCoreEntityEntityInterface'); $entity->expects($this->exactly(2)) ->method('getEntityTypeId') ->will($this->returnValue('node')); // Add the test node to our context as the evaluated entity. // First, test with a value that should evaluate TRUE. $this->condition->setContextValue('entity', $entity) ->setContextValue('type', 'node'); $this->assertTrue($this->condition->evaluate()); // Then test with values that should evaluate FALSE. $this->condition->setContextValue('type', 'taxonomy_term'); $this->assertFalse($this->condition->evaluate());
  • 104. /** * Tests evaluating the condition. * * @covers ::evaluate() */ public function testConditionEvaluation() { $entity = $this->getMock('DrupalCoreEntityEntityInterface'); $entity->expects($this->exactly(2)) ->method('getEntityTypeId') ->will($this->returnValue('node')); // Add the test node to our context as the evaluated entity. // First, test with a value that should evaluate TRUE. $this->condition->setContextValue('entity', $entity) ->setContextValue('type', 'node'); $this->assertTrue($this->condition->evaluate()); // Then test with values that should evaluate FALSE. $this->condition->setContextValue('type', 'taxonomy_term'); $this->assertFalse($this->condition->evaluate());
  • 105. /** * Tests evaluating the condition. * * @covers ::evaluate() */ public function testConditionEvaluation() { $entity = $this->getMock('DrupalCoreEntityEntityInterface'); $entity->expects($this->exactly(2)) ->method('getEntityTypeId') ->will($this->returnValue('node')); // Add the test node to our context as the evaluated entity. // First, test with a value that should evaluate TRUE. $this->condition->setContextValue('entity', $entity) ->setContextValue('type', 'node'); $this->assertTrue($this->condition->evaluate()); // Then test with values that should evaluate FALSE. $this->condition->setContextValue('type', 'taxonomy_term'); $this->assertFalse($this->condition->evaluate());
  • 108. Traits
  • 109. trait StringTranslationTrait { /** * The string translation service. * * @var DrupalCoreStringTranslationTranslationInterface */ protected $stringTranslation; /** * Translates a string to the current language or to a given language. * * See the t() documentation for details. */ protected function t($string, …) { return $this->getStringTranslation()->translate($string, …); } }
  • 110. class MyClass { use StringTranslationTrait; public function __construct( TranslationInterface $string_translation) { $this->stringTranslation = $string_translation; } /** * Does something. */ public function doSth() { // ... $string = $this->t('Something'); // ... } }
  • 111. Traits • RulesContextTrait • in addition to ContextAwarePluginBase • used in RulesActionBase and RulesConditionBase
  • 112. Outro
  • 114. Sprint with us! • Port actions & conditions • https://www.drupal.org/node/2245015
  • 115. Sprint with us! • Port actions & conditions • https://www.drupal.org/node/2245015
  • 119. NoFlo