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

Migrating from TYPO3 CMS to TYPO3 Neos

Migrating from TYPO3 CMS to TYPO3 Neos

Moving from TYPO3 CMS to TYPO3 Neos is not for everyone. This presentation looks briefly at the key factors of the usefulness of a migration. Then it covers migration of things like TypoScript, templates and configuration as well as look at what to do with extensions and existing content. Afterwards you should be able to confidently judge if a migration is worth the effort.

Karsten Dambekalns

March 28, 2014
Tweet

More Decks by Karsten Dambekalns

Other Decks in Programming

Transcript

  1. M I G R AT I N G F R

    O M T Y P O 3 C M S T O N E O S I N S P I R I N G C O N F E R E N C E 2 0 1 4
  2. A B O U T M E • TYPO3 Neos

    and Flow developer • 36 years old • lives in Lübeck • works at TechDivision • 1 wife, 3 sons • 1 espresso machine • likes canoeing & climbing K A R S T E N D A M B E K A L N S
  3. W H Y D O Y O U N E

    E D T O M I G R AT E ? D E C I S I O N
  4. T Y P O 3 V E R S I

    O N R E A C H E D E O L • You want to use a supported (LTS) version • Are you happy with TYPO3? • Are your extensions ready for the next LTS? • Why not migrate to the next LTS version?
  5. H O W M U C H W O R

    K I S I T ? I H A V E N O I D E A
  6. W E B S I T E I S B

    E I N G R E D O N E • No longer happy with TYPO3? • Looking at alternatives already? • Are you eager to learn something new? • Migrate to Neos! F L I C K R . C O M – K O N N E X U S
  7. H O W M U C H W O R

    K I S I T ? W E W I L L L O O K A T T H A T D U R I N G T H I S TA L K
  8. F I R S T S O M E B

    L O C K E R S B U T, L E T ’ S B E H O N E S T ( I F T I M E I S A N I S S U E )
  9. B L O C K E R S F O

    R U S I N G N E O S ! • fine-grained access control for editors • front end user access control • multi-language aware user interface • tools for working with large amounts of data Neos 1.1 will not have
  10. T H E F U T U R E I

    S N E A R • Internal support for content dimensions Neos 1.1 will have • Content Dimension support in the UI • Fine-grained permissions / ACL support Neos 1.2 will have one of
  11. C O N T E N T F I R

    S T P R E PA R A T I O N
  12. C O N T E N T I N V

    E N T O RY • Most important task! • Look at your content • Categorize it • Prioritize it F L I C K R . C O M – B E S S E R E _ Z U K U N F T _ E V
  13. C O N T E N T S T R

    U C T U R E • Most important task, too! • Plan your content structure • Use freely defined node types for your content • If you need blocks or columns on your site, give them a meaning F L I C K R . C O M – S N A P S I 4 2
  14. M I G R AT I O N D O

    I N G T H E F L I C K R . C O M – J A C K A L 1
  15. T Y P O S C R I P T

    M I G R A T I O N
  16. D O N ’ T D O I T. Q

    U I C K A N D E A S Y A N S W E R
  17. T Y P O S C R I P T

    I N N E O S • Neos uses it only for configuring the rendering • New syntax, other possibilities • Use of templates for content, less tweaks needed • Most sites will need less TypoScript
  18. D E S I G N & T E M

    P L AT E S M I G R A T I O N
  19. D E S I G N & T E M

    P L AT E S • If you redesign: wait, do content first • Reusing HTML templates & CSS is no problem • No more marker templates: Fluid and TypoScript
 • see IntegratorGuide/AdjustingOutput.html
  20. D E S I G N & T E M

    P L AT E S • Basically you can do whatever you like! • HTML5, jQuery, Bootstrap, Zurb Foundation, … • But watch out for • JavaScript conflicts • Media Queries / Responsive Design
  21. <body> <f:section name="body"> ! <div class="menu"> <ts:render path="parts.menu" /> </div>

    ! <div id="masthead"> <div class=“content"> <ts:render path="content.masthead" /> </div> </div> ! <div class="content"> <ts:render path="content.main" /> </div> ! </f:section> </body>
  22. page.body { templatePath = 'resource://Acme.Demo/Private/Templates/Page/Default.html' sectionName = 'body' ! parts

    { menu = Menu menu { templatePath = 'resource://Acme.Cemo/Private/Templates/Menu.html' } } ! content { masthead = ContentCollection masthead.nodePath = 'masthead' ! main = PrimaryContent main.nodePath = 'main' } }
  23. E X T E N S I O N S

    M I G R A T I O N
  24. E X T E N S I O N S

    • Your new content may not even need extensions • Use NodeTypes and TypoScript instead of extensions • Write custom Eel helpers or Fluid ViewHelpers • Implement a custom node type in PHP
  25. E X T E N S I O N S

    • You might still need a “real plugin” • Flow is the base for extensions to Neos • For business logic code reuse is possible ! • see IntegratorGuide/CreatingAPlugin.html
  26. C O N T E N T M I G

    R A T I O N F L I C K R . C O M – M A R C G O E RT Z
  27. U S I N G X M L WA Y

    S T O M I G R A T E
  28. • Use the impexp extension to export to XML •

    Use XSLT to transform into the XML format of Neos • Import into Neos <type>string</type> <tokenID>dddf74f333c1655240381a30e <tokenValue>http://www.yaml.de/</t </subst> </softref_element> </softrefs> </rec> <rec index="690" type="array"> <uid>690</uid> <pid>403</pid> <title>Padomi, kā iepirkties. Ja kas, zvani 277... <size>3952</size> <relations index="rels" type="array"> </relations> <softrefs type="array"> <softref_element index="bodytext:typolink_tag <field>bodytext</field> <spKey>typolink_tag</spKey> <matchString>http://www.motolietas.lv _t <subst type="array"> <type>string</type> <tokenID>618089b60ec48edc6433fdc60 <tokenValue>http://www.motolietas. </subst> </softref_element> <softref_element index="bodytext:typolink_tag <field>bodytext</field> <spKey>typolink_tag</spKey> <matchString>e-pasts.html _blank externa </softref_element> <softref_element index="bodytext:typolink_tag <field>bodytext</field> <spKey>typolink_tag</spKey> <matchString>e-pasts.html _blank externa </softref_element> </softrefs> </rec> <rec index="706" type="array"> <uid>706</uid>
  29. • impexp exports way more than we need • XSLT

    knowledge needed • Does not work for huge sites ! • see https://github.com/crusoe/TYPO3-Transition-Tool
  30. R A W D ATA B A S E A

    C C E S S WA Y S T O M I G R A T E
  31. • Read from the TYPO3 database directly • Apply transformations

    as needed • Create nodes in Neos from that data
  32. CREATE TABLE `tt_content` ( `uid` int(11) NOT NULL AUTO_INCREMENT, `pid`

    int(11) NOT NULL DEFAULT '0', `t3ver_oid` int(11) NOT NULL DEFAULT '0', `t3ver_id` int(11) NOT NULL DEFAULT '0', `t3ver_wsid` int(11) NOT NULL DEFAULT '0', `t3ver_label` varchar(255) NOT NULL DEFAULT '', `t3ver_state` tinyint(4) NOT NULL DEFAULT '0', `t3ver_stage` int(11) NOT NULL DEFAULT '0', `t3ver_count` int(11) NOT NULL DEFAULT '0', `t3ver_tstamp` int(11) NOT NULL DEFAULT '0', `t3_origuid` int(11) NOT NULL DEFAULT '0', `tstamp` int(11) unsigned NOT NULL DEFAULT '0', `hidden` tinyint(4) unsigned NOT NULL DEFAULT '0', `sorting` int(11) unsigned NOT NULL DEFAULT '0', `CType` varchar(30) NOT NULL DEFAULT '', `header` varchar(255) NOT NULL DEFAULT '', `header_position` varchar(6) NOT NULL DEFAULT '', `bodytext` mediumtext, `image` text, `imagewidth` mediumint(11) unsigned NOT NULL DEFAULT '0', `imageorient` tinyint(4) unsigned NOT NULL DEFAULT '0', `imagecaption` text, `imagecols` tinyint(4) unsigned NOT NULL DEFAULT '0', `imageborder` tinyint(4) unsigned NOT NULL DEFAULT '0', `media` text, `layout` tinyint(3) unsigned NOT NULL DEFAULT '0', `deleted` tinyint(4) unsigned NOT NULL DEFAULT '0', `cols` tinyint(3) unsigned NOT NULL DEFAULT '0', `records` text, `pages` tinytext, `starttime` int(11) unsigned NOT NULL DEFAULT '0', `endtime` int(11) unsigned NOT NULL DEFAULT '0', `colPos` tinyint(3) unsigned NOT NULL DEFAULT '0', `subheader` varchar(255) NOT NULL DEFAULT '', `spaceBefore` smallint(5) unsigned NOT NULL DEFAULT '0', `spaceAfter` smallint(5) unsigned NOT NULL DEFAULT '0', `fe_group` varchar(100) NOT NULL DEFAULT '0', `header_link` varchar(255) NOT NULL DEFAULT '', `imagecaption_position` varchar(6) NOT NULL DEFAULT '', • Do not migrate everything! • Which content types are needed? • Which fields are really used? • Which are misused?
  33. R E A D I N G T H E

    D ATA • Use plain PDO, Doctrine DBAL, … • Fetch only the needed fields • Return raw data
  34. R E A D I N G T H E

    D ATA /** * Returns raw tt_content data for the article uid * * @param integer $articleUid * @return array */ public function getArticleContent($articleUid) { $sql = sprintf('SELECT uid, hidden, CType, header, header_layout, bodytext, tx_templavoila_to, image, imageorient, imagecaption, imagecols, image_link, altText, titleText, pi_flexform FROM tt_content WHERE deleted = 0 AND irre_parenttable = \'tx_t3blog_post\' AND irre_parentid = %u ORDER BY sorting ASC', $articleUid); $statement = $this->connection->prepare($sql); $statement->execute(); ! return $statement->fetchAll(\PDO::FETCH_ASSOC); }
  35. R E A D I N G T H E

    D ATA /** * Returns an array of raw article data * * @return array */ public function getArticles() { $sql = sprintf('SELECT p.uid, p.uuid, p.hidden, p.title, p.subtitle, p.date, p.starttime, p.endtime, p.top_3_image, u.realName AS author, c.uid AS maincategory, c.catname AS maincategoryname, GROUP_CONCAT(c.uid ORDER BY mm.sorting DESC SEPARATOR \',\') AS categories, p.searchwords, r.value_alias as realurl_uniqalias FROM tx_t3blog_post p LEFT JOIN be_users u ON p.author=u.uid LEFT JOIN tx_t3blog_post_cat_mm mm ON p.uid=mm.uid_local LEFT JOIN tx_t3blog_cat c ON c.uid=mm.uid_foreign LEFT JOIN tx_realurl_uniqalias r ON r.value_id=p.uid AND r.tablename=\'tx_t3blog_post\' WHERE p.pid=%u AND p.deleted=0 GROUP BY p.uid ORDER BY p.date DESC, mm.sorting ASC', $this->settings['articles']['storagePid']); ! $statement = $this->connection->prepare($sql); $statement->execute(); ! return $statement->fetchAll(\PDO::FETCH_ASSOC); }
  36. H A N D L E D C O N

    T E N T T Y P E S • text: TYPO3.Neos.NodeTypes:Headline, TYPO3.Neos.NodeTypes:Text • html: TYPO3.Neos.NodeTypes:Html • textpic: TYPO3.Neos.NodeTypes:Headline, TYPO3.Neos.NodeTypes:TextWithImage, TYPO3.Neos.NodeTypes:Text • templavoila_pi1: TYPO3.Neos.NodeTypes:Html • image: TYPO3.Neos.NodeTypes:Headline, TYPO3.Neos.NodeTypes:Image • media: Journal.Commons:FlashVideo • div, list, uploads: skipped I N T H E C E N T U R I O N M A G A Z I N E M I G R A T I O N
  37. switch ($contentRecord['CType']) { case 'list': case 'div': case 'uploads': //

    no support needed, as these are not used in articles continue; case ‘text': ! …
  38. A P P LY I N G T R A

    N S F O R M AT I O N S • Skip unusable items • Clean up the data • Transform raw data to nodes
  39. C L E A N U P protected function cleanBodyText($content)

    { // remove leftover ###META### $content = str_replace('###META###', '', $content); ! // prune empty tags $content = preg_replace('@<(p|div|span|i|b|strong|em)[^>]*></\1>@ui', '', $content); ! // wrap lines in p tags $content = preg_replace('/^((?!<p>).+)$/uim', '<p>$1</p>', $content); ! // convert TYPO3 link tag $splitContent = preg_split('|(<link[^>]*>[^<]+</link>)|', $content, -1, PREG_SPLIT_DELIM_CAPTURE); $content = ''; foreach ($splitContent as $part) { if (substr($part, 0, 5) === '<link') { preg_match('|<link\s+(?P<linkend>[^\s>]+)(?:\s(?P<target>[^\s>]+))?(?:\s(?P<class>[^ \s>]+))?(?:\s"(?P<title>[^">]+)")?>(?P<linktext>[^<]*)</link>|xui', $part, $matches); if ($matches !== array()) { $content .= '<a href="' . $matches['linkend'] . '"';
  40. C O N T E N T T R A

    N S F O R M AT I O N • Create Headline nodes from header • Create Image and Text nodes from textpic • Order Text and Image nodes based on orientation • Create image carousel from image with multiple images
  41. H O W T O C R E AT E

    T H E N O D E S • Create XML for import into Neos • Add nodes to the content repository
  42. C R E AT E A N H T M

    L N O D E case 'html': if (!empty($contentRecord['bodytext'])) { $nodeTemplate = new NodeTemplate(); $nodeTemplate->setName(uniqid('html')); $nodeTemplate->setNodeType( $this->nodeTypeManager->getNodeType(‘TYPO3.Neos.NodeTypes:Html') ); $nodeTemplate->setHidden((boolean)$contentRecord['hidden']); $nodeTemplate->setProperty('source', $contentRecord['bodytext']); ! $mainContentCollectionNode->createNodeFromTemplate($nodeTemplate); } break;
  43. C R E AT E A H E A D

    E R N O D E protected function createHeaderIfNeeded(NodeInterface $targetNode, array $contentRecord) { // header_layout 100 means hidden, so skip it if (!empty($contentRecord['header']) && $contentRecord['header_layout'] !== 100) { $nodeTemplate = new NodeTemplate(); $nodeTemplate->setName(uniqid('header')); $nodeTemplate->setHidden((boolean)$contentRecord['hidden']); $nodeTemplate->setNodeType( $this->nodeTypeManager->getNodeType(‘TYPO3.Neos.NodeTypes:Headline') ); $wrap = explode('|', $this->settings['headline']['defaultWrap']); $nodeTemplate->setProperty('title', $wrap[0] . $contentRecord['header'] . $wrap[1]); ! $targetNode->createNodeFromTemplate($nodeTemplate); } }
  44. C R E AT E A N I M A

    G E N O D E • image elements can have multiple images • Image nodes hold exactly one image • How to deal with that? It is project specific
  45. F U T U R E A L O O

    K I N T O T H E F L I C K R . C O M – L I T T L E _ B L A C K _ C H E R RY
  46. N E X T S T E P S •

    Clean up the existing code • remove project specific parts • make modular and reusable • Write documentation • Publish as a package!
  47. Q U E S T I O N S N

    O W I S T H E T I M E F O R ?
  48. S O M E P O I N T E

    R S • These slides
 speakerdeck.com/kdambekalns • TYPO3 Neos
 neos.typo3.org • TYPO3 Neos documentation
 docs.typo3.org/neos/TYPO3NeosDocumentation • karsten.dambekalns.de | [email protected]
  49. T H A N K Y O U ! E

    N J O Y T H E C O N F E R E N C E !