Robert Lemke_


TYPO3 Flow 2.0
project founder of TYPO3 Flow and TYPO3 Neos

co-founder of the TYPO3 Association

coach, coder, consultant

36 years old

                      TEXT HERE
lives in Lübeck, Germany

1 wife, 2 daughters, 1 espresso machine

likes drumming
TYPO3 Flow Website and Download
Installation via Composer
$ curl -s https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer

$ composer create-project --stability="beta" --dev typo3/flow-base-
distribution MyProject
Set File Permissions

  $ sudo ./flow core:setfilepermissions robert _www _www
  TYPO3 Flow File Permission Script

  Checking permissions from here upwards.
  Making sure Data and Web/_Resources exist.
  Setting file permissions, trying to set ACLs via chmod ...
  Done.



Linux:


  $ sudo usermod -a -G www-data robert


Mac OS X:

  $ sudo dscl . -append /Groups/_www GroupMembership robert
Set Up Database Connection
Configuration/Settings.yaml
TYPO3:
  Flow:
    persistence:
       backendOptions:
         host: '127.0.0.1'      #   adjust   to   your   database   host
         dbname: 'training'     #   adjust   to   your   database   name
         user: 'root'           #   adjust   to   your   database   user
         password: 'password'   #   adjust   to   your   database   password

  # if you want to log executed SQL queries, enable the next 2 lines
  #    doctrine:
  #      sqlLogger: 'TYPO3FlowPersistenceDoctrineLoggingSqlLogger'

  # You might need to uncomment the following lines and specify
  # the location of the PHP binary manually.
  # core:
  #    phpBinaryPathAndFilename: 'C:/path/to/php.exe'
Set Up Virtual Host
Apache Virtual Host

 <VirtualHost *:80>
     DocumentRoot ~/Sites/Flow/Web/
     ServerName flow.dev
     SetEnv FLOW_CONTEXT Development
 </VirtualHost>

 <VirtualHost *:80>
     DocumentRoot ~/Sites/Flow/Web/
     ServerName flow.prod
     SetEnv FLOW_CONTEXT Production
 </VirtualHost>
Final Check
Command Line Use

$ ./flow help kickstart:package

Kickstart a new package

COMMAND:
  typo3.kickstart:kickstart:package

USAGE:
  ./flow kickstart:package <package key>

ARGUMENTS:
  --package-key           The package key, for example "MyCompany.MyPackageName"

DESCRIPTION:
  Creates a new package and creates a standard Action Controller and a sample
  template for its Index Action.

  For creating a new package without sample code use the package:create command.

SEE ALSO:
  typo3.flow:package:create (Create a new package)
Command Line Use

$ ./flow help kickstart:actioncontroller

Kickstart a new action controller

COMMAND:
  typo3.kickstart:kickstart:actioncontroller

USAGE:
  ./flow kickstart:actioncontroller [<options>] <package key> <controller name>

ARGUMENTS:
  --package-key        The package key of the package for the new controller
                       with an optional subpackage, (e.g.
                       "MyCompany.MyPackage/Admin").
  --controller-name    The name for the new controller. This may also be a
                       comma separated list of controller names.

OPTIONS:
  --generate-actions   Also generate index, new, create, edit, update and
                       delete actions.
  --generate-templates Also generate the templates for each action.
  --generate-related   Also create the mentioned package, related model and
                       repository if neccessary.
  --force              Overwrite any existing controller or template code.
                       Regardless of this flag, the package, model and
                       repository will never be overwritten.

DESCRIPTION:
Biggest Book Store: Amazon
Biggest River: Amazon River




                              © Google
Smallest River: Roe River




                            © Google
Smallest River: Roe River




                            © Google
Smallest River: Roe River




                            © Google
Smallest River: Roe River
Smallest Book Store: Roebooks
Sketchy Model
H e ll o Wo r ld …

 5        2                1   1
        Ro bert Lem ke
        D.P. F l u x t r
       time ();
Object Management

Dependency Injection
 _ a class doesn't create or retrieve the
   instance of another class but get's it
   injected
 _ fosters loosely-coupling and high
   cohesion
 _ more stable, reusable code
class SomeService {

      protected static $instance;

      public function getInstance() {
        if (self::$instance === NULL) {
          self::$instance = new self;
        }
        return self::$instance;
      }
}



class SomeOtherController {

    public function action() {
      $service = SomeService::getInstance();
      …
    }

}
class ServiceLocator {

      protected static $services = array();

      public function getInstance($name) {
        return self::$service[$name];
      }

}



