SlideShare une entreprise Scribd logo
1  sur  170
Transmogrification:
Beyond the Magic Box
          Cris Ewing
     PLONE CONFERENCE, 2011
Plone Conference 2011




Migration
Plone Conference 2011




It’s Easy!
Plone Conference 2011




Photo by Christopher Michel - CC_BY
http://www.flickr.com/photos/cmichel67/4172613951/
Plone Conference 2011



 A Good Plan




Photo by Steve Jurvetson - CC-BY
http://www.flickr.com/photos/jurvetson/21470089/
Good Tools
                                                     Plone Conference 2011




Photo by	

Kimmo Palosaari - CC-BY
http://www.flickr.com/photos/kimmo-quva/4630630775/
Plone Conference 2011




                                                It doesn’t
                                                have to end
                                                like this


Photo by Mike Nelson - CC-BY
http://www.flickr.com/photos/mike_nelson/4720252548/
Plone Conference 2011




Our Story...
Plone Conference 2011




         heroes
         and
         villains



Photo by digital_ramapge via
http://www.flickr.com/photos/digital_ramapge/6118703544/
Plone Conference 2011




                                                  A Difficult
                                                    Journey


Photo by krayker - CC-BY
http://www.flickr.com/photos/krayker/2274246797/
Plone Conference 2011



Obstacles to Overcome




Photo by	

Joe Marinaro - CC-BY
http://www.flickr.com/photos/m500/5782771006/
Victory                                         Plone Conference 2011




Photo by	

Petr & Bara Ruzicka - CC-BY
http://www.flickr.com/photos/pruzicka/207209564/
Plone Conference 2011




The Plan
Plone Conference 2011




Liferay
Plone Conference 2011




Proprietary
Open Source
Plone Conference 2011




Image by	

Patrick Hoesly - CC_BY
http://www.flickr.com/photos/zooboing/5566075309/
Plone Conference 2011




    ‘lacking in
 documentation
explaining how it
 actually works’
Plone Conference 2011




                                                         data
                                                   spelunking



Photo by wjhunter - CC-BY
http://www.flickr.com/photos/wjhunter/3581151063/
Plone Conference 2011




DB Schema
              Clear




mysql> show tables;
+--------------------------------+
| Tables_in_lportal    |
+--------------------------------+
| Users_Permissions               |
| Users_Roles               |
| Users_UserGroups                 |
| Vocabulary                |
| WOL_MeetupsEntry                   |        Plone Conference 2011
| WOL_MeetupsRegistration               |
| WOL_SVNRepository                   |
| WOL_SVNRevision                  |
| WOL_WallEntry                 |


DB Schema
| WSRPConfiguredProducer                 |
| WSRPConsumerRegistration                |
| WSRPPortlet               |
| WSRPProducer                  |
| WebDAVProps                    |
| Website
| WikiNode
                 Clear   |
                           |
| WikiPage                |
| WikiPageResource                |
| guestUserInfo               |
+--------------------------------+
155 rows in set (0.01 sec)
Plone Conference 2011




              DB Schema
                            Simple


mysql> describe JournalArticle;
+--------------------+--------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| uuid_         | varchar(75) | YES | MUL | NULL |              |
| id_         | bigint(20) | NO | PRI | NULL |            |
| resourcePrimKey | bigint(20) | YES | MUL | NULL |                  |
| groupId         | bigint(20) | YES | MUL | NULL |             |
| companyId         | bigint(20) | YES | MUL | NULL |              |
| userId        | bigint(20) | YES |       | NULL |       |
| userName          | varchar(75) | YES |       | NULL |        |
| createDate       | datetime     | YES |     | NULL |        |
| modifiedDate        | datetime     | YES |     | NULL |         |
| articleId     | varchar(75) | YES |       | NULL |        |
| version        | double      | YES |     | NULL |       |
| title       | varchar(100) | YES |      | NULL |        |
| Field         | Type          | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| uuid_          | varchar(75) | YES | MUL | NULL |                   |
| id_          | bigint(20) | NO | PRI | NULL |                |
| resourcePrimKey | bigint(20) | YES | MUL | NULL |                           |     Plone Conference 2011
| groupId          | bigint(20) | YES | MUL | NULL |                   |
| companyId           | bigint(20) | YES | MUL | NULL |                    |
| userId         | bigint(20) | YES |         | NULL |         |
| userName            | varchar(75) | YES |         | NULL |           |


                DB Schema
| createDate         | datetime      | YES |      | NULL |          |
| modifiedDate          | datetime      | YES |      | NULL |           |
| articleId      | varchar(75) | YES |         | NULL |          |
| version         | double        | YES |     | NULL |         |
| title       | varchar(100) | YES |          | NULL |         |
| description
| content
                    | longtext
                  | longtext
                                Simple
                                    | YES |
                                   | YES |
                                                 | NULL |
                                               | NULL |         |
                                                                   |

| type_          | varchar(75) | YES |         | NULL |          |
| structureId       | varchar(75) | YES |         | NULL |          |
| templateId         | varchar(75) | YES |         | NULL |          |
| displayDate        | datetime      | YES |      | NULL |           |
| approved           | tinyint(4) | YES |       | NULL |          |
| approvedByUserId | bigint(20) | YES |               | NULL |             |
| approvedByUserName | varchar(75) | YES |                | NULL |              |
| approvedDate          | datetime      | YES |      | NULL |            |
| expired          | tinyint(4) | YES |       | NULL |         |
| expirationDate       | datetime      | YES |      | NULL |           |
| reviewDate         | datetime      | YES |      | NULL |           |
| indexable         | tinyint(4) | YES |       | NULL |          |
| smallImage          | tinyint(4) | YES |       | NULL |          |
| smallImageId         | bigint(20) | YES | MUL | NULL |                    |
| smallImageURL          | varchar(75) | YES |         | NULL |            |
| urlTitle       | varchar(150) | YES |         | NULL |          |
+--------------------+--------------+------+-----+---------+-------+
Plone Conference 2011




           DB Schema
                Easy to Understand


SELECT
   COALESCE(gui.guestName, mbm.userName) AS userName,
   mbm.createDate,
   mbm.modifiedDate,
   mbm.subject,
   mbm.body
FROM
   MBMessage mbm
JOIN
   MBDiscussion mbd ON mbd.threadId = mbm.threadId
LEFT JOIN
   guestUserInfo gui ON gui.messageId = mbm.messageId
WHERE
   mbd.classPK=%d ORDER BY modifiedDate
Plone Conference 2011




           DB Schema
                Easy to Understand


SELECT
   COALESCE(gui.guestName, mbm.userName) AS userName,
SELECT
   mbm.createDate,
   te.name
   mbm.modifiedDate,
FROM TagsEntry te
   mbm.subject,
WHERE te.entryId in
   mbm.body
   (SELECT tate.entryId
FROMFROM TagsAssets_TagsEntries tate
   MBMessage mbm in
    WHERE tate.assetId
JOIN (SELECT ta.assetId
   MBDiscussion mbd ON mbd.threadId = mbm.threadId
       FROM TagsAsset ta
LEFT JOIN
       WHERE ta.classPK=%d))
AND te.vocabularyid ON gui.messageId = mbm.messageId
   guestUserInfo gui = 41473
WHERE
   mbd.classPK=%d ORDER BY modifiedDate
Plone Conference 2011




DB Schema
 Easy to Understand


   </sarcasm>
Plone Conference 2011




Simple Goal
   (relatively)
Plone Conference 2011




All Articles
    ~2000
Plone Conference 2011




All Images
   ~5000
Plone Conference 2011




All Comments
    ~1000
Plone Conference 2011




Preserve Links
Plone Conference 2011




Preserve Dates
Plone Conference 2011




Preserve Authorship
Plone Conference 2011




Only a Few Tables
Plone Conference 2011
+--------------------+--------------+------+-----+---------+-------+
| Field         | Type          | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| uuid_          | varchar(75) | YES | MUL | NULL |                   |




                                                                                      1 for
| id_          | bigint(20) | NO | PRI | NULL |                |
| resourcePrimKey | bigint(20) | YES | MUL | NULL |                           |
| groupId          | bigint(20) | YES | MUL | NULL |                   |
| companyId           | bigint(20) | YES | MUL | NULL |                    |
| userId         | bigint(20) | YES |         | NULL |         |
| userName            | varchar(75) | YES |         | NULL |           |



                                                                                    Articles
| createDate         | datetime      | YES |      | NULL |          |
| modifiedDate          | datetime      | YES |      | NULL |           |
| articleId      | varchar(75) | YES |         | NULL |          |
| version         | double        | YES |     | NULL |         |
| title       | varchar(100) | YES |          | NULL |         |
| description       | longtext      | YES |      | NULL |          |
| content         | longtext       | YES |     | NULL |         |
| type_          | varchar(75) | YES |         | NULL |          |
| structureId       | varchar(75) | YES |         | NULL |          |
| templateId         | varchar(75) | YES |         | NULL |          |
| displayDate        | datetime      | YES |      | NULL |           |
| approved           | tinyint(4) | YES |       | NULL |          |
| approvedByUserId | bigint(20) | YES |               | NULL |             |
| approvedByUserName | varchar(75) | YES |                | NULL |              |
| approvedDate          | datetime      | YES |      | NULL |            |
| expired          | tinyint(4) | YES |       | NULL |         |
| expirationDate       | datetime      | YES |      | NULL |           |
| reviewDate         | datetime      | YES |      | NULL |           |
| indexable         | tinyint(4) | YES |       | NULL |          |
| smallImage          | tinyint(4) | YES |       | NULL |          |
| smallImageId         | bigint(20) | YES | MUL | NULL |                    |
| smallImageURL          | varchar(75) | YES |         | NULL |            |
| urlTitle       | varchar(150) | YES |         | NULL |          |
+--------------------+--------------+------+-----+---------+-------+
+--------------+------------+------+-----+---------+-------+
| Field        | Type       | Null | Key | Default | Extra |
+--------------+------------+------+-----+---------+-------+   Plone Conference 2011
| discussionId | bigint(20) | NO   | PRI | NULL    |       |
| classNameId | bigint(20) | YES | MUL | NULL      |       |
| classPK      | bigint(20) | YES |      | NULL    |       |
| threadId     | bigint(20) | YES | UNI | NULL     |       |
+--------------+------------+------+-----+---------+-------+




                                                           3 for
                                                       Comments
+--------------+------------+------+-----+---------+-------+
             | Field        | Type       | Null | Key | Default | Extra |
             +--------------+------------+------+-----+---------+-------+        Plone Conference 2011
             | discussionId | bigint(20) | NO    | PRI | NULL     |      |
             | classNameId | bigint(20) | YES | MUL | NULL        |      |
             | classPK      | bigint(20) | YES |        | NULL    |      |
             | threadId     | bigint(20) | YES | UNI | NULL       |      |
             +--------------+------------+------+-----+---------+-------+
+-----------------+-------------+------+-----+---------+-------+




                                                                        3 for
| Field            | Type        | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+-------+
| uuid_            | varchar(75) | YES | MUL | NULL       |       |
| messageId        | bigint(20) | NO    | PRI | NULL      |       |
| companyId        | bigint(20) | YES | MUL | NULL        |       |
| userId           | bigint(20) | YES |        | NULL     |       |




                                                                    Comments
| userName         | varchar(75) | YES |       | NULL     |       |
| createDate       | datetime    | YES |       | NULL     |       |
| modifiedDate     | datetime    | YES |       | NULL     |       |
| categoryId       | bigint(20) | YES | MUL | NULL        |       |
| threadId         | bigint(20) | YES | MUL | NULL        |       |
| parentMessageId | bigint(20) | YES |         | NULL     |       |
| subject          | varchar(75) | YES |       | NULL     |       |
| body             | longtext    | YES |       | NULL     |       |
| attachments      | tinyint(4) | YES |        | NULL     |       |
| anonymous        | tinyint(4) | YES |        | NULL     |       |
| groupId          | bigint(20) | YES | MUL | NULL        |       |
| classNameId      | bigint(20) | YES | MUL | NULL        |       |
| classPK          | bigint(20) | YES |        | NULL     |       |
| priority         | double      | YES |       | NULL     |       |
+-----------------+-------------+------+-----+---------+-------+
             +------------------+------------+------+-----+---------+-------+
             | Field            | Type        | Null | Key | Default | Extra |
             +------------------+------------+------+-----+---------+-------+
             | threadId         | bigint(20) | NO     | PRI | NULL   |       |
             | categoryId       | bigint(20) | YES | MUL | NULL      |       |
             | rootMessageId    | bigint(20) | YES |        | NULL   |       |
             | messageCount     | int(11)     | YES |       | NULL   |       |
             | viewCount        | int(11)     | YES |       | NULL   |       |
             | lastPostByUserId | bigint(20) | YES |        | NULL   |       |
             | lastPostDate     | datetime    | YES |       | NULL   |       |
             | priority         | double      | YES |       | NULL   |       |
             | groupId          | bigint(20) | YES | MUL | NULL      |       |
             +------------------+------------+------+-----+---------+-------+
+----------------+-------------+------+-----+---------+-------+
| Field          | Type        | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+     Plone Conference 2011
| uuid_          | varchar(75) | YES | MUL | NULL     |       |
| folderId       | bigint(20) | NO    | PRI | NULL    |       |
| groupId        | bigint(20) | YES | MUL | NULL      |       |
| companyId      | bigint(20) | YES | MUL | NULL      |       |




                                                                    3 for
