hacking movable type training - day 1

55
Page Six Apart Ltd. Hacking Movable Type A guide for developers

Upload: byrne-reese

Post on 01-Nov-2014

11.205 views

Category:

Technology


3 download

DESCRIPTION

A series of slides presented to developers wishing to learn how to build plugins using Movable Type.

TRANSCRIPT

Page 1: Hacking Movable Type Training - Day 1

Page

SixApartLtd.

HackingMovableTypeAguidefordevelopers

Page 2: Hacking Movable Type Training - Day 1

Page

DevelopingforMovableTypein2Days

• Day1:TheBasics– PluginStructure

– TheRegistry

– ConfiguraEonDirecEves

– TemplateTags

– Objects

– Callbacks

• Day2:BuildingUserInterfaces– Menus

– NewApplicaEonScreens

– Dialogs

– LisEngScreens

2

Page 3: Hacking Movable Type Training - Day 1

Page

CoursePrerequisites

• ThiscourserequiresthatyouhaveaccesstoaworkingMovableTypeinstalla:on.

• Thiscoursealsoassumesthatyouarefamiliarwithbasicsystemadministra:ontasks,suchascopyingandediEngfiles.

• Finally,thiscourserequiresknowledgeofthePerlprogramminglanguage.

Page 4: Hacking Movable Type Training - Day 1

Page

AboutHacking

• Whatmakesagoodprogrammer?

• UsethesourceLuke.

• Copyandpasteisyourfriend.

Page 5: Hacking Movable Type Training - Day 1

Page

DevelopingforMovableTypein2Days

• Day1:TheBasics➡ PluginStructure

– TheRegistry

– ConfiguraEonDirecEves

– TemplateTags

– Objects

– Callbacks

• Day2:BuildingUserInterfaces– Menus

– NewApplicaEonScreens

– Dialogs

– LisEngScreens

5

Page 6: Hacking Movable Type Training - Day 1

Page

PluginStructure

• Yourconfigfile– plugins/MyPlugin/config.yaml