class SomeOtherController {

    public function action() {
      $service = ServiceLocator::getInstance("SomeService");
      …
    }

}
class BookController extends ActionController {

    /**
     * @var BookRepository
     */
    protected $bookRepository;

    /**
      * @param BookRepository $bookRepository
      */
    public function __construct(BookRepository $bookRepository) {
       $this->bookRepository = $bookRepository;
    }

}
class BookController extends ActionController {

    /**
     * @var BookRepository
     */
    protected $bookRepository;

  /**
    * @param BookRepository $bookRepository
    */
  public function injectBookRepository(BookRepository
$bookRepository) {
     $this->bookRepository = $bookRepository;
  }

}
class BookController extends ActionController {

    /**
     * @FlowInject
     * @var BookRepository
     */
    protected $bookRepository;

}
TYPO3FlowSecurityCryptographyRsaWalletServiceInterface:
  className: TYPO3FlowSecurityCryptography
RsaWalletServicePhp
  scope: singleton
  properties:
    keystoreCache:
      object:
        factoryObjectName: TYPO3FLOW3CacheCacheManager
        factoryMethodName: getCache
        arguments:
          1:
             value: FLOW3_Security_Cryptography_RSAWallet
Object Management

Flow's take on Dependency Injection
 _ one of the first PHP implementations
   (started in 2006, improved ever since)
 _ object management for the whole lifecycle of
   all objects
 _ no unnecessary configuration if information
   can be gatered automatically (autowiring)
 _ intuitive use and no bad magical surprises
 _ fast! (like hardcoded or faster)
class Customer {

    /**
     * @FlowInject
     * @var AcmeCustomerNumberGenerator
     */
    protected $customerNumberGenerator;
     ...
}