| userId         | bigint(20) | YES |       | NULL    |       |
| createDate     | datetime    | YES |      | NULL    |       |
| modifiedDate   | datetime    | YES |      | NULL    |       |
| parentFolderId | bigint(20) | YES |       | NULL    |       |
| name           | varchar(75) | YES |      | NULL    |       |
| description    | longtext    | YES |      | NULL    |       |




                                                                  Images
+----------------+-------------+------+-----+---------+-------+
+----------------+-------------+------+-----+---------+-------+
     | Field           | Type         | Null | Key | Default | Extra |
     +----------------+-------------+------+-----+---------+-------+             Plone Conference 2011
     | uuid_           | varchar(75) | YES | MUL | NULL       |      |
     | folderId        | bigint(20) | NO     | PRI | NULL     |      |
     | groupId         | bigint(20) | YES | MUL | NULL        |      |
     | companyId       | bigint(20) | YES | MUL | NULL        |      |




                                                                                 3 for
     | userId          | bigint(20) | YES |        | NULL     |      |
     | createDate      | datetime     | YES |      | NULL     |      |
     | modifiedDate    | datetime     | YES |      | NULL     |      |
     | parentFolderId | bigint(20) | YES |         | NULL     |      |
     | name            | varchar(75) | YES |       | NULL     |      |
     | description     | longtext     | YES |      | NULL     |      |




                                                                               Images
     +----------------+-------------+------+-----+---------+-------+
+----------------+-------------+------+-----+---------+-------+
| Field           | Type         | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| uuid_           | varchar(75) | YES | MUL | NULL      |        |
| imageId         | bigint(20) | NO     | PRI | NULL    |        |
| companyId       | bigint(20) | YES |        | NULL    |        |
| userId          | bigint(20) | YES |        | NULL    |        |
| createDate      | datetime     | YES |      | NULL    |        |
| modifiedDate    | datetime     | YES |      | NULL    |        |
| folderId        | bigint(20) | YES | MUL | NULL       |        |
| name            | varchar(75) | YES |       | NULL    |        |
| description     | longtext     | YES |      | NULL    |        |
| smallImageId    | bigint(20) | YES | MUL | NULL       |        |
| largeImageId    | bigint(20) | YES | MUL | NULL       |        |
| custom1ImageId | bigint(20) | YES | MUL | NULL        |        |
| custom2ImageId | bigint(20) | YES | MUL | NULL        |        |
| groupId         | bigint(20) | YES | MUL | NULL       |        |
+----------------+-------------+------+-----+---------+-------+
              +--------------+-------------+------+-----+---------+-------+
              | Field         | Type        | Null | Key | Default | Extra |
              +--------------+-------------+------+-----+---------+-------+
              | imageId       | bigint(20) | NO    | PRI | NULL    |       |
              | modifiedDate | datetime     | YES |       | NULL   |       |
              | text_         | longtext    | YES |       | NULL   |       |
              | type_         | varchar(75) | YES |       | NULL   |       |
              | height        | int(11)     | YES |       | NULL   |       |
              | width         | int(11)     | YES |       | NULL   |       |
              | size_         | int(11)     | YES | MUL | NULL     |       |
              +--------------+-------------+------+-----+---------+-------+
Plone Conference 2011




What’s in an Article?
Plone Conference 2011
Plone Conference 2011



1. Image at top
2. Author name
3. Links in body
4. Images in body
5. Footnotes
6. Comments
Plone Conference 2011




And the Data?
+--------------------+--------------+------+-----+---------+-------+
| Field         | Type          | Null | Key | Default | Extra |                    Plone Conference 2011
+--------------------+--------------+------+-----+---------+-------+
| uuid_          | varchar(75) | YES | MUL | NULL |                   |
| id_          | bigint(20) | NO | PRI | NULL |                |
| resourcePrimKey | bigint(20) | YES | MUL | NULL |                           |
| groupId          | bigint(20) | YES | MUL | NULL |                   |
| companyId           | bigint(20) | YES | MUL | NULL |                    |
| userId         | bigint(20) | YES |         | NULL |         |
| userName            | varchar(75) | YES |         | NULL |           |
| createDate         | datetime      | YES |      | NULL |          |
| modifiedDate          | datetime      | YES |      | NULL |           |
| articleId      | varchar(75) | YES |         | NULL |          |
| version         | double        | YES |     | NULL |         |
| title       | varchar(100) | YES |          | NULL |         |
| description       | longtext      | YES |      | NULL |          |
| content         | longtext       | YES |     | NULL |         |
| type_          | varchar(75) | YES |         | NULL |          |
| structureId       | varchar(75) | YES |         | NULL |          |
| templateId         | varchar(75) | YES |         | NULL |          |
| displayDate        | datetime      | YES |      | NULL |           |
| approved           | tinyint(4) | YES |       | NULL |          |
| approvedByUserId | bigint(20) | YES |               | NULL |             |
| approvedByUserName | varchar(75) | YES |                | NULL |              |
| approvedDate          | datetime      | YES |      | NULL |            |
| expired          | tinyint(4) | YES |       | NULL |         |
| expirationDate       | datetime      | YES |      | NULL |           |
| reviewDate         | datetime      | YES |      | NULL |           |
| indexable         | tinyint(4) | YES |       | NULL |          |
| smallImage          | tinyint(4) | YES |       | NULL |          |
| smallImageId         | bigint(20) | YES | MUL | NULL |                    |
| smallImageURL          | varchar(75) | YES |         | NULL |            |
| urlTitle       | varchar(150) | YES |         | NULL |          |
+--------------------+--------------+------+-----+---------+-------+
+--------------------+--------------+------+-----+---------+-------+
                                                                                        Plone Conference 2011
                                                                               Author
| Field         | Type          | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| uuid_          | varchar(75) | YES | MUL | NULL |                   |
| id_          | bigint(20) | NO | PRI | NULL |                |
| resourcePrimKey | bigint(20) | YES | MUL | NULL |                           |
| groupId          | bigint(20) | YES | MUL | NULL |                   |
| companyId           | bigint(20) | YES | MUL | NULL |                    |
| userId         | bigint(20) | YES |         | NULL |         |
| userName            | varchar(75) | YES |         | NULL |           |
| createDate         | datetime      | YES |      | NULL |          |
| modifiedDate          | datetime      | YES |      | NULL |           |
| articleId      | varchar(75) | YES |         | NULL |          |
| version         | double        | YES |     | NULL |         |
| title       | varchar(100) | YES |          | NULL |         |
| description       | longtext      | YES |      | NULL |          |
| content         | longtext       | YES |     | NULL |         |
| type_          | varchar(75) | YES |         | NULL |          |
| structureId       | varchar(75) | YES |         | NULL |          |
| templateId         | varchar(75) | YES |         | NULL |          |
| displayDate        | datetime      | YES |      | NULL |           |
| approved           | tinyint(4) | YES |       | NULL |          |
| approvedByUserId | bigint(20) | YES |               | NULL |             |
| approvedByUserName | varchar(75) | YES |                | NULL |              |
| approvedDate          | datetime      | YES |      | NULL |            |
| expired          | tinyint(4) | YES |       | NULL |         |
| expirationDate       | datetime      | YES |      | NULL |           |
| reviewDate         | datetime      | YES |      | NULL |           |
| indexable         | tinyint(4) | YES |       | NULL |          |
| smallImage          | tinyint(4) | YES |       | NULL |          |
| smallImageId         | bigint(20) | YES | MUL | NULL |                    |
| smallImageURL          | varchar(75) | YES |         | NULL |            |
| urlTitle       | varchar(150) | YES |         | NULL |          |
+--------------------+--------------+------+-----+---------+-------+
+--------------------+--------------+------+-----+---------+-------+
                                                                                           Plone Conference 2011
                                                                               Author
| Field         | Type          | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| uuid_          | varchar(75) | YES | MUL | NULL |                   |
| id_          | bigint(20) | NO | PRI | NULL |                |
| resourcePrimKey | bigint(20) | YES | MUL | NULL |                           |
| groupId          | bigint(20) | YES | MUL | NULL |                   |
| companyId           | bigint(20) | YES | MUL | NULL |                    |
| userId         | bigint(20) | YES |         | NULL |         |
| userName            | varchar(75) | YES |         | NULL |           |
| createDate         | datetime      | YES |      | NULL |          |
| modifiedDate          | datetime      | YES |      | NULL |           |
| articleId
| version
| title
                 | varchar(75) | YES |
                  | double        | YES |
              | varchar(100) | YES |
                                               | NULL |
                                              | NULL |
                                              | NULL |
                                                               |
                                                               |
                                                                 |
                                                                               Body Text
| description
| content
| type_
                    | longtext
                  | longtext
                                    | YES |
                                   | YES |
                 | varchar(75) | YES |
                                                 | NULL |
                                               | NULL |
                                               | NULL |
                                                                |
                                                                 |
                                                                   |
                                                                                (links)
| structureId       | varchar(75) | YES |         | NULL |          |
| templateId         | varchar(75) | YES |         | NULL |          |
| displayDate        | datetime      | YES |      | NULL |           |
| approved           | tinyint(4) | YES |       | NULL |          |
| approvedByUserId | bigint(20) | YES |               | NULL |             |
| approvedByUserName | varchar(75) | YES |                | NULL |              |
| approvedDate          | datetime      | YES |      | NULL |            |
| expired          | tinyint(4) | YES |       | NULL |         |
| expirationDate       | datetime      | YES |      | NULL |           |
| reviewDate         | datetime      | YES |      | NULL |           |
| indexable         | tinyint(4) | YES |       | NULL |          |
| smallImage          | tinyint(4) | YES |       | NULL |          |
| smallImageId         | bigint(20) | YES | MUL | NULL |                    |
| smallImageURL          | varchar(75) | YES |         | NULL |            |
| urlTitle       | varchar(150) | YES |         | NULL |          |
+--------------------+--------------+------+-----+---------+-------+
+--------------------+--------------+------+-----+---------+-------+
                                                                                           Plone Conference 2011
                                                                               Author
| Field         | Type          | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| uuid_          | varchar(75) | YES | MUL | NULL |                   |
| id_          | bigint(20) | NO | PRI | NULL |                |
| resourcePrimKey | bigint(20) | YES | MUL | NULL |                           |
| groupId          | bigint(20) | YES | MUL | NULL |                   |
| companyId           | bigint(20) | YES | MUL | NULL |                    |
| userId         | bigint(20) | YES |         | NULL |         |
| userName            | varchar(75) | YES |         | NULL |           |
| createDate         | datetime      | YES |      | NULL |          |
| modifiedDate          | datetime      | YES |      | NULL |           |
| articleId
| version
| title
                 | varchar(75) | YES |
                  | double        | YES |
              | varchar(100) | YES |
                                               | NULL |
                                              | NULL |
                                              | NULL |
                                                               |
                                                               |
                                                                 |
                                                                               Body Text
| description
| content
| type_
                    | longtext
                  | longtext
                                    | YES |
                                   | YES |
                 | varchar(75) | YES |
                                                 | NULL |
                                               | NULL |
                                               | NULL |
                                                                |
                                                                 |
                                                                   |
                                                                                (links)
| structureId       | varchar(75) | YES |         | NULL |          |
| templateId         | varchar(75) | YES |         | NULL |          |
| displayDate        | datetime      | YES |      | NULL |           |
| approved           | tinyint(4) | YES |       | NULL |          |
| approvedByUserId | bigint(20) | YES |               | NULL |             |
| approvedByUserName | varchar(75) | YES |                | NULL |              |
| approvedDate          | datetime      | YES |      | NULL |            |
| expired          | tinyint(4) | YES |       | NULL |         |
| expirationDate       | datetime      | YES |      | NULL |           |
| reviewDate         | datetime      | YES |      | NULL |           |
| indexable         | tinyint(4) | YES |       | NULL |          |
| smallImage          | tinyint(4) | YES |       | NULL |          |
| smallImageId         | bigint(20) | YES | MUL | NULL |                    |


                                                                               Top Image
| smallImageURL          | varchar(75) | YES |         | NULL |            |
| urlTitle       | varchar(150) | YES |         | NULL |          |
+--------------------+--------------+------+-----+---------+-------+
+--------------------+--------------+------+-----+---------+-------+
                                                                                           Plone Conference 2011
                                                                               Author
| Field         | Type          | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| uuid_          | varchar(75) | YES | MUL | NULL |                   |
| id_          | bigint(20) | NO | PRI | NULL |                |
| resourcePrimKey | bigint(20) | YES | MUL | NULL |                           |
| groupId          | bigint(20) | YES | MUL | NULL |                   |
| companyId           | bigint(20) | YES | MUL | NULL |                    |
| userId         | bigint(20) | YES |         | NULL |         |
| userName            | varchar(75) | YES |         | NULL |           |
| createDate         | datetime      | YES |      | NULL |          |
| modifiedDate          | datetime      | YES |      | NULL |           |
| articleId
| version
| title
                 | varchar(75) | YES |
                  | double        | YES |
              | varchar(100) | YES |
                                               | NULL |
                                              | NULL |
                                              | NULL |
                                                               |
                                                               |
                                                                 |
                                                                               Body Text
| description
| content
| type_
                    | longtext
                  | longtext
                                    | YES |
                                   | YES |
                 | varchar(75) | YES |
                                                 | NULL |
                                               | NULL |
                                               | NULL |
                                                                |
                                                                 |
                                                                   |
                                                                                (links)
