Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Head Start Into TypoScript 2.0 -- Inspiring Conference 2014 in Kolbermoor

A Head Start Into TypoScript 2.0 -- Inspiring Conference 2014 in Kolbermoor

While TypoScript 2.0 shares the name with its ancestor from TYPO3 CMS, it has been a completely re-thought language focusing on extensibility and consistency. During this talk, we'll explain how to use this language, show its building blocks and advanced features. We will highlight the different parts of TypoScript, such as EEL and FlowQuery and we'll especially focus on patterns that make your TypoScript more extensible and easy to maintain.

#TYPO3 #TYPO3Neos #TYPO3Flow

30c0b6f50f67163bee8500aa4115d126?s=128

Sebastian Kurfürst

March 28, 2014
Tweet

Transcript

  1. A Head Start Into TypoScript 2.0 !

  2. Sebastian Kurfürst @skurfuerst sandstorm|media

  3. A short
 History of TypoScript

  4. an important part of TYPO3 CMS

  5. Configuration of basically almost everything Plugins Backend Behavior Page Rendering

    Extensions Permissions
  6. Back to the roots Page Rendering

  7. TypoScript in TYPO3 Neos is used to configure rendering

  8. TypoScript in TYPO3 Neos is used to configure „the V

    in MVC“
  9. Data to be shown ! e.g. page node Fluid Templates

    TypoScript
  10. Extensibility is implemented by TypoScript

  11. Divide and Conquer

  12. Getting Started

  13. Syntax # prototypes
 prototype(Bar) < prototype(Content) 
 # instantiation
 foo

    = Bar
 # processors
 foo.@process.wrapHeader = ${'<h1>' + value + '</h1>'}
 # data types
 string = "my string"
 number = 42
 eelExpression = ${[1, 2, 3]}
 boolean = TRUE
  14. None
  15. None
  16. None
  17. None
  18. None
  19. don’t be afraid

  20. None
  21. Building Blocks - the inner workings -

  22. Context contains rendered data

  23. features/teaser/text1 features features/main/2column1 features/main/2column1/left/header1 features/main/2column1/left/text1 features/main/2column1/right/header1 features/main/2column1/right/text1

  24. The context is side-effect free

  25. features/teaser/text1 features features/main/2column1 features/main/2column1/left/header1 features/main/2column1/left/text1 features/main/2column1/right/header1 features/main/2column1/right/text1 out-of-band rendering

  26. TypoScript Prototypes

  27. prototype(Acme:Slideshow) < prototype(TYPO3.Neos:Content) { @process.wrap = ${'<div class="slideshow">' + value

    + '</div>'} } ! # Instantiation mySlideshow = Acme:Slideshow Prototype Based Language
  28. Tree-Prototype Based # global prototype(Image).maximumWidth = … ! # local

    prototype(TwoColumn).prototype(Image).maximumWidth = … TwoColumn Image Image
  29. Eel and FlowQuery „JavaScript“ „jQuery“

  30. Eel prototype(TYPO3.Neos.NodeTypes:Headline) { title = } ${q(node).property('title')}

  31. Eel ${q(node).property('title')} Eel is the language + runtime FlowQuery is

    a library in Eel
  32. ${'<div class="wrapper">' + object.value + '</div>'}
 # columnLayout == 33-66


    # iterator.index == 0…1
 ${'span-' + 
 Math.round((String.split(columnLayout, '-')[iterator.index]) / 100 * 12))
 }
 # -> span-4
 # -> span-8 
 ${(iterator.index == 0 ? 'class="first"' : '')} Eel
  33. croppedText = ${String.substr(this.text, 10, 10)} firstCharacter = ${String.charAt(this.text, 0)} plainText

    = ${String.stripTags(this.text)} firstFewWords = ${String.cropAtWord(this.text, 200, '…')} firstFewSentences = ${String.cropAtSentence(this.text, 200)} ! roundedValue = ${Math.round(1.412, 1)} # == 1.4 ! speedMode = ${Configuration.setting('Foo.Bar.speedMode')} ! currentDate = ${Date.format(Date.now(), 'd-m-Y')} currentYear = ${Date.year(Date.now())} ! reversedArray = ${Array.reverse(['a', 'b', 'c'])} Additional Helpers in Eel
  34. FlowQuery ${q(node).closest('[instanceof Acme.Foo:WebsitePart]') .property('title')} ${q(site).find('[instanceof TYPO3.Neos.NodeTypes:Text]')} ${q(node).children('[instanceof TYPO3.Neos.NodeTypes:Text]') .property('title')} documentNode

    = the document node node == the current node site == the current site ! request == the current request
  35. FlowQuery ${q(node).children()} ${q(node).find('[instanceof TYPO3.Neos.NodeTypes:Text]')} ${q(node).children().get(0)} API resembles that of jQuery

    ${q(node).parents()} ${q(node).parents().count()} ${q(node).is('[instanceof TYPO3.Neos.NodeTypes:Page]')} ${q(node).is('[title ^= "Welcome"]')} ${q(node).is('[title ^= "Welcome"], [description ^= "Welcome"]')}
  36. using this

  37. None
  38. newestArticle = ${q(ElasticSearch.query(site).nodeType('Acme:Article')
 .sortDesc('datePublished').limit(1).execute()).get(0)}
 newestArticleImage = ${q(this.newestArticle).property('image')}
 newestArticleTitle = ${q(this.newestArticle)


    .parents('[instanceof TYPO3.Neos:Page]')
 .first().property('title')}
 newestArticleTeaserText = ${String.cropAtWord(q(this.newestArticle)
 .parents('[instanceof TYPO3.Neos:Page]')
 .first().property('teaser'), 200, '…')} prototype(Acme:ArticleTeaser) < prototype(Template) { } Define a TypoScript Object
  39. <div class="article-teaser"> <media:image asset="{newestArticleImage}" /> <h2>{newestArticleTitle}</h2> <p>{newestArticleTeaserText}</p> </div> The Corresponding

    Fluid Template
  40. None
  41. Extensibility Patterns

  42. Extend Everything!

  43. None
  44. /root root is a TYPO3.TypoScript:Case Object, which (most importantly)… !

    1. delegates rendering to /[requestFormat] 2. renders /page as fallback
  45. root { printLayout { condition = ${request.arguments.print} renderPath = '/print'

    } ! @cache.entryIdentifier.print = ${request.arguments.print} } ! print = … /root
  46. None
  47. override built-in rendering Example: adjust the built-in MultiColumn rendering

  48. prototype(TYPO3.Neos.NodeTypes:MultiColumn) { attributes.class = ${'row-fluid columns-' + q(node).property('layout')} columns.iterationName =

    'iterator' } prototype(TYPO3.Neos.NodeTypes:MultiColumn) { @override.columnLayout = ${q(node).property('layout')} ! prototype(TYPO3.Neos.NodeTypes:MultiColumnItem) { ! @override.columnSize = ${Math.round( String.split(columnLayout, '-')[iterator.index] / 100 * 12)} ! attributes.class = ${'span' + columnSize} } } Bootstrap 2
  49. prototype(TYPO3.Neos.NodeTypes:MultiColumn) { attributes.class = ${'row'} columns.iterationName = 'iterator' } prototype(TYPO3.Neos.NodeTypes:MultiColumn)

    { @override.columnLayout = ${q(node).property('layout')} ! prototype(TYPO3.Neos.NodeTypes:MultiColumnItem) { ! @override.columnSize = ${Math.round( String.split(columnLayout, '-')[iterator.index] / 100 * 12)} ! attributes.class = ${'large-' + columnSize + ' columns'} } } Zurb Foundation 5
  50. Processors

  51. x = "Hello" ! x.@process.1 = ${value + ' World'}

    x.@process.2 = ${value + '!'} Processors
  52. x = TYPO3.Neos.NodeTypes:Headline ! x.@process.1 = ${value + ' World'}

    x.@process.2 = ${value + '!'} Processors
  53. x = ${q(node).property('greeting')} ! x.@process.1 = ${value + ' World'}

    x.@process.2 = ${value + '!'} Processors
  54. x = ${q(node).property('greeting')} name = 'Robert' x.@process.1 = ${value +

    this.name} x.@process.2 = ${value + '!'} Processors
  55. x = ${q(node).property('greeting')} name = 'Robert' x.@process.1 = Some.Complex.TypoScript:Object x.@process.2

    = 'Does not make sense' Processors
  56. x.@process.1 = … ! ! ! ! x.@process.100 = …

    Processors - Ordering Syntax Magic Numbers
  57. x.@process.wrapWithText { expression = … @position = 1 } !

    x.@process.addFormControls { expression = … @position = 100 } Processors - Ordering Syntax Encouraged
  58. Processors - Ordering Syntax • start 100 • end •

    handles • after handles • 10 • 20 • before handles • start • end 100 see PositionalArraySorter class
  59. Caching already in master coming in Neos 1.1

  60. Summary

  61. None
  62. Thank You! ?

  63. None