• Yourlibraryfiles– plugins/MyPlugin/lib/*

• Yourtemplates– plugins/MyPlugin/tmpl/*

• YourstaEcimages,javascriptandCSSfiles– mt-static/plugins/MyPlugin/*

Page 7: Hacking Movable Type Training - Day 1

Page

PluginStructure

• Otherimportantfilesanddirectories– MyPlugin-README.txt– MyPlugin-LICENSE.txt– plugins/MyPlugin/t/*– plugins/MyPlugin/extlib/*– plugins/MyPlugin/php/*

Page 8: Hacking Movable Type Training - Day 1

Page

PluginPackaging

• FilesthatreallyhelpwiththepackaginganddistribuEonofanenEreplugin:– Makefile.PL

– MANIFEST.SKIP

Page 9: Hacking Movable Type Training - Day 1

Page

Makefile.PL

use ExtUtils::MakeMaker;WriteMakefile( NAME => "My Plugin's Display Name", VERSION => '1.1', DISTNAME => 'MyPlugin',);

Page 10: Hacking Movable Type Training - Day 1

Page

MANIFEST.SKIP

# version control\bCVS(^|/)\.

# CPAN chain files^MANIFEST^Makefile^META.yml$^blib/~$

# packages\.zip$\.tar\.gz$

Page 11: Hacking Movable Type Training - Day 1

Page

CreaEngaPluginZipFile

Thesesimplesequenceofcommands:

> perl Makefile.PL> make manifest> make zipdist

WillproducetheperfectMTPluginzipfile:• MyPlugin‐1.1.zip

Page 12: Hacking Movable Type Training - Day 1

Page

DevelopingforMovableTypein2Days

• Day1:TheBasics– PluginStructure

➡ TheRegistry

– ConfiguraEonDirecEves

– TemplateTags

– Objects

– Callbacks

• Day2:BuildingUserInterfaces– Menus

– NewApplicaEonScreens

– Dialogs

– LisEngScreens

12

Page 13: Hacking Movable Type Training - Day 1

Page

TheMovableTypeRegistry

• MovableTypeisaconfig‐drivenapplicaEon.

• The“registry”iswhereMovableTypestoresitsconfiguraEon.

• Eachpluginprovidesamini‐registryfile,config.yaml,thatdefinesitsfeatureset.

• Theconfig.yamlfileisthenmergedintoMovableType’smainregistry.

• Everypluginthereforeis50%configuraEonand50%code.

Page 14: Hacking Movable Type Training - Day 1

Page

config.yaml

name: Fluid Appid: FluidAppauthor_link: http://www.majordojo.com/author_name: Byrne Reesedescription: This plugin provides enhanced support for Fluid.version: 0.90plugin_link: http://www.majordojo.com/projects/mt-fluid-app.php

applications: cms: methods: fluid_update: $FluidApp::FluidApp::Plugin::cms_updatecallbacks: MT::App::CMS::template_source.header: $FluidApp::…::Plugin::xfrm

Page 15: Hacking Movable Type Training - Day 1

Page

YikesWhatisallthat?

Page 16: Hacking Movable Type Training - Day 1

Page

AYAMLPrimer

• YAML==“YetAnotherMarkupLanguage”

• XMLAlternaEve

• Lessverbose

• Humanreadableandwritable

Page 17: Hacking Movable Type Training - Day 1

Page

XMLvs.YAML

<?xml version="1.0"><address> <first_name>Byrne</first_name> <last_name>Reese</last_name> <email>[email protected]</email> <company> <name>Six Apart, Ltd.</name> <street_address> 548 4th Street, San Francisco, CA 94107 </street_address> </company></address>

Page 18: Hacking Movable Type Training - Day 1

Page

XMLvs.YAML

address: first_name: Byrne last_name: Reese email: [email protected] company: name: Six Apart, Ltd. street_address: 548 4th Street, \ San Francisco, CA 94107

Page 19: Hacking Movable Type Training - Day 1

Page

YourFirstPlugin

Placethisin:plugins/Good4Nothing/config.yaml

name: Good for Nothing Plugin for Movable Typeid: Good4Nothingkey: Good4Nothingauthor_link: http://www.yourwebsite.com/author_name: Your Name Heredescription: This plugin is an example plugin.version: 1.0

Page 20: Hacking Movable Type Training - Day 1

Page

DevelopingforMovableTypein2Days

• Day1:TheBasics– PluginStructure

– TheRegistry

➡ Configura:onDirec:ves

– TemplateTags

– Objects

– Callbacks

• Day2:BuildingUserInterfaces– Menus

– NewApplicaEonScreens

– Dialogs

– LisEngScreens

20

Page 21: Hacking Movable Type Training - Day 1

Page

AddingaConfigDirecEve

• WhatisaconfiguraEondirecEve?

• WhenshouldyouuseaconfigdirecEve?

• WhatarethealternaEves?

Page 22: Hacking Movable Type Training - Day 1

Page

AddingaConfigDirecEve

name: Good for Nothing Plugin for Movable Typeid: Good4Nothingkey: Good4Nothingauthor_link: http://www.yourwebsite.com/author_name: Your Name Heredescription: This plugin is an example plugin.version: 1.0config_settings: MyImageURL: default: http://path.com/images/foo.jpg

Page 23: Hacking Movable Type Training - Day 1

Page

ConfigDirecEveProperEes

• RegistryproperEes:– path

– handler

– alias

Page 24: Hacking Movable Type Training - Day 1

Page

DevelopingforMovableTypein2Days

• Day1:TheBasics– PluginStructure

– TheRegistry

– ConfiguraEonDirecEves

➡ TemplateTags

– Objects

– Callbacks

• Day2:BuildingUserInterfaces– Menus

– NewApplicaEonScreens

– Dialogs

– LisEngScreens

24

Page 25: Hacking Movable Type Training - Day 1

Page

AddingaTemplateTag

• Whatisatemplatetag?

• Wherearetemplatetagsused?

• Whatarethevarioustypesoftemplatetags?

Page 26: Hacking Movable Type Training - Day 1

Page

AddingaTemplateTag‐config.yaml

name: Good for Nothing Plugin for Movable Typeid: Good4Nothingkey: Good4Nothingauthor_link: http://www.yourwebsite.com/author_name: Your Name Heredescription: This plugin is an example plugin.version: 1.0config_settings: MyImageURL: default: http://path.com/images/foo.jpgtags: function: MyImageURL: $Good4Nothing::Good4Nothing::Plugin::tag

Page 27: Hacking Movable Type Training - Day 1

Page

AddingaTemplateTag‐Handler

# Good for Nothing Plugin for Movable Type# Author: Your Name Here, [email protected]# Copyright (C) 2008 Your Name Here# This file is licensed under the Artistic License,# or the same terms as Perl itself.

package Good4Nothing::Plugin;use strict;

sub tag { my ($ctx) = @_; my $cfg = $ctx->{config}; return $cfg->MyImageURL; }

1; # Every module must return true

Page 28: Hacking Movable Type Training - Day 1

Page

MoreaboutTemplateTags

• TypesofTags– funcEon

– block

– modifiers

• CondiEonalTags

• Loops

• TemplateContext

Page 29: Hacking Movable Type Training - Day 1

Page

MoreaboutTemplateTags

tags: function: 'SaySomething': $Example::Example::Plugin::SaySomething

'SayWhatever': $Example::Example::Plugin::SayWhatever block: 'LoopTenTimes': $Example::Example::Plugin::LoopTenTimes 'IfOdd?': $Example::Example::Plugin::IfOdd

Page 30: Hacking Movable Type Training - Day 1

Page

MoreaboutTemplateTags

# Example: <mt:SaySomething>sub SaySomething { my ($ctx, $args) = @_; return "Something""; }

# Example: <mt:SayWhatever say=”Hello”>sub SayWhatever { my ($ctx, $args) = @_; # What the person passed in through the # argument 'say' my $input = $args->{'say'}; return $input;}

Page 31: Hacking Movable Type Training - Day 1

Page

MoreaboutTemplateTags

# Example: <mt:LoopTenTimes>...</mt:LoopTenTimes>sub LoopTenTimes { my ($ctx, $args, $cond) = @_; my $out = ""; my $builder = $ctx->stash('builder'); my $tokens = $ctx->stash('tokens'); for (my $i = 1; $i <= 10; $i++) { $ctx->stash("current_loop_number",$i); $out .= "$i * " . $builder->build($ctx,$tokens,$cond); } return $out;}

# Example: <mt:IfOdd>do this</mt:IfOdd>sub IfOdd { my ($ctx, $args, $cond) = @_; my $num = $ctx->stash('current_loop_number'); if ($num % 2 == 0) { return 0; } else { return 1; }}

Page 32: Hacking Movable Type Training - Day 1

Page

AddingaTagModifier

• Whatisatagmodifier?

• Examplemodifiers:– <mt:block capitalize=“1”>abc</block>– <mt:block ltrim=“1”> foo</mt:block>– <mt:block regex_replace=“/foo/gi”,”bar”>

foo</mt:block>

– <mt:block count_words=“1”>Hello World</mt:block>

Page 33: Hacking Movable Type Training - Day 1

Page

AddingaTemplateTag‐config.yaml

name: Good for Nothing Plugin for Movable Typeid: Good4Nothingkey: Good4Nothingauthor_link: http://www.yourwebsite.com/author_name: Your Name Heredescription: This plugin is an example plugin.version: 1.0config_settings: MyImageURL: default: http://path.com/images/foo.jpgtags: modifier: lolcats: $Good4Nothing::Good4Nothing::Plugin::lolcats

Page 34: Hacking Movable Type Training - Day 1

Page

AddingaModifier‐Handler

# Good for Nothing Plugin for Movable Type# Author: Your Name Here, [email protected]# Copyright (C) 2008 Your Name Here# This file is licensed under the Artistic License,# or the same terms as Perl itself.

package Good4Nothing::Plugin;use strict;

sub lolcats { my ($str, $val, $ctx) = @_; return "CAN I HAZ “. uc($str);}

1; # Every module must return true

Page 35: Hacking Movable Type Training - Day 1

Page

DevelopingforMovableTypein2Days

• Day1:TheBasics– PluginStructure

– TheRegistry

– ConfiguraEonDirecEves

– TemplateTags

➡ Objects

– Callbacks

• Day2:BuildingUserInterfaces– Menus

– NewApplicaEonScreens

– Dialogs

– LisEngScreens

35

Page 36: Hacking Movable Type Training - Day 1

Page

ObjectsandDataPersistence

• AnoverviewofMovableTypeObjects–MT::Entry

–MT::Comment

– Etc.

• BeforeandaferarecordismodifiedintheMovableTypedatabase,aneventisfired.

• Pluginscanregistercallbacksforthoseevents.

Page 37: Hacking Movable Type Training - Day 1

Page

AboutMTObjects

• MovableType’sDataAbstracEonLayer– Data::ObjectDriver

–MT::ObjectDriver

–MT::Object

• MemcachedSupport

• EventPropagaEon

• Gegers/Segers

Page 38: Hacking Movable Type Training - Day 1

Page

InteracEngwithMT::Objects

• MT::MyObject‐>new()• $obj‐>save()• MT::MyObject‐>load($terms,$arguments)• MT::MyObject‐>load_iter($terms,$arguments)• $obj‐>remove($terms,$arguments)• MT::MyObject‐>remove_all• MT::MyObject‐>count($terms)• MT::MyObject‐>exists($terms)• $obj‐>clone()

Page 39: Hacking Movable Type Training - Day 1

Page

new()andsave()

my $foo = MT::Foo->new;$foo->first_name(’Byrne');$foo->last_name(‘Reese’);$foo->save() or die "Saving foo failed: ", $foo->errstr;

Page 40: Hacking Movable Type Training - Day 1

Page

load()

my @objects = MT::Foo->load( { title => "Hello World", foo => "bar", }, { sort => 'created_on', direction => 'ascend', });

foreach my $obj (@objects) { print $obj->baz(); # do something}

Page 41: Hacking Movable Type Training - Day 1

Page

load_iter()

my $iter = MT::Foo->load_iter( { title => "Hello World", foo => "bar", }, { sort => 'created_on', direction => 'ascend', });

while (my $obj = $iter->()) { print $obj->baz(); # do something}

Page 42: Hacking Movable Type Training - Day 1

Page

loadandload_iterOpEons

• sort• direcEon• limit• lastn• offset• start_val• range• range_incl• join• unique

Page 43: Hacking Movable Type Training - Day 1

Page

CreaEngYourOwnObject

• SchemadefiniEon• Registeringdatabaseindexes• RecordaudiEng• Primarykeys• MetaData

Page 44: Hacking Movable Type Training - Day 1

Page

MT::MyObject

package Example::MyObject;

use strict;use base qw( MT::Object );

__PACKAGE__->install_properties({ column_defs => { 'id' => 'integer not null auto_increment', 'blog_id' => 'integer', 'some_property' => 'string(100) not null', }, audit => 1, indexes => { id => 1, }, datasource => 'myplugin_myobject', primary_key => 'id',});

Page 45: Hacking Movable Type Training - Day 1

Page

MT::ObjectDatabaseDataTypes

• string• integer• boolean• smallint• dateEme• blob• text• float

Page 46: Hacking Movable Type Training - Day 1

Page

ExtendingExisEngObjects

• ExtendingexisEngobjects• schema_versionregistryproperty

Page 47: Hacking Movable Type Training - Day 1

Page

ExtendingExisEngObjects

name: Example Plugin for Movable Typeid: Examplekey: Exampledescription: This plugin is an example pluginversion: 1.0schema_version: 2object_types: entry: is_featured: smallint

Page 48: Hacking Movable Type Training - Day 1

Page

ExtendingExisEngObjects

• Whichthenlet’syoudothis:

use MT::Entry;my $entry = MT::Entry->load($id);$entry->is_featured(1);$entry->save;

Page 49: Hacking Movable Type Training - Day 1

Page

DevelopingforMovableTypein2Days

• Day1:TheBasics– PluginStructure

– TheRegistry

– ConfiguraEonDirecEves

– TemplateTags

– Objects

➡ Callbacks

• Day2:BuildingUserInterfaces– Menus

– NewApplicaEonScreens

– Dialogs

– LisEngScreens

49

Page 50: Hacking Movable Type Training - Day 1

Page

MovableTypeCallbacks

• Nomenclature:– Event,Callback,Fire,Listening

• EventTypes– ObjectLevel

– ApplicaEonLevel

– TransformaEon

Page 51: Hacking Movable Type Training - Day 1

Page

Object‐LevelCallbacks

• Events:–MT::ObjectName::pre_save

–MT::ObjectName::post_save

–MT::ObjectName::pre_load

–MT::ObjectName::post_load

–MT::ObjectName::pre_remove

–MT::ObjectName::pre_remove_all

–MT::ObjectName::post_remove_all

Page 52: Hacking Movable Type Training - Day 1

Page

AddingaCallback‐config.yaml

name: Good for Nothing Plugin for Movable Typeid: Good4Nothingkey: Good4Nothingauthor_link: http://www.yourwebsite.com/author_name: Your Name Heredescription: This plugin is an example plugin.version: 1.0callbacks: MT::Entry::pre_save: $Example::Example::Plugin::pre_save

Page 53: Hacking Movable Type Training - Day 1

Page

AddingaCallback‐Handler

package Example::Plugin;use strict;

sub pre_save { my ($cb, $obj) = @_; # $cb - holds a reference to the callback object # $obj - holds a reference to the object about # to be saved # do your thing if ($error) { return $cb->error(“Error Message”); }}

Page 54: Hacking Movable Type Training - Day 1

Page

Exercise:AddaCallback

• YourMission:AddarecordtotheMovableTypeAcEvityLog,justaferanentryissaved.

• AboutLogging:

MT->log({ message => "DemoPlugin: an object was saved.", class => 'system', level => MT::Log::INFO() });});

Page 55: Hacking Movable Type Training - Day 1

Page

EndDay1

[email protected]