| structureId       | varchar(75) | YES |         | NULL |          |
| templateId         | varchar(75) | YES |         | NULL |          |
| displayDate        | datetime      | YES |      | NULL |           |
| approved           | tinyint(4) | YES |       | NULL |          |
| approvedByUserId | bigint(20) | YES |               | NULL |             |

                                                                           Dates
| approvedByUserName | varchar(75) | YES |                | NULL |              |
| approvedDate          | datetime      | YES |      | NULL |            |
| expired          | tinyint(4) | YES |       | NULL |         |
| expirationDate       | datetime      | YES |      | NULL |           |
| reviewDate         | datetime      | YES |      | NULL |           |
| indexable         | tinyint(4) | YES |       | NULL |          |
| smallImage          | tinyint(4) | YES |       | NULL |          |
| smallImageId         | bigint(20) | YES | MUL | NULL |                    |


                                                                               Top Image
| smallImageURL          | varchar(75) | YES |         | NULL |            |
| urlTitle       | varchar(150) | YES |         | NULL |          |
+--------------------+--------------+------+-----+---------+-------+
Plone Conference 2011




  Join   SELECT
           IGImage.imageId,

Image      IGImage.createDate,
           IGImage.modifiedDate,
           IGImage.uuid_,


Scales
           IGImage.userId,
           IGImage.name,
           IGImage.description,
           IGImage.smallImageId,
           IGImage.largeImageId,
           IGImage.custom1ImageId,
           IGImage.custom2ImageId,
           IGImage.folderId,
           Image.type_
         FROM IGImage JOIN Image
         ON IGImage.largeImageId = Image.imageId
Plone Conference 2011




 Get Article Comments
SELECT
   COALESCE(gui.guestName, mbm.userName) AS userName,
   mbm.createDate,
   mbm.modifiedDate,
   mbm.subject,
   mbm.body
FROM
   MBMessage mbm
JOIN
   MBDiscussion mbd ON mbd.threadId = mbm.threadId
LEFT JOIN
   guestUserInfo gui ON gui.messageId = mbm.messageId
WHERE
   mbd.classPK=%d ORDER BY modifiedDate
Plone Conference 2011




Alright, Good to Go!
Plone Conference 2011




The Toolbox
Plone Conference 2011




Transmogrifier
Plone Conference 2011




Transmogrifier
  “It’s a series of tubes”
Plone Conference 2011




Transmogrifier
Plone Conference 2011




Transmogrifier
Plone Conference 2011




Transmogrifier
Plone Conference 2011




Not Too Opinionated
Plone Conference 2011




Not Too Opinionated
Plone Conference 2011




  Not Too Opinionated
A migration deals with moving pieces of content from
one place to another
Plone Conference 2011




  Not Too Opinionated
A migration deals with moving pieces of content from
one place to another
A piece of content comes from somewhere
Plone Conference 2011




  Not Too Opinionated
A migration deals with moving pieces of content from
one place to another
A piece of content comes from somewhere
A piece of content ends up somewhere
Plone Conference 2011




  Not Too Opinionated
A migration deals with moving pieces of content from
one place to another
A piece of content comes from somewhere
A piece of content ends up somewhere
You should be able to do what you want to a piece of
content between point A and point B
Plone Conference 2011




A Nice Set of Tools
Plone Conference 2011




A Nice Set of Tools
Plone Conference 2011




The Migration
Plone Conference 2011




Two Main Types
Plone Conference 2011




Two Main Types
     Images
Plone Conference 2011




Two Main Types
     Images

     Articles
Plone Conference 2011




Two Pipelines
Plone Conference 2011




  Two Pipelines
One for each main content category
Plone Conference 2011




Two Pipelines
Plone Conference 2011




       Two Pipelines
• Extract content from SQL
Plone Conference 2011




       Two Pipelines
• Extract content from SQL
• Update text field encodings
Plone Conference 2011




       Two Pipelines
• Extract content from SQL
• Update text field encodings
• Transform Dates to Python
Plone Conference 2011




        Two Pipelines
• Extract content from SQL
• Update text field encodings
• Transform Dates to Python
• Calculate Final Plone Location
Plone Conference 2011




        Two Pipelines
• Extract content from SQL
• Update text field encodings
• Transform Dates to Python
• Calculate Final Plone Location
• Create Plone Object
Plone Conference 2011




        Two Pipelines
• Extract content from SQL
• Update text field encodings
• Transform Dates to Python
• Calculate Final Plone Location
• Create Plone Object
• Post-process (publication, etc.)
Plone Conference 2011




A Simplification
   but you get the idea
Plone Conference 2011




          Can You Spot the Flaw?




Photo by pollyann - CC-BY-NC-ND
http://www.flickr.com/photos/pollyann/4299826600/
Plone Conference 2011




How Do We Match Them?
     Plone ID != Original SQL ID
Plone Conference 2011




How Do We Match Them?
 JournalArticle.smallImageId != Image.smallImageID
Plone Conference 2011




How Do We Match Them?
JournalArticle.smallImageId != JournalArticle.smallImageURL

     |   449868   |   /image/image_gallery?img_id=449858&t=1296250152541            |
     |   449894   |   /image/image_gallery?img_id=449888&t=1296250703087            |
     |   450604   |   /image/image_gallery?img_id=450582&t=1296515550638            |
     |   450845   |   /image/image_gallery?img_id=450835&t=1296599014396            |
     |   450917   |   /image/image_gallery?img_id=450907&t=1296615851690            |
Plone Conference 2011




Photo by hobvias sudoneighm - CC-BY
http://www.flickr.com/photos/striatic/2192192956/
Plone Conference 2011




Transmogrifier
   To The Rescue!!!
Plone Conference 2011




Two Features
Plone Conference 2011




Splitter Section
run content down different pipelines
       in one transmogrifier
Plone Conference 2011




     Annotations
  store data on the transmogrifier to
communicate between pipeline sections
Plone Conference 2011




How Does This Help?
Plone Conference 2011




                 Three Facts
           1. Pipeline sections are generators

class MySection(object):
   classProvides(ISectionBlueprint)
   implements(ISection)

  def __init__(self, transmogrifier, name, options, previous):
    [setup]

  def __iter__(self):
    ...
    for item in self.previous:
        [do some stuff]
        ...
        yield item
    [clean up]
Plone Conference 2011




                 Three Facts
2. SQL sections process items 1 query at a time


  for query in self.queries:
     result=self.connection.execute(query)
     for row in result:
        yield dict((x[0].encode('utf-8'), x[1])
                for x in row.items())
Plone Conference 2011




                     Three Facts
           3. Pipelines process one item at a time



class SectionOne(object):        class SectionTwo(object):

  def __iter__(self):              def __iter__(self):
    ...                              ...
    for item in self.previous:       for item in self.previous:
        [do some stuff]                  [do some stuff]
        ...                              ...
        yield item                       yield item
Plone Conference 2011




Using
Annotations
Plone Conference 2011




Using
Annotations
Plone Conference 2011


Image
Information




              Using
              Annotations
Plone Conference 2011


Image
Information




              Using
              Annotations
Plone Conference 2011



class IGImageIDMapper(object):
   classProvides(ISectionBlueprint)
   implements(ISection)

  def __init__(self, transmogrifier, name, options, previous):
    self.transmogrifier = transmogrifier
    ...
    annotations = IAnnotations(self.transmogrifier)
    if IMAGE_MAPS_KEY in annotations:
        self.image_maps = annotations[IMAGE_MAPS_KEY]
    else:
        annotations[IMAGE_MAPS_KEY] = self.image_maps = {'img_uuid': {},
                                       'sm_img_id': {},
                                       'lg_img_id': {},
                                       'c1_img_id': {},
                                       'c2_img_id': {}}
Plone Conference 2011



class IGImageIDMapper(object):
   classProvides(ISectionBlueprint)
   implements(ISection)

  def __init__(self, transmogrifier, name, options, previous):
    self.transmogrifier = transmogrifier
    ...
    annotations = IAnnotations(self.transmogrifier)
    if IMAGE_MAPS_KEY in annotations:
        self.image_maps = annotations[IMAGE_MAPS_KEY]
    else:__iter__(self):
     def
        annotations[IMAGE_MAPS_KEY] = self.image_maps = {'img_uuid': {},
        for item in self.previous:
           if item['_type'] != 'Folder':     'sm_img_id': {},
               path = item.get('_path', None)'lg_img_id': {},
                                             'c1_img_id': {},
               current = self.transmogrifier.context.unrestrictedTraverse(path)
               if current:                   'c2_img_id': {}}
                   cuid = current.UID()
                   info = {'uid': cuid, 'path': path}
                   self.image_maps['img_uuid'][item['uuid_']] = info
                   self.image_maps['lg_img_id'][item['largeImageId']] = info
                   self.image_maps['sm_img_id'][item['smallImageId']] = info
                   self.image_maps['c1_img_id'][item['custom1ImageId']] = info
                   self.image_maps['c2_img_id'][item['custom2ImageId']] = info

           yield item
Plone Conference 2011


Image
Information




              Using
              Annotations
Plone Conference 2011


Image
Information




              Using
              Annotations
Plone Conference 2011


Image
Information




              Using
              Annotations
Plone Conference 2011




Using
Annotations
Plone Conference 2011




class GetArticleImage(object):
   classProvides(ISectionBlueprint)
   implements(ISection)

  def __iter__(self):
    annotations = IAnnotations(self.transmogrifier)
    self.image_maps = annotations[IMAGE_MAPS_KEY]
    for item in self.previous:
       if item['smallImage'] != 0:
           img_id = None
           try:
               url = item['smallImageURL']
               img_id = extract_img_id_from_url(url)
               if img_id is None:
                   img_id = extract_img_uuid_from_url(url)
           except KeyError:
               img_id = item['smallImageId']
           if img_id is not None:
               img_info = find_image_from_id(img_id, self.image_maps)
           ...
       yield item
Plone Conference 2011




                                                  Victory!




Photo by	

Petr & Bara Ruzicka - CC-BY
http://www.flickr.com/photos/pruzicka/207209564/
Plone Conference 2011




Image by justinshearer - CC-BY-NC-SA
http://www.flickr.com/photos/justinshearer/3675295127/
Plone Conference 2011




What About Links
  In Articles
Plone Conference 2011




What About Links
  In Articles
To Other Articles?
Plone Conference 2011




Images finish
before
Articles Start
Plone Conference 2011


Image
Information



              Images finish
              before
              Articles Start
Plone Conference 2011


Image
Information



              Images finish
              before
              Articles Start
Plone Conference 2011
Plone Conference 2011
Plone Conference 2011

Article 1 ID




               Article 1
               Identifiers
               Stored
Plone Conference 2011

Article 1 ID
Plone Conference 2011

Article 1 ID




               Article 2
               Links
               Processed
Plone Conference 2011

Article 1 ID




               Article 2
               Links
               Processed
               Link to
               Article 1 ✓
Plone Conference 2011

Article 1 ID




               Article 2
               Links
               Processed
               Link to
               Article 1 ✓
               Link to
               Article 3 ✗
Plone Conference 2011




                                                Sad
                                                Panda



Photo by Luis Markovic - CC-BY
http://www.flickr.com/photos/_lulu/3265194525/
Plone Conference 2011




Transmogrifier
   To The Rescue!!!
Plone Conference 2011




                 Three Facts
           1. Pipeline sections are generators

class MySection(object):
   classProvides(ISectionBlueprint)
   implements(ISection)

  def __init__(self, transmogrifier, name, options, previous):
    [setup]

  def __iter__(self):
    ...
    for item in self.previous:
        [do some stuff]
        ...
        yield item
    [clean up]
Plone Conference 2011




        One Fact, Really
           1. Pipeline sections are generators

class MySection(object):
   classProvides(ISectionBlueprint)
   implements(ISection)

  def __init__(self, transmogrifier, name, options, previous):
    [setup]

  def __iter__(self):
    ...
    for item in self.previous:
        [do some stuff]
        ...
        yield item
    [clean up]
Plone Conference 2011




        One Fact, Really
           1. Pipeline sections are generators

class MySection(object):
   classProvides(ISectionBlueprint)
   implements(ISection)

  def __init__(self, transmogrifier, name, options, previous):
    [setup]

  def __iter__(self):
    ...
    for item in self.previous:
        [do some stuff]
        ...
        yield item
    [clean up]
Plone Conference 2011




After all items are gone
Plone Conference 2011




After all items are gone
 Cleanup code is run
Plone Conference 2011



                      Set up ID Map
class PostCreation(object):
   classProvides(ISectionBlueprint)
   implements(ISection)

  def __init__(self, transmogrifier, name, options, previous):
    self.transmogrifier = transmogrifier
    ...
    if DOC_MAPS_KEY in annotations.keys():
        self.doc_maps = annotations[DOC_MAPS_KEY]
    else:
        annotations[DOC_MAPS_KEY] = self.doc_maps = {'resourcePrimKey': {},
                                      'urlTitle': {},
                                      'articleId': {},
                                      'uuid_': {},
                                      '_path': {}}
Plone Conference 2011



                      Set up ID Map