$customer = new Customer();
$customer->getCustomerNumber();
Object Management
                           <?php
                           declare(ENCODING = 'u
                                                 tf-8');
                           namespace TYPO3Conf
Flow creates proxy         use TYPO3FlowAnnot
                                                erenceDomainModel
                                                ations as Flow;
                                                                     Conference;


classes                     /**
                             * Autogenerated Prox
for realizing DI and AOP     * @FlowScope(“proto
                             * @FlowEntity
                                                   y Class
                                                   type”)

magic                        */
                           class Paper extends
                                                 Paper_Original implem
                           TYPO3FlowPersiste                        ents TYPO3FlowObje
                                                 nceAspectPersisten                        c
                                                                      ceMagicInterface {
 _ new operator is            /**
                               * @var string
   supported                   * @ORMId
                               * @ORMColumn(length
                                                    ="40")
                               * introduced by TYPO
                                                    3FlowPersistenceA
                                                                         spectPersistenceMag
 _ proxy classes are           */
                             protected $Flow_Pers
                                                   istence_Identifier =
                                                                                              i

                                                                         NULL;
   created on the fly       private $Flow_AOP_Pr
                                                  oxy_targetMethodsAnd
                                                                       GroupedAdvices = arra
                                                                                             y
                            private $Flow_AOP_Pr
                                                  oxy_groupedAdviceCha
 _ in production context    private $Flow_AOP_Pr
                                                  oxy_methodIsInAdvice
                                                                       ins = array();


   all code is static                                                  Mode = array();

                           /**
                            * Autogenerated Prox
                                                 y Method
                            */
                           public function __co
                                                nstruct() {
Object Scope

 /**
  * @FlowScope("prototype")
  */
 class BookController extends ActionController {




 _ prototype: multiple instances for one request
 _ singleton: one unique instance for one request
 _ session: one unique instance for one session
 _ default scope: prototype.
Lifecycle Methods

/**
  * Called after the object has been constructed and all
  * dependencies have been injected
  *
  * @param integer $initializationCause
  * @return void
  */
public function initializeObject($initializationCause) {
    switch ($initializationCause) {
      case ObjectManagerInterface::INITIALIZATIONCAUSE_CREATED :
        …
      case ObjectManagerInterface::INITIALIZATIONCAUSE_RECREATED :
        …
    }
}
Lifecycle Methods

/**
  * Called shortly before the framework shuts down
  */
public function shutdownObject() {
}
Aspect-Oriented Programming

_ programming paradigm
_ separates concerns to improve modularization
_ OOP modularizes concerns into objects
_ AOP modularizes cross-cutting concerns into aspects


_ FLOW3 makes it easy (and possible at all)
  to use AOP in PHP
AOP
                           /**
                            * @Aspect
FLOW3 uses AOP for ...      * @Introduce
                                                    TYPO3FlowPe
                            */                                              rsistenceAsp
                                                                                                    ectPer
                          class Persist
                                                  enceMagicAspe
 _ persistence magic                                                     ct {
                             /**
                              * @Pointcut c
 _ logging                    */
                                                      lassTaggedWit
                                                                              h(entity) ||
                                                                                                      classT
                            public functi
                                                    on isEntityOr
                                                                           V a l u e O b j e c t( )
 _ debugging               /**
                                                                                                     {}

                             * After retur
                                                     ning advice,
                             *                                               making sure w
 _ security                 * @param TYP
                                                                                                     e have
                                                    O3FlowAOPJ
                            * @return voi                                   oinPointInter
                                                    d                                               face $j
                            * @Before cla
                                                    ssTaggedWith(
                           */                                              entity) && me
                                                                                                   thod(.*
                         public functi
                                                  on generateUU
                             $proxy = $joi                               I D( J o i n P o i n t I
                                                     n P o i n t- >g e t P r                      nterface
                            O b j e c t A c c e s s:                         oxy();
                                                     :setProperty(
                         }                                                  $proxy, 'Flow
                                                                                                    _Persis
Aspect

_ part of the application where cross-cutting concerns are
  implemented
_ in Flow aspects are classes annotated with
  @FlowAspect
Join Point

A single point in the call graph
 _ method execution
 _ exception
Join Point

A single point in the call graph
 _ method execution
 _ exception
Represents an event, not a location
Pointcut

A set of join points where advices could be executed
 _ can be composed
 _ can be named
Advice

Action to take at a join points defined by the point cut
Kinds of Advice

Advice types supported by Flow:
@FlowBefore
@FlowAfterReturning
@FlowAfterThrowing
@FlowAfter
@FlowAround
Pointcut Designators

method(AcmeDemoMyClass->myMethod())
class(AcmeDemoMyClass)
within(AcmeDemoMyInterface)
classAnnotatedWith(someTag)
methodAnnotatedWith(anotherTag)
setting(Acme.Demo.SomeSetting = "yeah, do it")
filter(AcmeDemoMyCustomFilterImplementation)

evaluate(coffe.kind = "Arabica")
/**
 * An aspect which centralizes the logging of important session actions.
 *
 * @FlowAspect
 * @FlowScope("singleton")
 */
class LoggingAspect {


     /**
      * @var TYPO3FlowLogSystemLoggerInterface
      * @FlowInject
      */
     protected $systemLogger;


     /**
      * Logs calls of start()
      *
      * @FlowAfter("within(TYPO3FlowSessionSessionInterface) && method(.*->start())"
      * @param TYPO3FlowAopJoinPointInterface $joinPoint The current joinpoint
      */
     public function logStart(TYPO3FlowAopJoinPointInterface $joinPoint) {
          $session = $joinPoint->getProxy();
          if ($session->isStarted()) {
            $this->systemLogger->log(sprintf('Started session with id %s', $session->getId(
Persistence

Object Persistence in the Flow
 _ based on Doctrine 2
 _ seamless integration into Flow
 _ provides all the great Doctrine 2
   features
 _ uses UUIDs
 _ low level persistence API
   _ allows for own, custom persistence
     backends (instead of Doctrine 2)
   _ e.g. CouchDB, Solr
// Create a new customer and persist it:
$customer = new Customer("Robert");
$this->customerRepository->add($customer);

  // Find an existing customer:
$otherCustomer = $this->customerRepository-
>findByFirstName("Karsten");

  // and delete it:
$this->customerRepository->remove($otherCustomer);
Annotations

In order to use less code, the following examples assume
that annotations have been imported directly:


 use TYPO3FlowAnnotationsEntity;

 /**
  * @Entity
  */
 class Foo {}
Validation and Doctrine Annotations
/**
 * @Entity
 */
class Blog {

    /**
     * @var string
     * @Validate Text, StringLength(minimum = 1, maximum = 80)
     * @Column(length="80")
     */
    protected $title;

    /**
     * @var DoctrineCommonCollectionsCollection<TYPO3Blog
DomainModelPost>
     * @OneToMany(mappedBy="blog")
     * @OrderBy({"date" = "DESC"})
     */
Persistence-related Annotations

@Entity       Declares a class as "entity"
@Column       Controls the database column related
              to the class property. Very useful for
              longer text content (type="text" !)
@ManyToOne    Defines relations to other entities.
@OneToMany    Unlike with vanilla Doctrine
@ManyToMany   targetEntity does not have to be given
@OneToOne     but will be reused from the @var
              annotation.

              cascade can be used to cascade
              operation to related objects.
Persistence-related Annotations




@var           Defines the type of a property,
               collections can be typed using angle
               brackets
               Collection<TYPO3ConferenceDomainModelComment>

@transient     The property will be ignored, it will
               neither be persisted nor reconstituted
@identity      Marks the property as part of an objects
               identity
Custom Queries using the
   Query Object Model
class PostRepository extends Repository {


    /**
     * Finds posts by the specified tag and blog
     *
     * @param TYPO3BlogDomainModelTag $tag
     * @param TYPO3BlogDomainModelBlog $blog The blog the post must refe
     * @return TYPO3FlowPersistenceQueryResultInterface The posts
     */
    public function findByTagAndBlog(TYPO3BlogDomainModelTag $tag,
      TYPO3BlogDomainModelBlog $blog) {
          $query = $this->createQuery();
          return $query->matching(
              $query->logicalAnd(
                  $query->equals('blog', $blog),
                  $query->contains('tags', $tag)
              )
Schema Management

Doctrine 2 Migrations

 _ Migrations allow schema versioning
   and change deployment
 _ Migrations are the recommended
   way for DB updates
 _ Tools to create and deploy migrations
   are integrated with Flow
Schema Management

Executing migration scripts
Needed after installation or upgrade:


$ ./flow doctrine:migrate
Schema Management

Manual database updates
Ad-hoc table and column creation, while you’re developing:


$ ./flow doctrine:create

$ ./flow doctrine:update
Schema Management

Generating migration scripts
Creates a basis for a migration script which sometimes
needs to be adjusted but in any case needs to be checked:

$ ./flow doctrine:migrationgenerate
Security

 _ centrally managed (through AOP)
 _ as secure as possible by default
 _ modeled after TYPO3 CMS and Spring Security
 _ authentication, authorization, validation, filtering ...
   _ can intercept arbitrary method calls
   _ transparently filters content through query-rewriting
 _ extensible for new authentication or authorization
   mechanisms
Accounts, Users, Authentication

Flow distinguishes between accounts and persons:
 _ account: TYPO3FlowSecurityAccount
 _ person: TYPO3PartyDomainModelPerson


A person (or machine) can have any number of accounts.
Creating Accounts

 _ always use the AccountFactory
 _ create a party (eg. a Person) separately
 _ assign the account to the party
 _ add account and party to their respective repositories
$account = $this->accountFactory->createAccountWithPassword(
   $accountIdentifier,
   $password,
   array($role)
);

$this->accountRepository->add($account);

$person = new Person();
$person->addAccount($account);

$name = new PersonName('', 'Robert', '', 'Lemke');
$person->setName($name);

$this->partyRepository->add($person);
Authentication Configuration

 _ Authentication Provider is responsible for
   authentication in a specific "area"
 _ Entry Point kicks in if a restricted resource is accessed
   and no account is authenticated yet
TYPO3:
  Flow:
    security:
       authentication:
         providers:
           DefaultProvider:
             provider: 'PersistedUsernamePasswordProvider'
             entryPoint: 'WebRedirect'
             entryPointOptions:
               routeValues:
                 '@package': 'RobertLemke.Example.Bookshop'
                 '@controller': 'Login'
                 '@action': 'login'
                 '@format': 'html'
Security Policy (policy.yaml)

 _ resources
   defines what can potentially be protected
 _ roles
   defines who can potentially be granted or denied access
 _ acls
   defines who may or may not access which resource
resources:
  methods:
    BookManagementMethods: 'method(.*Controller->(new|edit|create|
delete|update)Action())'
    BookManagementDelete: 'method(.*BookController->deleteAction())'

roles:
  Administrator: []



acls:
  methods:
    Administrator:
      BookManagementMethods: GRANT
Login / Logout

 _ simply extend AbstractAuthenticationController
 _ create a Fluid template with a login form
/**
 * @FlowScope("singleton")
 */
class LoginController extends AbstractAuthenticationController {

    /**
      * @param TYPO3FlowMvcActionRequest $originalRequest The request
      * @return string
      */
    protected function onAuthenticationSuccess(ActionRequest $originalRe
       $this->redirect('index', 'Book');
    }

    /**
      * @return void
      */
    public function logoutAction() {
       parent::logoutAction();
       $this->redirect('index', 'Book');
    }
}
<f:base/>
<f:flashMessages />
<f:form action="authenticate">
  <f:form.textfield name="__authentication[TYPO3][Flow][Security]
[Authentication][Token][UsernamePassword][username]" />
  <f:form.password name="__authentication[TYPO3][Flow][Security]
[Authentication][Token][UsernamePassword][password]" />
  <f:form.submit value="login" />
</f:form>
Security

Cross-Site Request Forgery
 _ enables an attacker to execute privileged operations
   without being authenticated
 _ the risk lies in using malicious links or forms while still
   being authenticated
 _ imagine a link coming in through an URL shortener...
Security

Avoiding Cross-Site Request Forgery
 _ add a (truly!) random string token to each link or form
 _ make sure this token is correct before executing
   anything


 _ change the token as often as possible to make it
   impossible to send you a working malicious link while
   you’re logged in
 _ in most cases, we can assume that it should be enough
   to generate one token when you log in – that’s the
   default
Security

CSRF Protection in Flow
 _ you must not forget to add that token to any link
 _ Flow automatically adds the CSRF token to each
   _ link you generate
   _ each form you create with Fluid
 _ and checks it for every call to a protected action
 _ the protection can be disabled using
   @skipCsrfProtection on an action
Robert Lemke_
robertlemke.com
@robertlemke

TYPO3 Flow 2.0 Workshop T3BOARD13

  • 1.
  • 2.
    project founder ofTYPO3 Flow and TYPO3 Neos co-founder of the TYPO3 Association coach, coder, consultant 36 years old TEXT HERE lives in Lübeck, Germany 1 wife, 2 daughters, 1 espresso machine likes drumming
  • 3.
    TYPO3 Flow Websiteand Download
  • 4.
    Installation via Composer $curl -s https://getcomposer.org/installer | php $ sudo mv composer.phar /usr/local/bin/composer $ composer create-project --stability="beta" --dev typo3/flow-base- distribution MyProject
  • 5.
    Set File Permissions $ sudo ./flow core:setfilepermissions robert _www _www TYPO3 Flow File Permission Script Checking permissions from here upwards. Making sure Data and Web/_Resources exist. Setting file permissions, trying to set ACLs via chmod ... Done. Linux: $ sudo usermod -a -G www-data robert Mac OS X: $ sudo dscl . -append /Groups/_www GroupMembership robert
  • 6.
    Set Up DatabaseConnection Configuration/Settings.yaml TYPO3: Flow: persistence: backendOptions: host: '127.0.0.1' # adjust to your database host dbname: 'training' # adjust to your database name user: 'root' # adjust to your database user password: 'password' # adjust to your database password # if you want to log executed SQL queries, enable the next 2 lines # doctrine: # sqlLogger: 'TYPO3FlowPersistenceDoctrineLoggingSqlLogger' # You might need to uncomment the following lines and specify # the location of the PHP binary manually. # core: # phpBinaryPathAndFilename: 'C:/path/to/php.exe'
  • 7.
    Set Up VirtualHost Apache Virtual Host <VirtualHost *:80> DocumentRoot ~/Sites/Flow/Web/ ServerName flow.dev SetEnv FLOW_CONTEXT Development </VirtualHost> <VirtualHost *:80> DocumentRoot ~/Sites/Flow/Web/ ServerName flow.prod SetEnv FLOW_CONTEXT Production </VirtualHost>
  • 8.
  • 9.
    Command Line Use $./flow help kickstart:package Kickstart a new package COMMAND: typo3.kickstart:kickstart:package USAGE: ./flow kickstart:package <package key> ARGUMENTS: --package-key The package key, for example "MyCompany.MyPackageName" DESCRIPTION: Creates a new package and creates a standard Action Controller and a sample template for its Index Action. For creating a new package without sample code use the package:create command. SEE ALSO: typo3.flow:package:create (Create a new package)
  • 10.
    Command Line Use $./flow help kickstart:actioncontroller Kickstart a new action controller COMMAND: typo3.kickstart:kickstart:actioncontroller USAGE: ./flow kickstart:actioncontroller [<options>] <package key> <controller name> ARGUMENTS: --package-key The package key of the package for the new controller with an optional subpackage, (e.g. "MyCompany.MyPackage/Admin"). --controller-name The name for the new controller. This may also be a comma separated list of controller names. OPTIONS: --generate-actions Also generate index, new, create, edit, update and delete actions. --generate-templates Also generate the templates for each action. --generate-related Also create the mentioned package, related model and repository if neccessary. --force Overwrite any existing controller or template code. Regardless of this flag, the package, model and repository will never be overwritten. DESCRIPTION:
  • 11.
  • 12.
    Biggest River: AmazonRiver © Google
  • 13.
    Smallest River: RoeRiver © Google
  • 14.
    Smallest River: RoeRiver © Google
  • 15.
    Smallest River: RoeRiver © Google
  • 16.
  • 17.
  • 18.
  • 19.
    H e llo Wo r ld … 5 2 1 1 Ro bert Lem ke D.P. F l u x t r time ();
  • 20.
    Object Management Dependency Injection _ a class doesn't create or retrieve the instance of another class but get's it injected _ fosters loosely-coupling and high cohesion _ more stable, reusable code
  • 21.
    class SomeService { protected static $instance; public function getInstance() { if (self::$instance === NULL) { self::$instance = new self; } return self::$instance; } } class SomeOtherController { public function action() { $service = SomeService::getInstance(); … } }
  • 22.
    class ServiceLocator { protected static $services = array(); public function getInstance($name) { return self::$service[$name]; } } class SomeOtherController { public function action() { $service = ServiceLocator::getInstance("SomeService"); … } }
  • 23.
    class BookController extendsActionController { /** * @var BookRepository */ protected $bookRepository; /** * @param BookRepository $bookRepository */ public function __construct(BookRepository $bookRepository) { $this->bookRepository = $bookRepository; } }
  • 24.
    class BookController extendsActionController { /** * @var BookRepository */ protected $bookRepository; /** * @param BookRepository $bookRepository */ public function injectBookRepository(BookRepository $bookRepository) { $this->bookRepository = $bookRepository; } }
  • 25.
    class BookController extendsActionController { /** * @FlowInject * @var BookRepository */ protected $bookRepository; }
  • 26.
    TYPO3FlowSecurityCryptographyRsaWalletServiceInterface: className:TYPO3FlowSecurityCryptography RsaWalletServicePhp scope: singleton properties: keystoreCache: object: factoryObjectName: TYPO3FLOW3CacheCacheManager factoryMethodName: getCache arguments: 1: value: FLOW3_Security_Cryptography_RSAWallet
  • 27.
    Object Management Flow's takeon Dependency Injection _ one of the first PHP implementations (started in 2006, improved ever since) _ object management for the whole lifecycle of all objects _ no unnecessary configuration if information can be gatered automatically (autowiring) _ intuitive use and no bad magical surprises _ fast! (like hardcoded or faster)
  • 28.
    class Customer { /** * @FlowInject * @var AcmeCustomerNumberGenerator */ protected $customerNumberGenerator; ... } $customer = new Customer(); $customer->getCustomerNumber();
  • 29.
    Object Management <?php declare(ENCODING = 'u tf-8'); namespace TYPO3Conf Flow creates proxy use TYPO3FlowAnnot erenceDomainModel ations as Flow; Conference; classes /** * Autogenerated Prox for realizing DI and AOP * @FlowScope(“proto * @FlowEntity y Class type”) magic */ class Paper extends Paper_Original implem TYPO3FlowPersiste ents TYPO3FlowObje nceAspectPersisten c ceMagicInterface { _ new operator is /** * @var string supported * @ORMId * @ORMColumn(length ="40") * introduced by TYPO 3FlowPersistenceA spectPersistenceMag _ proxy classes are */ protected $Flow_Pers istence_Identifier = i NULL; created on the fly private $Flow_AOP_Pr oxy_targetMethodsAnd GroupedAdvices = arra y private $Flow_AOP_Pr oxy_groupedAdviceCha _ in production context private $Flow_AOP_Pr oxy_methodIsInAdvice ins = array(); all code is static Mode = array(); /** * Autogenerated Prox y Method */ public function __co nstruct() {
  • 30.
    Object Scope /** * @FlowScope("prototype") */ class BookController extends ActionController { _ prototype: multiple instances for one request _ singleton: one unique instance for one request _ session: one unique instance for one session _ default scope: prototype.
  • 31.
    Lifecycle Methods /** * Called after the object has been constructed and all * dependencies have been injected * * @param integer $initializationCause * @return void */ public function initializeObject($initializationCause) { switch ($initializationCause) { case ObjectManagerInterface::INITIALIZATIONCAUSE_CREATED : … case ObjectManagerInterface::INITIALIZATIONCAUSE_RECREATED : … } }
  • 32.
    Lifecycle Methods /** * Called shortly before the framework shuts down */ public function shutdownObject() { }
  • 33.
    Aspect-Oriented Programming _ programmingparadigm _ separates concerns to improve modularization _ OOP modularizes concerns into objects _ AOP modularizes cross-cutting concerns into aspects _ FLOW3 makes it easy (and possible at all) to use AOP in PHP
  • 34.
    AOP /** * @Aspect FLOW3 uses AOP for ... * @Introduce TYPO3FlowPe */ rsistenceAsp ectPer class Persist enceMagicAspe _ persistence magic ct { /** * @Pointcut c _ logging */ lassTaggedWit h(entity) || classT public functi on isEntityOr V a l u e O b j e c t( ) _ debugging /** {} * After retur ning advice, * making sure w _ security * @param TYP e have O3FlowAOPJ * @return voi oinPointInter d face $j * @Before cla ssTaggedWith( */ entity) && me thod(.* public functi on generateUU $proxy = $joi I D( J o i n P o i n t I n P o i n t- >g e t P r nterface O b j e c t A c c e s s: oxy(); :setProperty( } $proxy, 'Flow _Persis
  • 36.
    Aspect _ part ofthe application where cross-cutting concerns are implemented _ in Flow aspects are classes annotated with @FlowAspect
  • 37.
    Join Point A singlepoint in the call graph _ method execution _ exception
  • 38.
    Join Point A singlepoint in the call graph _ method execution _ exception Represents an event, not a location
  • 39.
    Pointcut A set ofjoin points where advices could be executed _ can be composed _ can be named
  • 40.
    Advice Action to takeat a join points defined by the point cut
  • 41.
    Kinds of Advice Advicetypes supported by Flow: @FlowBefore @FlowAfterReturning @FlowAfterThrowing @FlowAfter @FlowAround
  • 42.
  • 43.
    /** * Anaspect which centralizes the logging of important session actions. * * @FlowAspect * @FlowScope("singleton") */ class LoggingAspect { /** * @var TYPO3FlowLogSystemLoggerInterface * @FlowInject */ protected $systemLogger; /** * Logs calls of start() * * @FlowAfter("within(TYPO3FlowSessionSessionInterface) && method(.*->start())" * @param TYPO3FlowAopJoinPointInterface $joinPoint The current joinpoint */ public function logStart(TYPO3FlowAopJoinPointInterface $joinPoint) { $session = $joinPoint->getProxy(); if ($session->isStarted()) { $this->systemLogger->log(sprintf('Started session with id %s', $session->getId(
  • 44.
    Persistence Object Persistence inthe Flow _ based on Doctrine 2 _ seamless integration into Flow _ provides all the great Doctrine 2 features _ uses UUIDs _ low level persistence API _ allows for own, custom persistence backends (instead of Doctrine 2) _ e.g. CouchDB, Solr
  • 45.
    // Create anew customer and persist it: $customer = new Customer("Robert"); $this->customerRepository->add($customer); // Find an existing customer: $otherCustomer = $this->customerRepository- >findByFirstName("Karsten"); // and delete it: $this->customerRepository->remove($otherCustomer);
  • 46.
    Annotations In order touse less code, the following examples assume that annotations have been imported directly: use TYPO3FlowAnnotationsEntity; /** * @Entity */ class Foo {}
  • 47.
    Validation and DoctrineAnnotations /** * @Entity */ class Blog { /** * @var string * @Validate Text, StringLength(minimum = 1, maximum = 80) * @Column(length="80") */ protected $title; /** * @var DoctrineCommonCollectionsCollection<TYPO3Blog DomainModelPost> * @OneToMany(mappedBy="blog") * @OrderBy({"date" = "DESC"}) */
  • 48.
    Persistence-related Annotations @Entity Declares a class as "entity" @Column Controls the database column related to the class property. Very useful for longer text content (type="text" !) @ManyToOne Defines relations to other entities. @OneToMany Unlike with vanilla Doctrine @ManyToMany targetEntity does not have to be given @OneToOne but will be reused from the @var annotation. cascade can be used to cascade operation to related objects.
  • 49.
    Persistence-related Annotations @var Defines the type of a property, collections can be typed using angle brackets Collection<TYPO3ConferenceDomainModelComment> @transient The property will be ignored, it will neither be persisted nor reconstituted @identity Marks the property as part of an objects identity
  • 50.
    Custom Queries usingthe Query Object Model class PostRepository extends Repository { /** * Finds posts by the specified tag and blog * * @param TYPO3BlogDomainModelTag $tag * @param TYPO3BlogDomainModelBlog $blog The blog the post must refe * @return TYPO3FlowPersistenceQueryResultInterface The posts */ public function findByTagAndBlog(TYPO3BlogDomainModelTag $tag, TYPO3BlogDomainModelBlog $blog) { $query = $this->createQuery(); return $query->matching( $query->logicalAnd( $query->equals('blog', $blog), $query->contains('tags', $tag) )
  • 51.
    Schema Management Doctrine 2Migrations _ Migrations allow schema versioning and change deployment _ Migrations are the recommended way for DB updates _ Tools to create and deploy migrations are integrated with Flow
  • 52.
    Schema Management Executing migrationscripts Needed after installation or upgrade: $ ./flow doctrine:migrate
  • 53.
    Schema Management Manual databaseupdates Ad-hoc table and column creation, while you’re developing: $ ./flow doctrine:create $ ./flow doctrine:update
  • 54.
    Schema Management Generating migrationscripts Creates a basis for a migration script which sometimes needs to be adjusted but in any case needs to be checked: $ ./flow doctrine:migrationgenerate
  • 55.
    Security _ centrallymanaged (through AOP) _ as secure as possible by default _ modeled after TYPO3 CMS and Spring Security _ authentication, authorization, validation, filtering ... _ can intercept arbitrary method calls _ transparently filters content through query-rewriting _ extensible for new authentication or authorization mechanisms
  • 56.
    Accounts, Users, Authentication Flowdistinguishes between accounts and persons: _ account: TYPO3FlowSecurityAccount _ person: TYPO3PartyDomainModelPerson A person (or machine) can have any number of accounts.
  • 57.
    Creating Accounts _always use the AccountFactory _ create a party (eg. a Person) separately _ assign the account to the party _ add account and party to their respective repositories
  • 58.
    $account = $this->accountFactory->createAccountWithPassword( $accountIdentifier, $password, array($role) ); $this->accountRepository->add($account); $person = new Person(); $person->addAccount($account); $name = new PersonName('', 'Robert', '', 'Lemke'); $person->setName($name); $this->partyRepository->add($person);
  • 59.
    Authentication Configuration _Authentication Provider is responsible for authentication in a specific "area" _ Entry Point kicks in if a restricted resource is accessed and no account is authenticated yet
  • 60.
    TYPO3: Flow: security: authentication: providers: DefaultProvider: provider: 'PersistedUsernamePasswordProvider' entryPoint: 'WebRedirect' entryPointOptions: routeValues: '@package': 'RobertLemke.Example.Bookshop' '@controller': 'Login' '@action': 'login' '@format': 'html'
  • 61.
    Security Policy (policy.yaml) _ resources defines what can potentially be protected _ roles defines who can potentially be granted or denied access _ acls defines who may or may not access which resource
  • 62.
    resources: methods: BookManagementMethods: 'method(.*Controller->(new|edit|create| delete|update)Action())' BookManagementDelete: 'method(.*BookController->deleteAction())' roles: Administrator: [] acls: methods: Administrator: BookManagementMethods: GRANT
  • 63.
    Login / Logout _ simply extend AbstractAuthenticationController _ create a Fluid template with a login form
  • 64.
    /** * @FlowScope("singleton") */ class LoginController extends AbstractAuthenticationController { /** * @param TYPO3FlowMvcActionRequest $originalRequest The request * @return string */ protected function onAuthenticationSuccess(ActionRequest $originalRe $this->redirect('index', 'Book'); } /** * @return void */ public function logoutAction() { parent::logoutAction(); $this->redirect('index', 'Book'); } }
  • 65.
    <f:base/> <f:flashMessages /> <f:form action="authenticate"> <f:form.textfield name="__authentication[TYPO3][Flow][Security] [Authentication][Token][UsernamePassword][username]" /> <f:form.password name="__authentication[TYPO3][Flow][Security] [Authentication][Token][UsernamePassword][password]" /> <f:form.submit value="login" /> </f:form>
  • 66.
    Security Cross-Site Request Forgery _ enables an attacker to execute privileged operations without being authenticated _ the risk lies in using malicious links or forms while still being authenticated _ imagine a link coming in through an URL shortener...
  • 67.
    Security Avoiding Cross-Site RequestForgery _ add a (truly!) random string token to each link or form _ make sure this token is correct before executing anything _ change the token as often as possible to make it impossible to send you a working malicious link while you’re logged in _ in most cases, we can assume that it should be enough to generate one token when you log in – that’s the default
  • 68.
    Security CSRF Protection inFlow _ you must not forget to add that token to any link _ Flow automatically adds the CSRF token to each _ link you generate _ each form you create with Fluid _ and checks it for every call to a protected action _ the protection can be disabled using @skipCsrfProtection on an action
  • 69.