class PostCreation(object):
   classProvides(ISectionBlueprint)
   implements(ISection)

  def __init__(self, transmogrifier, name, options, previous):
    def __iter__(self):
    self.transmogrifier = transmogrifier
        site = self.transmogrifier.context
    ... for item in self.previous:
    if DOC_MAPS_KEY in annotations.keys():
           path = item.get('_path', None)
        self.doc_maps = annotations[DOC_MAPS_KEY]
           if path:
    else:     try:
        annotations[DOC_MAPS_KEY] = self.doc_maps = {'resourcePrimKey': {},
                  current = site.unrestrictedTraverse(path)
              except KeyError:             'urlTitle': {},
                                           'articleId': {},
                  # missing element in path somewhere, skip it?
                  pass                     'uuid_': {},
              if current:                  '_path': {}}
                  cuid = current.UID()
                  for key in ['resourcePrimKey', 'urlTitle', 'articleId',
                            'uuid_', '_path']:
                     if key in item:
                         self.doc_maps[key][item[key]] = cuid
           yield item
Plone Conference 2011



         Find Image Links
class ImageTagsFinder(object):
   classProvides(ISectionBlueprint)
   implements(ISection)

  def __init__(self, transmogrifier, name, options, previous):
    self.transmogrifier = transmogrifier
    ...
    annotations = IAnnotations(transmogrifier)
    if REWRITABLE_ELEMENTS_KEY not in annotations.keys():
        annotations[REWRITABLE_ELEMENTS_KEY] = {}
    self.rewriteable = annotations[REWRITABLE_ELEMENTS_KEY]
Plone Conference 2011



         Find Image Links
class ImageTagsFinder(object):
   classProvides(ISectionBlueprint)
             def __iter__(self):
   implements(ISection)
                  num_found = 0
                  for item in self.previous:
   def __init__(self, transmogrifier, name, options, previous):
      self.transmogrifier = item['_path']
                      path = transmogrifier
      ...             if tree is None:
                          parser = etree.HTMLParser()
      annotations = IAnnotations(transmogrifier)
                          tree = etree.fromstring(item['text'], parser)
      if REWRITABLE_ELEMENTS_KEY not in annotations.keys():
                      if tree is not None:
          annotations[REWRITABLE_ELEMENTS_KEY] = {}
                          all_images = tree.xpath('//img')
      self.rewriteable = annotations[REWRITABLE_ELEMENTS_KEY]
                          if len(all_images) > 0:
                              # we have some anchors, do any need re-writing?
                              internal = []
                              for img in all_images:
                                 src = img.attrib.get('src', '')
                                 match = img_is_internal(src)
                                 if match:
                                    internal.append(img)
                              mapped['images'] = internal
                              self.rewriteable[path] = internal
                      yield item
Find Other Tags
                                                                      Plone Conference 2011




class LinkFinder(object):
   """ create a mapping of the items which have links to be modified
   """
   classProvides(ISectionBlueprint)
   implements(ISection)

  def __init__(self, transmogrifier, name, options, previous):
    self.transmogrifier = transmogrifier
    annotations = IAnnotations(transmogrifier)
    if REWRITABLE_ELEMENTS_KEY not in annotations.keys():
       annotations[REWRITABLE_ELEMENTS_KEY] = {}
    self.rewriteable = annotations[REWRITABLE_ELEMENTS_KEY]
Find Other Tags
                                                                           Plone Conference 2011




class LinkFinder(object):
   """ create a mapping of the items which have links to be modified
   """
   classProvides(ISectionBlueprint)
   implements(ISection)
          def __iter__(self):
   def __init__(self,etrees of any documents with links that need fixing
             """ save transmogrifier, name, options, previous):
             """
       self.transmogrifier = transmogrifier
       annotations =in self.previous:
             for item IAnnotations(transmogrifier)
                 path = item['_path']
       if REWRITABLE_ELEMENTS_KEY not in annotations.keys():
          annotations[REWRITABLE_ELEMENTS_KEY]parser)
                 tree = etree.fromstring(item['text'], = {}
                 if tree is not None:
       self.rewriteable = annotations[REWRITABLE_ELEMENTS_KEY]
                     all_anchors = tree.xpath('//a')
                     if len(all_anchors) > 0:
                         # we have some anchors, do any need re-writing?
                         internal = []
                         for a in all_anchors:
                            href = a.attrib.get('href', '')
                            if is_internal_link(href):
                                internal.append(href)
                         self.rewriteable[path] = internal
                 yield item
Plone Conference 2011



             Replace Found Links
class LinkReplacer(object):
   """ re-write links in body texts of all created items

  The work done by this item takes place entirely in the clean-up stage of
  the section.
  """
  classProvides(ISectionBlueprint)
  implements(ISection)

  def __init__(self, transmogrifier, name, options, previous):
    self.transmogrifier = transmogrifier
    annotations = IAnnotations(transmogrifier)
    if REWRITABLE_ELEMENTS_KEY not in annotations.keys():
       annotations[REWRITABLE_ELEMENTS_KEY] = {}
    self.rewriteable = annotations[REWRITABLE_ELEMENTS_KEY]
Plone Conference 2011



             Replace Found Links
class LinkReplacer(object):
   """ re-write links in body texts of all created items

      def __iter__(self):
  The work done by this item takes place entirely in the clean-up stage of
  the section. in self.previous:
         for item
  """       # no action takes place here
            yield item
  classProvides(ISectionBlueprint)
  implements(ISection)
         # get the maps we will use
         annotations = IAnnotations(self.transmogrifier)
  def __init__(self, transmogrifier, name, options, previous):
         doc_maps = annotations[DOC_MAPS_KEY]
      self.transmogrifier = transmogrifier
         image_maps = annotations[IMAGE_MAPS_KEY]
      annotations = IAnnotations(transmogrifier)
      if REWRITABLE_ELEMENTS_KEY tagsin annotations.keys():
         # rewrite image and anchor not
         for path, info in self.rewriteable.items():
         annotations[REWRITABLE_ELEMENTS_KEY] = {}
            page = self.transmogrifier.context.unrestrictedTraverse(path)
      self.rewriteable = annotations[REWRITABLE_ELEMENTS_KEY]
            tree = info.get('tree', None)
            links = info.get('links', [])
            images = info.get('images', [])
            lg, ln, le = rewrite_links(links, page, doc_maps,
                                self.logger, self.transmogrifier.context)
            ig, _in, ie = rewrite_image_tags(images, page, image_maps,
                                     self.logger)
Plone Conference 2011




                                                  Victory!




Photo by	

Petr & Bara Ruzicka - CC-BY
http://www.flickr.com/photos/pruzicka/207209564/
Plone Conference 2011




                                                  Victory!
                                                   Right?


Photo by	

Petr & Bara Ruzicka - CC-BY
http://www.flickr.com/photos/pruzicka/207209564/
Plone Conference 2011



please?
Plone Conference 2011



please?
Plone Conference 2011




Photo of moo
http://instagr.am/p/SSMBw/
Plone Conference 2011




Link Formats
Plone Conference 2011




Link Formats
how many can you imagine?
Plone Conference 2011




Link Formats
how many can you imagine?

     we had them all
Plone Conference 2011




~2,000 Articles
Plone Conference 2011




5-10 Links per Article
Plone Conference 2011




5-10 Links per Article
         at least
Plone Conference 2011




5-10 Links per Article
           at least



       you do the math
Plone Conference 2011




                                              How to
                                              Find the
                                              Bad Ones?



Photo by	

Alessandra Oddi - CC-BY
http://www.flickr.com/photos/uvafragola/4834037874/
Plone Conference 2011




Transmogrifier
   To The Rescue!!!
Plone Conference 2011




Python
To The Rescue!!!
Plone Conference 2011




CSV Reports
Plone Conference 2011




CSV Reports
 Which links worked?
Plone Conference 2011




CSV Reports
 Which links worked?
  Which links didn’t?
class LinkReplacer(object):
   """ re-write links in body texts of all created items
   """
   classProvides(ISectionBlueprint)
   implements(ISection)
   ...
   def __iter__(self):
       good, notenough, errors = [],[],[]
       for item in self.previous:
           yield item
       for path, info in self.rewriteable.items():
           page = self.transmogrifier.context.unrestrictedTraverse(path)
           tree = info.get('tree', None)
           links = info.get('links', [])
           images = info.get('images', [])
           lg, ln, le = rewrite_links(links, page, doc_maps,
                               self.logger, self.transmogrifier.context)
           ig, _in, ie = rewrite_image_tags(images, page, image_maps,
                                    self.logger)
           good.extend(lg + ig)
           notenough.extend(ln + _in)
           errors.extend(le + ie)
       with open('goodlinks.csv', 'w') as f:
           goodwriter = csv.writer(f)
           goodwriter.writerows(good)
       with open('badlinks.csv', 'w') as f:
           badwriter = csv.writer(f)
           badwriter.writerows(notenough)
       ...
class LinkReplacer(object):
   """ re-write links in body texts of all created items
   """             def rewrite_image_tags(images, page, img_maps, logger):
                      good = []
   classProvides(ISectionBlueprint)
                      notenough = []
   implements(ISection)
   ...                errors = []
   def __iter__(self): image in images:
                      for
                         url = image.attrib.get('src', '')
       good, notenough, errors = [],[],[]
                         # get information about the image to be subbed, either by id or uuid
       for item in self.previous:
           yield item img_id = extract_img_id_from_url(url)
       for path, info in img_id is None:
                         if self.rewriteable.items():
                             img_id = extract_img_uuid_from_url(url)
           page = self.transmogrifier.context.unrestrictedTraverse(path)
           tree = info.get('tree', is None:
                         if img_id None)
           links = info.get('links', []) not find a mapped image matching, not enough to go on
                             # we could
                             logger.warn('unable to find image id in url: %s' % url)
           images = info.get('images', [])
           lg, ln, le = rewrite_links(links, page, doc_maps, bad url', page.absolute_url(), url))
                             notenough.append(('missing img,
                             continue
                                self.logger, self.transmogrifier.context)
           ig, _in, ie =# resolve the id we found into a plone object UID via image maps
                          rewrite_image_tags(images, page, image_maps,
                         img_info = find_image_from_id(img_id, img_maps)
                                     self.logger)
                         if img_info is None:
           good.extend(lg + ig)
                             logger.warn('unable to find mapped plone image id %s' % img_id)
           notenough.extend(ln + _in)
                             notenough.append(('missing img, no map', page.absolute_url(), url))
           errors.extend(le + ie)
                             continue
       with open('goodlinks.csv', 'w') as f:
           goodwriter # by default, use the 300x300 px medium size for in-page images
                         = csv.writer(f)
                         # To change this, adjust the value of STANDARD_IMG_SCALE
           goodwriter.writerows(good)
                         newurl = "resolveuid/%s%s" % (img_info['uid'],
       with open('badlinks.csv', 'w') as f:
           badwriter = csv.writer(f)                 STANDARD_IMG_SCALE)
           badwriter.writerows(notenough)newurl
                         image.attrib['src'] =
       ...               good.append(('image match', page.absolute_url(), url))
                      return good, notenough, errors
Plone Conference 2011




Iteration FTW!
Plone Conference 2011




Iteration FTW!
  from > 2000 bad links
Plone Conference 2011




Iteration FTW!
  from > 2000 bad links

    to < 75 bad links
Plone Conference 2011




Iteration FTW!
    from > 2000 bad links

      to < 75 bad links

 fix those that remain by hand
Plone Conference 2011




                                                  Victory!




Photo by	

Petr & Bara Ruzicka - CC-BY
http://www.flickr.com/photos/pruzicka/207209564/
Plone Conference 2011




So What Did We Learn?
Plone Conference 2011




 Clients, when asked to describe their existing system,
will never describe it with enough accuracy to properly
                  plan for a migration
Plone Conference 2011




Learn as much as you can about the source system
           when planning a migration
Plone Conference 2011




Learn as much as you can about the source system
           when planning a migration

but know that you will always need to know more
Plone Conference 2011




 Learn as much as you can about the source system
            when planning a migration

  but know that you will always need to know more

and that you will not find it out until you actually start
                     the migration
Plone Conference 2011




Users, if given more than one way to do things, will use
                      all the ways
Plone Conference 2011




Have a plan, but be prepared to adjust when reality hits.
  Plans are best when treated as jumping-off points.
Plone Conference 2011




Estimate Migrations HIGH
Plone Conference 2011




Photo by neilspicys - CC-BY
http://www.flickr.com/photos/neilspicys/2349770710/
Check p.com/de
      out       mos
sixfeetu

Contenu connexe

Similaire à Transmogrifier: Beyond the Magic Box

Getting startedwith noir-clojureexchange-2011
Getting startedwith noir-clojureexchange-2011Getting startedwith noir-clojureexchange-2011
Getting startedwith noir-clojureexchange-2011John Stevenson
 
Spring MVC - The Basics
Spring MVC -  The BasicsSpring MVC -  The Basics
Spring MVC - The BasicsIlio Catallo
 
Automating Networks by Converting into API/Webs
Automating Networks by Converting into API/WebsAutomating Networks by Converting into API/Webs
Automating Networks by Converting into API/WebsAPNIC
 
Automating Networks by using API
Automating Networks by using APIAutomating Networks by using API
Automating Networks by using API一清 井上
 
Fluentd 20150918 no_demo_public
Fluentd 20150918 no_demo_publicFluentd 20150918 no_demo_public
Fluentd 20150918 no_demo_publicSaewoong Lee
 
MongoDB user group israel May
MongoDB user group israel MayMongoDB user group israel May
MongoDB user group israel MayAlon Horev
 
Scaling Confluence: From Performance to People
Scaling Confluence: From Performance to PeopleScaling Confluence: From Performance to People
Scaling Confluence: From Performance to PeopleAtlassian
 
MCE^3 - Kyle Fuller - End-to-end Building Web Services in-swift-mce-2016
MCE^3 - Kyle Fuller - End-to-end Building Web Services in-swift-mce-2016MCE^3 - Kyle Fuller - End-to-end Building Web Services in-swift-mce-2016
MCE^3 - Kyle Fuller - End-to-end Building Web Services in-swift-mce-2016PROIDEA
 
Html5 Whats around the bend
Html5 Whats around the bendHtml5 Whats around the bend
Html5 Whats around the bendRaj Lal
 
Advanced Data Modeling with Apache Cassandra
Advanced Data Modeling with Apache CassandraAdvanced Data Modeling with Apache Cassandra
Advanced Data Modeling with Apache CassandraDataStax Academy
 
Let's get accessible!
Let's get accessible!Let's get accessible!
Let's get accessible!Tady Walsh
 
2_MySQL_Cluster_Introduction.pdf
2_MySQL_Cluster_Introduction.pdf2_MySQL_Cluster_Introduction.pdf
2_MySQL_Cluster_Introduction.pdfHaiping Li
 
gDayX 2013 - Advanced AngularJS - Nicolas Embleton
gDayX 2013 - Advanced AngularJS - Nicolas EmbletongDayX 2013 - Advanced AngularJS - Nicolas Embleton
gDayX 2013 - Advanced AngularJS - Nicolas EmbletonGeorge Nguyen
 
The MySQL SYS Schema
The MySQL SYS SchemaThe MySQL SYS Schema
The MySQL SYS SchemaMark Leith
 
Mobyle administrator workshop
Mobyle administrator workshopMobyle administrator workshop
Mobyle administrator workshopbneron
 
Observability of InfluxDB IOx: Tracing, Metrics and System Tables
Observability of InfluxDB IOx: Tracing, Metrics and System TablesObservability of InfluxDB IOx: Tracing, Metrics and System Tables
Observability of InfluxDB IOx: Tracing, Metrics and System TablesInfluxData
 
Distributed Identities with OpenID
Distributed Identities with OpenIDDistributed Identities with OpenID
Distributed Identities with OpenIDBastian Hofmann
 

Similaire à Transmogrifier: Beyond the Magic Box (20)

CraftCMS 3.x Deep Dive
CraftCMS 3.x Deep DiveCraftCMS 3.x Deep Dive
CraftCMS 3.x Deep Dive
 
Getting startedwith noir-clojureexchange-2011
Getting startedwith noir-clojureexchange-2011Getting startedwith noir-clojureexchange-2011
Getting startedwith noir-clojureexchange-2011
 
Spring MVC - The Basics
Spring MVC -  The BasicsSpring MVC -  The Basics
Spring MVC - The Basics
 
Automating Networks by Converting into API/Webs
Automating Networks by Converting into API/WebsAutomating Networks by Converting into API/Webs
Automating Networks by Converting into API/Webs
 
20120116 - NvMgr
20120116 - NvMgr20120116 - NvMgr
20120116 - NvMgr
 
Automating Networks by using API
Automating Networks by using APIAutomating Networks by using API
Automating Networks by using API
 
Polyglot JVM
Polyglot JVMPolyglot JVM
Polyglot JVM
 
Fluentd 20150918 no_demo_public
Fluentd 20150918 no_demo_publicFluentd 20150918 no_demo_public
Fluentd 20150918 no_demo_public
 
MongoDB user group israel May
MongoDB user group israel MayMongoDB user group israel May
MongoDB user group israel May
 
Scaling Confluence: From Performance to People
Scaling Confluence: From Performance to PeopleScaling Confluence: From Performance to People
Scaling Confluence: From Performance to People
 
MCE^3 - Kyle Fuller - End-to-end Building Web Services in-swift-mce-2016
MCE^3 - Kyle Fuller - End-to-end Building Web Services in-swift-mce-2016MCE^3 - Kyle Fuller - End-to-end Building Web Services in-swift-mce-2016
MCE^3 - Kyle Fuller - End-to-end Building Web Services in-swift-mce-2016
 
Html5 Whats around the bend
Html5 Whats around the bendHtml5 Whats around the bend
Html5 Whats around the bend
 
Advanced Data Modeling with Apache Cassandra
Advanced Data Modeling with Apache CassandraAdvanced Data Modeling with Apache Cassandra
Advanced Data Modeling with Apache Cassandra
 
Let's get accessible!
Let's get accessible!Let's get accessible!
Let's get accessible!
 
2_MySQL_Cluster_Introduction.pdf
2_MySQL_Cluster_Introduction.pdf2_MySQL_Cluster_Introduction.pdf
2_MySQL_Cluster_Introduction.pdf
 
gDayX 2013 - Advanced AngularJS - Nicolas Embleton
gDayX 2013 - Advanced AngularJS - Nicolas EmbletongDayX 2013 - Advanced AngularJS - Nicolas Embleton
gDayX 2013 - Advanced AngularJS - Nicolas Embleton
 
The MySQL SYS Schema
The MySQL SYS SchemaThe MySQL SYS Schema
The MySQL SYS Schema
 
Mobyle administrator workshop
Mobyle administrator workshopMobyle administrator workshop
Mobyle administrator workshop
 
Observability of InfluxDB IOx: Tracing, Metrics and System Tables
Observability of InfluxDB IOx: Tracing, Metrics and System TablesObservability of InfluxDB IOx: Tracing, Metrics and System Tables
Observability of InfluxDB IOx: Tracing, Metrics and System Tables
 
Distributed Identities with OpenID
Distributed Identities with OpenIDDistributed Identities with OpenID
Distributed Identities with OpenID
 

Plus de Cristopher Ewing

Getting Things Done with Content Rules
Getting Things Done with Content RulesGetting Things Done with Content Rules
Getting Things Done with Content RulesCristopher Ewing
 
Speaking at PyCon: The how and why
Speaking at PyCon: The how and whySpeaking at PyCon: The how and why
Speaking at PyCon: The how and whyCristopher Ewing
 
Adaptation in Open Source Software, PyCon 2016 Keynote
Adaptation in Open Source Software, PyCon 2016 KeynoteAdaptation in Open Source Software, PyCon 2016 Keynote
Adaptation in Open Source Software, PyCon 2016 KeynoteCristopher Ewing
 
Ancient To Modern: Upgrading nearly a decade of Plone in public radio
Ancient To Modern: Upgrading nearly a decade of Plone in public radioAncient To Modern: Upgrading nearly a decade of Plone in public radio
Ancient To Modern: Upgrading nearly a decade of Plone in public radioCristopher Ewing
 
Plone for Education: Bibliographies
Plone for Education: BibliographiesPlone for Education: Bibliographies
Plone for Education: BibliographiesCristopher Ewing
 
Jumpstart Your Development with ZopeSkel
Jumpstart Your Development with ZopeSkelJumpstart Your Development with ZopeSkel
Jumpstart Your Development with ZopeSkelCristopher Ewing
 
ZopeSkel: The past, present and future
ZopeSkel: The past, present and futureZopeSkel: The past, present and future
ZopeSkel: The past, present and futureCristopher Ewing
 
Yes It Can: Leverage Workflow in Plone to Bring Business Process Online
Yes It Can: Leverage Workflow in Plone to Bring Business Process OnlineYes It Can: Leverage Workflow in Plone to Bring Business Process Online
Yes It Can: Leverage Workflow in Plone to Bring Business Process OnlineCristopher Ewing
 

Plus de Cristopher Ewing (9)

Getting Things Done with Content Rules
Getting Things Done with Content RulesGetting Things Done with Content Rules
Getting Things Done with Content Rules
 
Speaking at PyCon: The how and why
Speaking at PyCon: The how and whySpeaking at PyCon: The how and why
Speaking at PyCon: The how and why
 
Adaptation in Open Source Software, PyCon 2016 Keynote
Adaptation in Open Source Software, PyCon 2016 KeynoteAdaptation in Open Source Software, PyCon 2016 Keynote
Adaptation in Open Source Software, PyCon 2016 Keynote
 
Ancient To Modern: Upgrading nearly a decade of Plone in public radio
Ancient To Modern: Upgrading nearly a decade of Plone in public radioAncient To Modern: Upgrading nearly a decade of Plone in public radio
Ancient To Modern: Upgrading nearly a decade of Plone in public radio
 
Plone for Education: Bibliographies
Plone for Education: BibliographiesPlone for Education: Bibliographies
Plone for Education: Bibliographies
 
Jumpstart Your Development with ZopeSkel
Jumpstart Your Development with ZopeSkelJumpstart Your Development with ZopeSkel
Jumpstart Your Development with ZopeSkel
 
ZopeSkel: The past, present and future
ZopeSkel: The past, present and futureZopeSkel: The past, present and future
ZopeSkel: The past, present and future
 
Yes It Can: Leverage Workflow in Plone to Bring Business Process Online
Yes It Can: Leverage Workflow in Plone to Bring Business Process OnlineYes It Can: Leverage Workflow in Plone to Bring Business Process Online
Yes It Can: Leverage Workflow in Plone to Bring Business Process Online
 
We All Stand Together
We All Stand TogetherWe All Stand Together
We All Stand Together
 

Dernier

Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 

Dernier (20)

Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 

Transmogrifier: Beyond the Magic Box

  • 1. Transmogrification: Beyond the Magic Box Cris Ewing PLONE CONFERENCE, 2011
  • 4. Plone Conference 2011 Photo by Christopher Michel - CC_BY http://www.flickr.com/photos/cmichel67/4172613951/
  • 5. Plone Conference 2011 A Good Plan Photo by Steve Jurvetson - CC-BY http://www.flickr.com/photos/jurvetson/21470089/
  • 6. Good Tools Plone Conference 2011 Photo by Kimmo Palosaari - CC-BY http://www.flickr.com/photos/kimmo-quva/4630630775/
  • 7. Plone Conference 2011 It doesn’t have to end like this Photo by Mike Nelson - CC-BY http://www.flickr.com/photos/mike_nelson/4720252548/
  • 9. Plone Conference 2011 heroes and villains Photo by digital_ramapge via http://www.flickr.com/photos/digital_ramapge/6118703544/
  • 10. Plone Conference 2011 A Difficult Journey Photo by krayker - CC-BY http://www.flickr.com/photos/krayker/2274246797/
  • 11. Plone Conference 2011 Obstacles to Overcome Photo by Joe Marinaro - CC-BY http://www.flickr.com/photos/m500/5782771006/
  • 12. Victory Plone Conference 2011 Photo by Petr & Bara Ruzicka - CC-BY http://www.flickr.com/photos/pruzicka/207209564/
  • 14.
  • 15.
  • 16.
  • 19. Plone Conference 2011 Image by Patrick Hoesly - CC_BY http://www.flickr.com/photos/zooboing/5566075309/
  • 20. Plone Conference 2011 ‘lacking in documentation explaining how it actually works’
  • 21. Plone Conference 2011 data spelunking Photo by wjhunter - CC-BY http://www.flickr.com/photos/wjhunter/3581151063/
  • 22. Plone Conference 2011 DB Schema Clear mysql> show tables; +--------------------------------+ | Tables_in_lportal | +--------------------------------+
  • 23. | Users_Permissions | | Users_Roles | | Users_UserGroups | | Vocabulary | | WOL_MeetupsEntry | Plone Conference 2011 | WOL_MeetupsRegistration | | WOL_SVNRepository | | WOL_SVNRevision | | WOL_WallEntry | DB Schema | WSRPConfiguredProducer | | WSRPConsumerRegistration | | WSRPPortlet | | WSRPProducer | | WebDAVProps | | Website | WikiNode Clear | | | WikiPage | | WikiPageResource | | guestUserInfo | +--------------------------------+ 155 rows in set (0.01 sec)
  • 24. Plone Conference 2011 DB Schema Simple mysql> describe JournalArticle; +--------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------------+--------------+------+-----+---------+-------+ | uuid_ | varchar(75) | YES | MUL | NULL | | | id_ | bigint(20) | NO | PRI | NULL | | | resourcePrimKey | bigint(20) | YES | MUL | NULL | | | groupId | bigint(20) | YES | MUL | NULL | | | companyId | bigint(20) | YES | MUL | NULL | | | userId | bigint(20) | YES | | NULL | | | userName | varchar(75) | YES | | NULL | | | createDate | datetime | YES | | NULL | | | modifiedDate | datetime | YES | | NULL | | | articleId | varchar(75) | YES | | NULL | | | version | double | YES | | NULL | | | title | varchar(100) | YES | | NULL | |
  • 25. | Field | Type | Null | Key | Default | Extra | +--------------------+--------------+------+-----+---------+-------+ | uuid_ | varchar(75) | YES | MUL | NULL | | | id_ | bigint(20) | NO | PRI | NULL | | | resourcePrimKey | bigint(20) | YES | MUL | NULL | | Plone Conference 2011 | groupId | bigint(20) | YES | MUL | NULL | | | companyId | bigint(20) | YES | MUL | NULL | | | userId | bigint(20) | YES | | NULL | | | userName | varchar(75) | YES | | NULL | | DB Schema | createDate | datetime | YES | | NULL | | | modifiedDate | datetime | YES | | NULL | | | articleId | varchar(75) | YES | | NULL | | | version | double | YES | | NULL | | | title | varchar(100) | YES | | NULL | | | description | content | longtext | longtext Simple | YES | | YES | | NULL | | NULL | | | | type_ | varchar(75) | YES | | NULL | | | structureId | varchar(75) | YES | | NULL | | | templateId | varchar(75) | YES | | NULL | | | displayDate | datetime | YES | | NULL | | | approved | tinyint(4) | YES | | NULL | | | approvedByUserId | bigint(20) | YES | | NULL | | | approvedByUserName | varchar(75) | YES | | NULL | | | approvedDate | datetime | YES | | NULL | | | expired | tinyint(4) | YES | | NULL | | | expirationDate | datetime | YES | | NULL | | | reviewDate | datetime | YES | | NULL | | | indexable | tinyint(4) | YES | | NULL | | | smallImage | tinyint(4) | YES | | NULL | | | smallImageId | bigint(20) | YES | MUL | NULL | | | smallImageURL | varchar(75) | YES | | NULL | | | urlTitle | varchar(150) | YES | | NULL | | +--------------------+--------------+------+-----+---------+-------+
  • 26. Plone Conference 2011 DB Schema Easy to Understand SELECT COALESCE(gui.guestName, mbm.userName) AS userName, mbm.createDate, mbm.modifiedDate, mbm.subject, mbm.body FROM MBMessage mbm JOIN MBDiscussion mbd ON mbd.threadId = mbm.threadId LEFT JOIN guestUserInfo gui ON gui.messageId = mbm.messageId WHERE mbd.classPK=%d ORDER BY modifiedDate
  • 27. Plone Conference 2011 DB Schema Easy to Understand SELECT COALESCE(gui.guestName, mbm.userName) AS userName, SELECT mbm.createDate, te.name mbm.modifiedDate, FROM TagsEntry te mbm.subject, WHERE te.entryId in mbm.body (SELECT tate.entryId FROMFROM TagsAssets_TagsEntries tate MBMessage mbm in WHERE tate.assetId JOIN (SELECT ta.assetId MBDiscussion mbd ON mbd.threadId = mbm.threadId FROM TagsAsset ta LEFT JOIN WHERE ta.classPK=%d)) AND te.vocabularyid ON gui.messageId = mbm.messageId guestUserInfo gui = 41473 WHERE mbd.classPK=%d ORDER BY modifiedDate
  • 28. Plone Conference 2011 DB Schema Easy to Understand </sarcasm>
  • 29. Plone Conference 2011 Simple Goal (relatively)
  • 30. Plone Conference 2011 All Articles ~2000
  • 32. Plone Conference 2011 All Comments ~1000
  • 37. Plone Conference 2011 +--------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------------+--------------+------+-----+---------+-------+ | uuid_ | varchar(75) | YES | MUL | NULL | | 1 for | id_ | bigint(20) | NO | PRI | NULL | | | resourcePrimKey | bigint(20) | YES | MUL | NULL | | | groupId | bigint(20) | YES | MUL | NULL | | | companyId | bigint(20) | YES | MUL | NULL | | | userId | bigint(20) | YES | | NULL | | | userName | varchar(75) | YES | | NULL | | Articles | createDate | datetime | YES | | NULL | | | modifiedDate | datetime | YES | | NULL | | | articleId | varchar(75) | YES | | NULL | | | version | double | YES | | NULL | | | title | varchar(100) | YES | | NULL | | | description | longtext | YES | | NULL | | | content | longtext | YES | | NULL | | | type_ | varchar(75) | YES | | NULL | | | structureId | varchar(75) | YES | | NULL | | | templateId | varchar(75) | YES | | NULL | | | displayDate | datetime | YES | | NULL | | | approved | tinyint(4) | YES | | NULL | | | approvedByUserId | bigint(20) | YES | | NULL | | | approvedByUserName | varchar(75) | YES | | NULL | | | approvedDate | datetime | YES | | NULL | | | expired | tinyint(4) | YES | | NULL | | | expirationDate | datetime | YES | | NULL | | | reviewDate | datetime | YES | | NULL | | | indexable | tinyint(4) | YES | | NULL | | | smallImage | tinyint(4) | YES | | NULL | | | smallImageId | bigint(20) | YES | MUL | NULL | | | smallImageURL | varchar(75) | YES | | NULL | | | urlTitle | varchar(150) | YES | | NULL | | +--------------------+--------------+------+-----+---------+-------+
  • 38. +--------------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------+------------+------+-----+---------+-------+ Plone Conference 2011 | discussionId | bigint(20) | NO | PRI | NULL | | | classNameId | bigint(20) | YES | MUL | NULL | | | classPK | bigint(20) | YES | | NULL | | | threadId | bigint(20) | YES | UNI | NULL | | +--------------+------------+------+-----+---------+-------+ 3 for Comments
  • 39. +--------------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------+------------+------+-----+---------+-------+ Plone Conference 2011 | discussionId | bigint(20) | NO | PRI | NULL | | | classNameId | bigint(20) | YES | MUL | NULL | | | classPK | bigint(20) | YES | | NULL | | | threadId | bigint(20) | YES | UNI | NULL | | +--------------+------------+------+-----+---------+-------+ +-----------------+-------------+------+-----+---------+-------+ 3 for | Field | Type | Null | Key | Default | Extra | +-----------------+-------------+------+-----+---------+-------+ | uuid_ | varchar(75) | YES | MUL | NULL | | | messageId | bigint(20) | NO | PRI | NULL | | | companyId | bigint(20) | YES | MUL | NULL | | | userId | bigint(20) | YES | | NULL | | Comments | userName | varchar(75) | YES | | NULL | | | createDate | datetime | YES | | NULL | | | modifiedDate | datetime | YES | | NULL | | | categoryId | bigint(20) | YES | MUL | NULL | | | threadId | bigint(20) | YES | MUL | NULL | | | parentMessageId | bigint(20) | YES | | NULL | | | subject | varchar(75) | YES | | NULL | | | body | longtext | YES | | NULL | | | attachments | tinyint(4) | YES | | NULL | | | anonymous | tinyint(4) | YES | | NULL | | | groupId | bigint(20) | YES | MUL | NULL | | | classNameId | bigint(20) | YES | MUL | NULL | | | classPK | bigint(20) | YES | | NULL | | | priority | double | YES | | NULL | | +-----------------+-------------+------+-----+---------+-------+ +------------------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------------+------------+------+-----+---------+-------+ | threadId | bigint(20) | NO | PRI | NULL | | | categoryId | bigint(20) | YES | MUL | NULL | | | rootMessageId | bigint(20) | YES | | NULL | | | messageCount | int(11) | YES | | NULL | | | viewCount | int(11) | YES | | NULL | | | lastPostByUserId | bigint(20) | YES | | NULL | | | lastPostDate | datetime | YES | | NULL | | | priority | double | YES | | NULL | | | groupId | bigint(20) | YES | MUL | NULL | | +------------------+------------+------+-----+---------+-------+
  • 40. +----------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+-------------+------+-----+---------+-------+ Plone Conference 2011 | uuid_ | varchar(75) | YES | MUL | NULL | | | folderId | bigint(20) | NO | PRI | NULL | | | groupId | bigint(20) | YES | MUL | NULL | | | companyId | bigint(20) | YES | MUL | NULL | | 3 for | userId | bigint(20) | YES | | NULL | | | createDate | datetime | YES | | NULL | | | modifiedDate | datetime | YES | | NULL | | | parentFolderId | bigint(20) | YES | | NULL | | | name | varchar(75) | YES | | NULL | | | description | longtext | YES | | NULL | | Images +----------------+-------------+------+-----+---------+-------+
  • 41. +----------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+-------------+------+-----+---------+-------+ Plone Conference 2011 | uuid_ | varchar(75) | YES | MUL | NULL | | | folderId | bigint(20) | NO | PRI | NULL | | | groupId | bigint(20) | YES | MUL | NULL | | | companyId | bigint(20) | YES | MUL | NULL | | 3 for | userId | bigint(20) | YES | | NULL | | | createDate | datetime | YES | | NULL | | | modifiedDate | datetime | YES | | NULL | | | parentFolderId | bigint(20) | YES | | NULL | | | name | varchar(75) | YES | | NULL | | | description | longtext | YES | | NULL | | Images +----------------+-------------+------+-----+---------+-------+ +----------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+-------------+------+-----+---------+-------+ | uuid_ | varchar(75) | YES | MUL | NULL | | | imageId | bigint(20) | NO | PRI | NULL | | | companyId | bigint(20) | YES | | NULL | | | userId | bigint(20) | YES | | NULL | | | createDate | datetime | YES | | NULL | | | modifiedDate | datetime | YES | | NULL | | | folderId | bigint(20) | YES | MUL | NULL | | | name | varchar(75) | YES | | NULL | | | description | longtext | YES | | NULL | | | smallImageId | bigint(20) | YES | MUL | NULL | | | largeImageId | bigint(20) | YES | MUL | NULL | | | custom1ImageId | bigint(20) | YES | MUL | NULL | | | custom2ImageId | bigint(20) | YES | MUL | NULL | | | groupId | bigint(20) | YES | MUL | NULL | | +----------------+-------------+------+-----+---------+-------+ +--------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------+-------------+------+-----+---------+-------+ | imageId | bigint(20) | NO | PRI | NULL | | | modifiedDate | datetime | YES | | NULL | | | text_ | longtext | YES | | NULL | | | type_ | varchar(75) | YES | | NULL | | | height | int(11) | YES | | NULL | | | width | int(11) | YES | | NULL | | | size_ | int(11) | YES | MUL | NULL | | +--------------+-------------+------+-----+---------+-------+
  • 44. Plone Conference 2011 1. Image at top 2. Author name 3. Links in body 4. Images in body 5. Footnotes 6. Comments
  • 46. +--------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | Plone Conference 2011 +--------------------+--------------+------+-----+---------+-------+ | uuid_ | varchar(75) | YES | MUL | NULL | | | id_ | bigint(20) | NO | PRI | NULL | | | resourcePrimKey | bigint(20) | YES | MUL | NULL | | | groupId | bigint(20) | YES | MUL | NULL | | | companyId | bigint(20) | YES | MUL | NULL | | | userId | bigint(20) | YES | | NULL | | | userName | varchar(75) | YES | | NULL | | | createDate | datetime | YES | | NULL | | | modifiedDate | datetime | YES | | NULL | | | articleId | varchar(75) | YES | | NULL | | | version | double | YES | | NULL | | | title | varchar(100) | YES | | NULL | | | description | longtext | YES | | NULL | | | content | longtext | YES | | NULL | | | type_ | varchar(75) | YES | | NULL | | | structureId | varchar(75) | YES | | NULL | | | templateId | varchar(75) | YES | | NULL | | | displayDate | datetime | YES | | NULL | | | approved | tinyint(4) | YES | | NULL | | | approvedByUserId | bigint(20) | YES | | NULL | | | approvedByUserName | varchar(75) | YES | | NULL | | | approvedDate | datetime | YES | | NULL | | | expired | tinyint(4) | YES | | NULL | | | expirationDate | datetime | YES | | NULL | | | reviewDate | datetime | YES | | NULL | | | indexable | tinyint(4) | YES | | NULL | | | smallImage | tinyint(4) | YES | | NULL | | | smallImageId | bigint(20) | YES | MUL | NULL | | | smallImageURL | varchar(75) | YES | | NULL | | | urlTitle | varchar(150) | YES | | NULL | | +--------------------+--------------+------+-----+---------+-------+
  • 47. +--------------------+--------------+------+-----+---------+-------+ Plone Conference 2011 Author | Field | Type | Null | Key | Default | Extra | +--------------------+--------------+------+-----+---------+-------+ | uuid_ | varchar(75) | YES | MUL | NULL | | | id_ | bigint(20) | NO | PRI | NULL | | | resourcePrimKey | bigint(20) | YES | MUL | NULL | | | groupId | bigint(20) | YES | MUL | NULL | | | companyId | bigint(20) | YES | MUL | NULL | | | userId | bigint(20) | YES | | NULL | | | userName | varchar(75) | YES | | NULL | | | createDate | datetime | YES | | NULL | | | modifiedDate | datetime | YES | | NULL | | | articleId | varchar(75) | YES | | NULL | | | version | double | YES | | NULL | | | title | varchar(100) | YES | | NULL | | | description | longtext | YES | | NULL | | | content | longtext | YES | | NULL | | | type_ | varchar(75) | YES | | NULL | | | structureId | varchar(75) | YES | | NULL | | | templateId | varchar(75) | YES | | NULL | | | displayDate | datetime | YES | | NULL | | | approved | tinyint(4) | YES | | NULL | | | approvedByUserId | bigint(20) | YES | | NULL | | | approvedByUserName | varchar(75) | YES | | NULL | | | approvedDate | datetime | YES | | NULL | | | expired | tinyint(4) | YES | | NULL | | | expirationDate | datetime | YES | | NULL | | | reviewDate | datetime | YES | | NULL | | | indexable | tinyint(4) | YES | | NULL | | | smallImage | tinyint(4) | YES | | NULL | | | smallImageId | bigint(20) | YES | MUL | NULL | | | smallImageURL | varchar(75) | YES | | NULL | | | urlTitle | varchar(150) | YES | | NULL | | +--------------------+--------------+------+-----+---------+-------+
  • 48. +--------------------+--------------+------+-----+---------+-------+ Plone Conference 2011 Author | Field | Type | Null | Key | Default | Extra | +--------------------+--------------+------+-----+---------+-------+ | uuid_ | varchar(75) | YES | MUL | NULL | | | id_ | bigint(20) | NO | PRI | NULL | | | resourcePrimKey | bigint(20) | YES | MUL | NULL | | | groupId | bigint(20) | YES | MUL | NULL | | | companyId | bigint(20) | YES | MUL | NULL | | | userId | bigint(20) | YES | | NULL | | | userName | varchar(75) | YES | | NULL | | | createDate | datetime | YES | | NULL | | | modifiedDate | datetime | YES | | NULL | | | articleId | version | title | varchar(75) | YES | | double | YES | | varchar(100) | YES | | NULL | | NULL | | NULL | | | | Body Text | description | content | type_ | longtext | longtext | YES | | YES | | varchar(75) | YES | | NULL | | NULL | | NULL | | | | (links) | structureId | varchar(75) | YES | | NULL | | | templateId | varchar(75) | YES | | NULL | | | displayDate | datetime | YES | | NULL | | | approved | tinyint(4) | YES | | NULL | | | approvedByUserId | bigint(20) | YES | | NULL | | | approvedByUserName | varchar(75) | YES | | NULL | | | approvedDate | datetime | YES | | NULL | | | expired | tinyint(4) | YES | | NULL | | | expirationDate | datetime | YES | | NULL | | | reviewDate | datetime | YES | | NULL | | | indexable | tinyint(4) | YES | | NULL | | | smallImage | tinyint(4) | YES | | NULL | | | smallImageId | bigint(20) | YES | MUL | NULL | | | smallImageURL | varchar(75) | YES | | NULL | | | urlTitle | varchar(150) | YES | | NULL | | +--------------------+--------------+------+-----+---------+-------+
  • 49. +--------------------+--------------+------+-----+---------+-------+ Plone Conference 2011 Author | Field | Type | Null | Key | Default | Extra | +--------------------+--------------+------+-----+---------+-------+ | uuid_ | varchar(75) | YES | MUL | NULL | | | id_ | bigint(20) | NO | PRI | NULL | | | resourcePrimKey | bigint(20) | YES | MUL | NULL | | | groupId | bigint(20) | YES | MUL | NULL | | | companyId | bigint(20) | YES | MUL | NULL | | | userId | bigint(20) | YES | | NULL | | | userName | varchar(75) | YES | | NULL | | | createDate | datetime | YES | | NULL | | | modifiedDate | datetime | YES | | NULL | | | articleId | version | title | varchar(75) | YES | | double | YES | | varchar(100) | YES | | NULL | | NULL | | NULL | | | | Body Text | description | content | type_ | longtext | longtext | YES | | YES | | varchar(75) | YES | | NULL | | NULL | | NULL | | | | (links) | structureId | varchar(75) | YES | | NULL | | | templateId | varchar(75) | YES | | NULL | | | displayDate | datetime | YES | | NULL | | | approved | tinyint(4) | YES | | NULL | | | approvedByUserId | bigint(20) | YES | | NULL | | | approvedByUserName | varchar(75) | YES | | NULL | | | approvedDate | datetime | YES | | NULL | | | expired | tinyint(4) | YES | | NULL | | | expirationDate | datetime | YES | | NULL | | | reviewDate | datetime | YES | | NULL | | | indexable | tinyint(4) | YES | | NULL | | | smallImage | tinyint(4) | YES | | NULL | | | smallImageId | bigint(20) | YES | MUL | NULL | | Top Image | smallImageURL | varchar(75) | YES | | NULL | | | urlTitle | varchar(150) | YES | | NULL | | +--------------------+--------------+------+-----+---------+-------+
  • 50. +--------------------+--------------+------+-----+---------+-------+ Plone Conference 2011 Author | Field | Type | Null | Key | Default | Extra | +--------------------+--------------+------+-----+---------+-------+ | uuid_ | varchar(75) | YES | MUL | NULL | | | id_ | bigint(20) | NO | PRI | NULL | | | resourcePrimKey | bigint(20) | YES | MUL | NULL | | | groupId | bigint(20) | YES | MUL | NULL | | | companyId | bigint(20) | YES | MUL | NULL | | | userId | bigint(20) | YES | | NULL | | | userName | varchar(75) | YES | | NULL | | | createDate | datetime | YES | | NULL | | | modifiedDate | datetime | YES | | NULL | | | articleId | version | title | varchar(75) | YES | | double | YES | | varchar(100) | YES | | NULL | | NULL | | NULL | | | | Body Text | description | content | type_ | longtext | longtext | YES | | YES | | varchar(75) | YES | | NULL | | NULL | | NULL | | | | (links) | structureId | varchar(75) | YES | | NULL | | | templateId | varchar(75) | YES | | NULL | | | displayDate | datetime | YES | | NULL | | | approved | tinyint(4) | YES | | NULL | | | approvedByUserId | bigint(20) | YES | | NULL | | Dates | approvedByUserName | varchar(75) | YES | | NULL | | | approvedDate | datetime | YES | | NULL | | | expired | tinyint(4) | YES | | NULL | | | expirationDate | datetime | YES | | NULL | | | reviewDate | datetime | YES | | NULL | | | indexable | tinyint(4) | YES | | NULL | | | smallImage | tinyint(4) | YES | | NULL | | | smallImageId | bigint(20) | YES | MUL | NULL | | Top Image | smallImageURL | varchar(75) | YES | | NULL | | | urlTitle | varchar(150) | YES | | NULL | | +--------------------+--------------+------+-----+---------+-------+
  • 51. Plone Conference 2011 Join SELECT IGImage.imageId, Image IGImage.createDate, IGImage.modifiedDate, IGImage.uuid_, Scales IGImage.userId, IGImage.name, IGImage.description, IGImage.smallImageId, IGImage.largeImageId, IGImage.custom1ImageId, IGImage.custom2ImageId, IGImage.folderId, Image.type_ FROM IGImage JOIN Image ON IGImage.largeImageId = Image.imageId
  • 52. Plone Conference 2011 Get Article Comments SELECT COALESCE(gui.guestName, mbm.userName) AS userName, mbm.createDate, mbm.modifiedDate, mbm.subject, mbm.body FROM MBMessage mbm JOIN MBDiscussion mbd ON mbd.threadId = mbm.threadId LEFT JOIN guestUserInfo gui ON gui.messageId = mbm.messageId WHERE mbd.classPK=%d ORDER BY modifiedDate
  • 56. Plone Conference 2011 Transmogrifier “It’s a series of tubes”
  • 60. Plone Conference 2011 Not Too Opinionated
  • 61. Plone Conference 2011 Not Too Opinionated
  • 62. Plone Conference 2011 Not Too Opinionated A migration deals with moving pieces of content from one place to another
  • 63. Plone Conference 2011 Not Too Opinionated A migration deals with moving pieces of content from one place to another A piece of content comes from somewhere
  • 64. Plone Conference 2011 Not Too Opinionated A migration deals with moving pieces of content from one place to another A piece of content comes from somewhere A piece of content ends up somewhere
  • 65. Plone Conference 2011 Not Too Opinionated A migration deals with moving pieces of content from one place to another A piece of content comes from somewhere A piece of content ends up somewhere You should be able to do what you want to a piece of content between point A and point B
  • 66. Plone Conference 2011 A Nice Set of Tools
  • 67. Plone Conference 2011 A Nice Set of Tools
  • 70. Plone Conference 2011 Two Main Types Images
  • 71. Plone Conference 2011 Two Main Types Images Articles
  • 73. Plone Conference 2011 Two Pipelines One for each main content category
  • 75. Plone Conference 2011 Two Pipelines • Extract content from SQL
  • 76. Plone Conference 2011 Two Pipelines • Extract content from SQL • Update text field encodings
  • 77. Plone Conference 2011 Two Pipelines • Extract content from SQL • Update text field encodings • Transform Dates to Python
  • 78. Plone Conference 2011 Two Pipelines • Extract content from SQL • Update text field encodings • Transform Dates to Python • Calculate Final Plone Location
  • 79. Plone Conference 2011 Two Pipelines • Extract content from SQL • Update text field encodings • Transform Dates to Python • Calculate Final Plone Location • Create Plone Object
  • 80. Plone Conference 2011 Two Pipelines • Extract content from SQL • Update text field encodings • Transform Dates to Python • Calculate Final Plone Location • Create Plone Object • Post-process (publication, etc.)
  • 81. Plone Conference 2011 A Simplification but you get the idea
  • 82. Plone Conference 2011 Can You Spot the Flaw? Photo by pollyann - CC-BY-NC-ND http://www.flickr.com/photos/pollyann/4299826600/
  • 83. Plone Conference 2011 How Do We Match Them? Plone ID != Original SQL ID
  • 84. Plone Conference 2011 How Do We Match Them? JournalArticle.smallImageId != Image.smallImageID
  • 85. Plone Conference 2011 How Do We Match Them? JournalArticle.smallImageId != JournalArticle.smallImageURL | 449868 | /image/image_gallery?img_id=449858&t=1296250152541 | | 449894 | /image/image_gallery?img_id=449888&t=1296250703087 | | 450604 | /image/image_gallery?img_id=450582&t=1296515550638 | | 450845 | /image/image_gallery?img_id=450835&t=1296599014396 | | 450917 | /image/image_gallery?img_id=450907&t=1296615851690 |
  • 86. Plone Conference 2011 Photo by hobvias sudoneighm - CC-BY http://www.flickr.com/photos/striatic/2192192956/
  • 89. Plone Conference 2011 Splitter Section run content down different pipelines in one transmogrifier
  • 90. Plone Conference 2011 Annotations store data on the transmogrifier to communicate between pipeline sections
  • 91. Plone Conference 2011 How Does This Help?
  • 92. Plone Conference 2011 Three Facts 1. Pipeline sections are generators class MySection(object): classProvides(ISectionBlueprint) implements(ISection) def __init__(self, transmogrifier, name, options, previous): [setup] def __iter__(self): ... for item in self.previous: [do some stuff] ... yield item [clean up]
  • 93. Plone Conference 2011 Three Facts 2. SQL sections process items 1 query at a time for query in self.queries: result=self.connection.execute(query) for row in result: yield dict((x[0].encode('utf-8'), x[1]) for x in row.items())
  • 94. Plone Conference 2011 Three Facts 3. Pipelines process one item at a time class SectionOne(object): class SectionTwo(object): def __iter__(self): def __iter__(self): ... ... for item in self.previous: for item in self.previous: [do some stuff] [do some stuff] ... ... yield item yield item
  • 99. Plone Conference 2011 class IGImageIDMapper(object): classProvides(ISectionBlueprint) implements(ISection) def __init__(self, transmogrifier, name, options, previous): self.transmogrifier = transmogrifier ... annotations = IAnnotations(self.transmogrifier) if IMAGE_MAPS_KEY in annotations: self.image_maps = annotations[IMAGE_MAPS_KEY] else: annotations[IMAGE_MAPS_KEY] = self.image_maps = {'img_uuid': {}, 'sm_img_id': {}, 'lg_img_id': {}, 'c1_img_id': {}, 'c2_img_id': {}}
  • 100. Plone Conference 2011 class IGImageIDMapper(object): classProvides(ISectionBlueprint) implements(ISection) def __init__(self, transmogrifier, name, options, previous): self.transmogrifier = transmogrifier ... annotations = IAnnotations(self.transmogrifier) if IMAGE_MAPS_KEY in annotations: self.image_maps = annotations[IMAGE_MAPS_KEY] else:__iter__(self): def annotations[IMAGE_MAPS_KEY] = self.image_maps = {'img_uuid': {}, for item in self.previous: if item['_type'] != 'Folder': 'sm_img_id': {}, path = item.get('_path', None)'lg_img_id': {}, 'c1_img_id': {}, current = self.transmogrifier.context.unrestrictedTraverse(path) if current: 'c2_img_id': {}} cuid = current.UID() info = {'uid': cuid, 'path': path} self.image_maps['img_uuid'][item['uuid_']] = info self.image_maps['lg_img_id'][item['largeImageId']] = info self.image_maps['sm_img_id'][item['smallImageId']] = info self.image_maps['c1_img_id'][item['custom1ImageId']] = info self.image_maps['c2_img_id'][item['custom2ImageId']] = info yield item
  • 105. Plone Conference 2011 class GetArticleImage(object): classProvides(ISectionBlueprint) implements(ISection) def __iter__(self): annotations = IAnnotations(self.transmogrifier) self.image_maps = annotations[IMAGE_MAPS_KEY] for item in self.previous: if item['smallImage'] != 0: img_id = None try: url = item['smallImageURL'] img_id = extract_img_id_from_url(url) if img_id is None: img_id = extract_img_uuid_from_url(url) except KeyError: img_id = item['smallImageId'] if img_id is not None: img_info = find_image_from_id(img_id, self.image_maps) ... yield item
  • 106. Plone Conference 2011 Victory! Photo by Petr & Bara Ruzicka - CC-BY http://www.flickr.com/photos/pruzicka/207209564/
  • 107. Plone Conference 2011 Image by justinshearer - CC-BY-NC-SA http://www.flickr.com/photos/justinshearer/3675295127/
  • 108. Plone Conference 2011 What About Links In Articles
  • 109. Plone Conference 2011 What About Links In Articles To Other Articles?
  • 110. Plone Conference 2011 Images finish before Articles Start
  • 111. Plone Conference 2011 Image Information Images finish before Articles Start
  • 112. Plone Conference 2011 Image Information Images finish before Articles Start
  • 115. Plone Conference 2011 Article 1 ID Article 1 Identifiers Stored
  • 117. Plone Conference 2011 Article 1 ID Article 2 Links Processed
  • 118. Plone Conference 2011 Article 1 ID Article 2 Links Processed Link to Article 1 ✓
  • 119. Plone Conference 2011 Article 1 ID Article 2 Links Processed Link to Article 1 ✓ Link to Article 3 ✗
  • 120. Plone Conference 2011 Sad Panda Photo by Luis Markovic - CC-BY http://www.flickr.com/photos/_lulu/3265194525/
  • 122. Plone Conference 2011 Three Facts 1. Pipeline sections are generators class MySection(object): classProvides(ISectionBlueprint) implements(ISection) def __init__(self, transmogrifier, name, options, previous): [setup] def __iter__(self): ... for item in self.previous: [do some stuff] ... yield item [clean up]
  • 123. Plone Conference 2011 One Fact, Really 1. Pipeline sections are generators class MySection(object): classProvides(ISectionBlueprint) implements(ISection) def __init__(self, transmogrifier, name, options, previous): [setup] def __iter__(self): ... for item in self.previous: [do some stuff] ... yield item [clean up]
  • 124. Plone Conference 2011 One Fact, Really 1. Pipeline sections are generators class MySection(object): classProvides(ISectionBlueprint) implements(ISection) def __init__(self, transmogrifier, name, options, previous): [setup] def __iter__(self): ... for item in self.previous: [do some stuff] ... yield item [clean up]
  • 125. Plone Conference 2011 After all items are gone
  • 126. Plone Conference 2011 After all items are gone Cleanup code is run
  • 127. Plone Conference 2011 Set up ID Map class PostCreation(object): classProvides(ISectionBlueprint) implements(ISection) def __init__(self, transmogrifier, name, options, previous): self.transmogrifier = transmogrifier ... if DOC_MAPS_KEY in annotations.keys(): self.doc_maps = annotations[DOC_MAPS_KEY] else: annotations[DOC_MAPS_KEY] = self.doc_maps = {'resourcePrimKey': {}, 'urlTitle': {}, 'articleId': {}, 'uuid_': {}, '_path': {}}
  • 128. Plone Conference 2011 Set up ID Map class PostCreation(object): classProvides(ISectionBlueprint) implements(ISection) def __init__(self, transmogrifier, name, options, previous): def __iter__(self): self.transmogrifier = transmogrifier site = self.transmogrifier.context ... for item in self.previous: if DOC_MAPS_KEY in annotations.keys(): path = item.get('_path', None) self.doc_maps = annotations[DOC_MAPS_KEY] if path: else: try: annotations[DOC_MAPS_KEY] = self.doc_maps = {'resourcePrimKey': {}, current = site.unrestrictedTraverse(path) except KeyError: 'urlTitle': {}, 'articleId': {}, # missing element in path somewhere, skip it? pass 'uuid_': {}, if current: '_path': {}} cuid = current.UID() for key in ['resourcePrimKey', 'urlTitle', 'articleId', 'uuid_', '_path']: if key in item: self.doc_maps[key][item[key]] = cuid yield item
  • 129. Plone Conference 2011 Find Image Links class ImageTagsFinder(object): classProvides(ISectionBlueprint) implements(ISection) def __init__(self, transmogrifier, name, options, previous): self.transmogrifier = transmogrifier ... annotations = IAnnotations(transmogrifier) if REWRITABLE_ELEMENTS_KEY not in annotations.keys(): annotations[REWRITABLE_ELEMENTS_KEY] = {} self.rewriteable = annotations[REWRITABLE_ELEMENTS_KEY]
  • 130. Plone Conference 2011 Find Image Links class ImageTagsFinder(object): classProvides(ISectionBlueprint) def __iter__(self): implements(ISection) num_found = 0 for item in self.previous: def __init__(self, transmogrifier, name, options, previous): self.transmogrifier = item['_path'] path = transmogrifier ... if tree is None: parser = etree.HTMLParser() annotations = IAnnotations(transmogrifier) tree = etree.fromstring(item['text'], parser) if REWRITABLE_ELEMENTS_KEY not in annotations.keys(): if tree is not None: annotations[REWRITABLE_ELEMENTS_KEY] = {} all_images = tree.xpath('//img') self.rewriteable = annotations[REWRITABLE_ELEMENTS_KEY] if len(all_images) > 0: # we have some anchors, do any need re-writing? internal = [] for img in all_images: src = img.attrib.get('src', '') match = img_is_internal(src) if match: internal.append(img) mapped['images'] = internal self.rewriteable[path] = internal yield item
  • 131. Find Other Tags Plone Conference 2011 class LinkFinder(object): """ create a mapping of the items which have links to be modified """ classProvides(ISectionBlueprint) implements(ISection) def __init__(self, transmogrifier, name, options, previous): self.transmogrifier = transmogrifier annotations = IAnnotations(transmogrifier) if REWRITABLE_ELEMENTS_KEY not in annotations.keys(): annotations[REWRITABLE_ELEMENTS_KEY] = {} self.rewriteable = annotations[REWRITABLE_ELEMENTS_KEY]
  • 132. Find Other Tags Plone Conference 2011 class LinkFinder(object): """ create a mapping of the items which have links to be modified """ classProvides(ISectionBlueprint) implements(ISection) def __iter__(self): def __init__(self,etrees of any documents with links that need fixing """ save transmogrifier, name, options, previous): """ self.transmogrifier = transmogrifier annotations =in self.previous: for item IAnnotations(transmogrifier) path = item['_path'] if REWRITABLE_ELEMENTS_KEY not in annotations.keys(): annotations[REWRITABLE_ELEMENTS_KEY]parser) tree = etree.fromstring(item['text'], = {} if tree is not None: self.rewriteable = annotations[REWRITABLE_ELEMENTS_KEY] all_anchors = tree.xpath('//a') if len(all_anchors) > 0: # we have some anchors, do any need re-writing? internal = [] for a in all_anchors: href = a.attrib.get('href', '') if is_internal_link(href): internal.append(href) self.rewriteable[path] = internal yield item
  • 133. Plone Conference 2011 Replace Found Links class LinkReplacer(object): """ re-write links in body texts of all created items The work done by this item takes place entirely in the clean-up stage of the section. """ classProvides(ISectionBlueprint) implements(ISection) def __init__(self, transmogrifier, name, options, previous): self.transmogrifier = transmogrifier annotations = IAnnotations(transmogrifier) if REWRITABLE_ELEMENTS_KEY not in annotations.keys(): annotations[REWRITABLE_ELEMENTS_KEY] = {} self.rewriteable = annotations[REWRITABLE_ELEMENTS_KEY]
  • 134. Plone Conference 2011 Replace Found Links class LinkReplacer(object): """ re-write links in body texts of all created items def __iter__(self): The work done by this item takes place entirely in the clean-up stage of the section. in self.previous: for item """ # no action takes place here yield item classProvides(ISectionBlueprint) implements(ISection) # get the maps we will use annotations = IAnnotations(self.transmogrifier) def __init__(self, transmogrifier, name, options, previous): doc_maps = annotations[DOC_MAPS_KEY] self.transmogrifier = transmogrifier image_maps = annotations[IMAGE_MAPS_KEY] annotations = IAnnotations(transmogrifier) if REWRITABLE_ELEMENTS_KEY tagsin annotations.keys(): # rewrite image and anchor not for path, info in self.rewriteable.items(): annotations[REWRITABLE_ELEMENTS_KEY] = {} page = self.transmogrifier.context.unrestrictedTraverse(path) self.rewriteable = annotations[REWRITABLE_ELEMENTS_KEY] tree = info.get('tree', None) links = info.get('links', []) images = info.get('images', []) lg, ln, le = rewrite_links(links, page, doc_maps, self.logger, self.transmogrifier.context) ig, _in, ie = rewrite_image_tags(images, page, image_maps, self.logger)
  • 135. Plone Conference 2011 Victory! Photo by Petr & Bara Ruzicka - CC-BY http://www.flickr.com/photos/pruzicka/207209564/
  • 136. Plone Conference 2011 Victory! Right? Photo by Petr & Bara Ruzicka - CC-BY http://www.flickr.com/photos/pruzicka/207209564/
  • 139. Plone Conference 2011 Photo of moo http://instagr.am/p/SSMBw/
  • 141. Plone Conference 2011 Link Formats how many can you imagine?
  • 142. Plone Conference 2011 Link Formats how many can you imagine? we had them all
  • 144. Plone Conference 2011 5-10 Links per Article
  • 145. Plone Conference 2011 5-10 Links per Article at least
  • 146. Plone Conference 2011 5-10 Links per Article at least you do the math
  • 147. Plone Conference 2011 How to Find the Bad Ones? Photo by Alessandra Oddi - CC-BY http://www.flickr.com/photos/uvafragola/4834037874/
  • 151. Plone Conference 2011 CSV Reports Which links worked?
  • 152. Plone Conference 2011 CSV Reports Which links worked? Which links didn’t?
  • 153. class LinkReplacer(object): """ re-write links in body texts of all created items """ classProvides(ISectionBlueprint) implements(ISection) ... def __iter__(self): good, notenough, errors = [],[],[] for item in self.previous: yield item for path, info in self.rewriteable.items(): page = self.transmogrifier.context.unrestrictedTraverse(path) tree = info.get('tree', None) links = info.get('links', []) images = info.get('images', []) lg, ln, le = rewrite_links(links, page, doc_maps, self.logger, self.transmogrifier.context) ig, _in, ie = rewrite_image_tags(images, page, image_maps, self.logger) good.extend(lg + ig) notenough.extend(ln + _in) errors.extend(le + ie) with open('goodlinks.csv', 'w') as f: goodwriter = csv.writer(f) goodwriter.writerows(good) with open('badlinks.csv', 'w') as f: badwriter = csv.writer(f) badwriter.writerows(notenough) ...
  • 154. class LinkReplacer(object): """ re-write links in body texts of all created items """ def rewrite_image_tags(images, page, img_maps, logger): good = [] classProvides(ISectionBlueprint) notenough = [] implements(ISection) ... errors = [] def __iter__(self): image in images: for url = image.attrib.get('src', '') good, notenough, errors = [],[],[] # get information about the image to be subbed, either by id or uuid for item in self.previous: yield item img_id = extract_img_id_from_url(url) for path, info in img_id is None: if self.rewriteable.items(): img_id = extract_img_uuid_from_url(url) page = self.transmogrifier.context.unrestrictedTraverse(path) tree = info.get('tree', is None: if img_id None) links = info.get('links', []) not find a mapped image matching, not enough to go on # we could logger.warn('unable to find image id in url: %s' % url) images = info.get('images', []) lg, ln, le = rewrite_links(links, page, doc_maps, bad url', page.absolute_url(), url)) notenough.append(('missing img, continue self.logger, self.transmogrifier.context) ig, _in, ie =# resolve the id we found into a plone object UID via image maps rewrite_image_tags(images, page, image_maps, img_info = find_image_from_id(img_id, img_maps) self.logger) if img_info is None: good.extend(lg + ig) logger.warn('unable to find mapped plone image id %s' % img_id) notenough.extend(ln + _in) notenough.append(('missing img, no map', page.absolute_url(), url)) errors.extend(le + ie) continue with open('goodlinks.csv', 'w') as f: goodwriter # by default, use the 300x300 px medium size for in-page images = csv.writer(f) # To change this, adjust the value of STANDARD_IMG_SCALE goodwriter.writerows(good) newurl = "resolveuid/%s%s" % (img_info['uid'], with open('badlinks.csv', 'w') as f: badwriter = csv.writer(f) STANDARD_IMG_SCALE) badwriter.writerows(notenough)newurl image.attrib['src'] = ... good.append(('image match', page.absolute_url(), url)) return good, notenough, errors
  • 155.
  • 157. Plone Conference 2011 Iteration FTW! from > 2000 bad links
  • 158. Plone Conference 2011 Iteration FTW! from > 2000 bad links to < 75 bad links
  • 159. Plone Conference 2011 Iteration FTW! from > 2000 bad links to < 75 bad links fix those that remain by hand
  • 160. Plone Conference 2011 Victory! Photo by Petr & Bara Ruzicka - CC-BY http://www.flickr.com/photos/pruzicka/207209564/
  • 161. Plone Conference 2011 So What Did We Learn?
  • 162. Plone Conference 2011 Clients, when asked to describe their existing system, will never describe it with enough accuracy to properly plan for a migration
  • 163. Plone Conference 2011 Learn as much as you can about the source system when planning a migration
  • 164. Plone Conference 2011 Learn as much as you can about the source system when planning a migration but know that you will always need to know more
  • 165. Plone Conference 2011 Learn as much as you can about the source system when planning a migration but know that you will always need to know more and that you will not find it out until you actually start the migration
  • 166. Plone Conference 2011 Users, if given more than one way to do things, will use all the ways
  • 167. Plone Conference 2011 Have a plan, but be prepared to adjust when reality hits. Plans are best when treated as jumping-off points.
  • 168. Plone Conference 2011 Estimate Migrations HIGH
  • 169. Plone Conference 2011 Photo by neilspicys - CC-BY http://www.flickr.com/photos/neilspicys/2349770710/
  • 170. Check p.com/de out mos sixfeetu

Notes de l'éditeur

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n
  111. \n
  112. \n
  113. \n
  114. \n
  115. \n
  116. \n
  117. \n
  118. \n
  119. \n
  120. \n
  121. \n
  122. \n
  123. \n
  124. \n
  125. \n
  126. \n
  127. \n
  128. \n
  129. \n
  130. \n
  131. \n
  132. \n
  133. \n
  134. \n
  135. \n
  136. \n
  137. \n
  138. \n
  139. \n
  140. \n
  141. \n
  142. \n
  143. \n
  144. \n
  145. \n
  146. \n
  147. \n
  148. \n
  149. \n
  150. \n
  151. \n
  152. \n