Brand New API


Movable Type Developers & Designers Conference
              2010.2.5 in Tokyo

            Yuji Takayama,Six Apart
r y!
 u ng
H
Whatʼs brand new?
• Website
• Theme Framework
• Revision History Framework
• User Dashboard
• Everything is UTF-8
• Permission API
• Menu Structure
• Dynamic Publishing
• User Interface
• Custom Fields
What is “Website”?
Website is ...
The root object of the
  Movable Type 5
How can I use the
 website object
use MT::Website;

my $website_id = 1;
my $website =
    MT::Website-
>load($website_id)
    or die;
$website->name(‘New Website’);
$website->save or die;
itʼs easy
use MT::Blog;
use MT::Website;

my $website_id = 1;
my $website =
    MT::Website->load($website_id)
        or die;
my $blog = new MT::Blog;
$website->add_blog($blog);
my $blogs = $website->blogs;
All blogs belongs to
     the website
$website->site_url;
$website->site_path;
$website->name;
$website->description;
like a blog?

  Right.
• The website uses same table as the
  blog.

• The class of the website is “website”,
  also the class of the blog is “blog”.

• The blog has parent_id that means the
  belonging website.
mysql> select blog_id, blog_class, blog_parent_id
from mt_blog;

+---------+------------+----------------+
| blog_id | blog_class | blog_parent_id |
+---------+------------+----------------+
|       1 | website    |           NULL |
|       2 | blog       |              1 |
|       3 | blog       |              1 |
|       4 | blog       |              1 |
|       5 | website    |           NULL |
+---------+------------+----------------+
5 rows in set (0.01 sec)
new template tags
•   MTWebsites                •   MTWebsitePath

•   MTIfWebsite?              •   MTWebsiteTimezone

•   MTWebsiteIfCCLicense      •   MTWebsiteCCLicenseURL

•   MTWebsiteHasBlog          •   MTWebsiteCCLicenseImage

•   MTBlogParentWebsite       •   MTWebsiteFileExtension

•   MTWebsiteIfCommentsOpen   •   MTWebsiteHost

•   MTWebsiteID               •   MTWebsiteRelativeURL

•   MTWebsiteName             •   MTWebsiteThemeID

•   MTWebsiteDescription      •   MTWebsiteCommentCount

•   MTWebsiteLanguage         •   MTWebsitePingCount

•   MTWebsiteURL              •   MTWebsitePageCount
new template tags
•   MTWebsites                •   MTWebsitePath

•   MTIfWebsite?              •   MTWebsiteTimezone

•   MTWebsiteIfCCLicense      •   MTWebsiteCCLicenseURL

•   MTWebsiteHasBlog          •   MTWebsiteCCLicenseImage

•   MTBlogParentWebsite       •   MTWebsiteFileExtension

•   MTWebsiteIfCommentsOpen   •   MTWebsiteHost

•   MTWebsiteID               •   MTWebsiteRelativeURL

•   MTWebsiteName             •   MTWebsiteThemeID

•   MTWebsiteDescription      •   MTWebsiteCommentCount

•   MTWebsiteLanguage         •   MTWebsitePingCount

•   MTWebsiteURL              •   MTWebsitePageCount
Now, Movable Type
has a revision history
   management.
By default, only the entry
and the template use it.
But....
You can use it in your
      plug-in.
package MT::Object::MyModel
use base qw ( MT::Object
MT::Revisable );

__PACKAGE__->install_properties({
    ‘id’ => ‘integer not null
auto_increment’,
    ‘text’ => ‘string(255)
revisioned’
    # ...
});

1;
package MT::Object::MyModel
use base qw ( MT::Object
MT::Revisable );

__PACKAGE__->install_properties({
    ‘id’ => ‘integer not null
auto_increment’,
    ‘text’ => ‘string(255)
revisioned’
    # ...
});

1;
package MT::Object::MyModel
use base qw ( MT::Object
MT::Revisable );

__PACKAGE__->install_properties({
    ‘id’ => ‘integer not null
auto_increment’,
    ‘text’ => ‘string(255)
revisioned’
    # ...
});

1;
itʼs easy
Movable Type does
 save a revision
  automatically.
If your object related
    to other object
You must override
 ʻpack_revisionʼ and
  ʻunpack_revisionʼ
method on your object.
sub pack_revision {
    my $obj = shift;
    my $values = MT::Revisable::pack_revision( $obj );

    # add category placements and tag associations
    my ( @tags, @cats );
    if ( my $tags = $obj->get_tag_objects ) {
        @tags = map { $_->id } @$tags
            if @$tags;
    }
    # a revision may remove all the tags
    $values->{__rev_tags} = @tags;

    my $primary = $obj->category;
    if ( my $cats = $obj->categories ) {
        @cats = map { [
            $_->id,
            $_->id == $primary->id ? 1 : 0
        ] } @$cats
            if @$cats;
    }
    # a revision may remove all the categories
    $values->{__rev_cats} = @cats;

    $values;
}
}

sub unpack_revision {                             if ( my $rev_cats = delete $packed_obj-
    my $obj = shift;                          >{__rev_cats} ) {
    my ($packed_obj) = @_;                            $obj->clear_cache('category');
    MT::Revisable::unpack_revision( $obj,             $obj->clear_cache('categories');
@_ );
                                                      my ( $cat, @cats );
    # restore category placements and tag             if ( @$rev_cats ) {
associations                                              my ($primary) = grep { $_->[1] }
    if ( my $rev_tags = delete $packed_obj-   @$rev_cats;
>{__rev_tags} ) {                                         $cat = MT::Category-
        delete $obj->{__tags};                >lookup( $primary->[0] );
        delete $obj->{__tag_objects};                     my $cats = MT::Category-
        MT::Tag->clear_cache(datasource =>    >lookup_multi([ map { $_->[0] } @
$obj->datasource,                             $rev_cats ]);
             ($obj->blog_id ? (blog_id =>                 my @cats = sort { $a->label cmp
$obj->blog_id) : ()));                        $b->label } grep { defined } @$cats;
                                                          $obj->{__missing_cats_rev} = 1
        require MT::Memcached;                                 if scalar( @cats ) !=
        MT::Memcached->instance-              scalar( @$cats );
>delete( $obj->tag_cache_key );                       }
                                                      $obj->cache_property( 'category',
        if ( @$rev_tags ) {                   undef, $cat );
            my $lookups = MT::Tag-                    $obj->cache_property( 'categories',
>lookup_multi($rev_tags);                     undef, @cats );
            my @tags = grep { defined } @         }
$lookups;                                     }
            $obj->{__tags} = [ map { $_-
>name } @tags ];
            $obj->{__tag_objects} = @tags;
            $obj->{__missing_tags_rev} = 1
                 if scalar( @tags ) !=
scalar( @$lookups );
        }
        else {
            $obj->{__tags} = [];
            $obj->{__tag_objects} = [];
        }
See MT::Entry
perldoc MT::Revisable
Itʼs your Home to start
       all actions.
Also, you can add
your own widget here
widgets:
  FeedsWidget:
  label: Feed Aggregate
  template: tmpl/widget.tmpl
  handler:
$FeedWidget::Widget::hdlr_widget
  set: main
  singular: 1
  view: blog
widgets:
  FeedsWidget:
  label: Feed Aggregate
  template: tmpl/widget.tmpl
  handler:
$FeedWidget::Widget::hdlr_widget
  set: main
  singular: 1
  view: blog
widgets:
  FeedsWidget:
  label: Feed Aggregate
  template: tmpl/widget.tmpl
  handler:
$FeedWidget::Widget::hdlr_widget
  set: main
  singular: 1
  view: blog
widgets:
  FeedsWidget:
  label: Feed Aggregate
  template: tmpl/widget.tmpl
  handler:
$FeedWidget::Widget::hdlr_widget
  set: main
  singular: 1
  view: blog
widgets:
  FeedsWidget:
  label: Feed Aggregate
  template: tmpl/widget.tmpl
  handler:
$FeedWidget::Widget::hdlr_widget
  set: main
  singular: 1
  view: blog
Everything is UTF-8
Now, all strings in the
 Movable Type 5 is
   utf-8 flagged.
before
Movable Type 5
You must encode object
       by yourself
  if PublishCharset is
       not UTF-8.
sub _hdlr_my_tag {
    my ( $ctx, $args ) = @_;
    my $obj = MT::Entry->load(
        $args->{id});
    my $data = $obj->text;

    # do something...

    return MT::I18N::encode_text(
        $data, ‘utf-8’ );
}
sub _hdlr_my_tag {
    my ( $ctx, $args ) = @_;
    my $obj = MT::Entry->load(
        $args->{id});
    my $data = $obj->text;

    # do something...

    return MT::I18N::encode_text(
        $data, ‘utf-8’ );
}
from now,
You are freed from
obligation of Encode.
sub _hdlr_my_tag {
    my ( $ctx, $args ) = @_;
    my $obj = MT::Entry->load(
        $args->{id});
    my $data = $obj->text;

    # do something...

    return $data;
}
You must
encode/decode
 your own data
    when...
• Communicating with an external
  network.

• File input/output without MT::FileMgr.
• Saving valuesto columns declared in
  MT::Object blob format.
sub _hdlr_my_tag {
    my ( $ctx, $args ) = @_;
    my $data;

    # received from web service.

    return Encode::decode_utf8(
        $data );
}
sub _hdlr_my_tag {
    my ( $ctx, $args ) = @_;
    my $data;

    # received from web service.

    return Encode::decode_utf8(
        $data );
}
Weʼve aimed to...


• easy to understanding
An user who has ‘manage_pages’
permission. Which actions this
user can do?
Movable Type 4...
  $app->can_manage_pages();

Movable Type 5...
  $app->can_do(
‘remove_all_trackbacks_on_webpages’
  );

manage_pages:
 permitted_action:
  remove_all_trackbacks_on_webpages: 1
See MT::Core
load_core_permissions
Weʼve aimed to...


• easy to understanding
• Can be extensible
permissions:
   blog.your_permission:
       group: blog_admin
       label: Your New Permission
       order: 350
       permitted_action:
           your_action: 1
           your_other_action: 1
Specify the role group.


• blog_admin
• auth_pub           • sys_admin
• blog_upload          (only system
                       level)
• blog_comment
• blog_design
label
The display name of the permission.
order
Ordering the permission in its role group
permitted_action
Hash to define a list of actions permitted for hte
use who has this permission.
inherit_from
A list of inheritance origins for this permission.
Defined by references to the list.
Of course, you can
add your menu by
      plugin.
applications:
  cms:
    menus:
       tools:my_menu:
         label: Your Menu Label
         mode: your_mode
         order: 150
         view: blog
You can display your
   menu on any
     dashboard
applications:
  cms:
    menus:
       tools:my_menu:
         label: Your Menu Label
         mode: your_mode
         order: 150
         view: blog
applications:
  cms:
    menus:
       tools:my_menu:
         label: Your Menu Label
         mode: your_mode
         order: 150
         view: blog
You can restrict your
menu by permission.
permissions:
   blog.your_permission:
       permitted_action:
           your_action: 1
applications:
 cms:
  menus:
   tools:my_menu:
    label: Your Menu Label
    mode: your_mode
    order: 150
    view: blog
    permit_action: your_action
If your plugin still
supports MT4 and MT5
menus:
 create:my_object:
  condition: >
  sub {
    MT->product_version < 5; }
 entries:create:
  condition: >
  sub {
    MT->product_version >= 5; }
jquery
and... jquery-ui Ready.
CSS
More detail...

http://www.slideshare.net/
   swordbreaker/plugin
Thank you for listening.

MTDDC 2010.2.5 Tokyo - Brand new API

  • 2.
    Brand New API MovableType Developers & Designers Conference 2010.2.5 in Tokyo Yuji Takayama,Six Apart
  • 3.
    r y! ung H
  • 4.
  • 5.
    • Website • ThemeFramework • Revision History Framework • User Dashboard
  • 6.
    • Everything isUTF-8 • Permission API • Menu Structure • Dynamic Publishing • User Interface • Custom Fields
  • 8.
  • 9.
  • 10.
    The root objectof the Movable Type 5
  • 11.
    How can Iuse the website object
  • 12.
    use MT::Website; my $website_id= 1; my $website = MT::Website- >load($website_id) or die; $website->name(‘New Website’); $website->save or die;
  • 13.
  • 14.
    use MT::Blog; use MT::Website; my$website_id = 1; my $website = MT::Website->load($website_id) or die; my $blog = new MT::Blog; $website->add_blog($blog); my $blogs = $website->blogs;
  • 15.
    All blogs belongsto the website
  • 16.
  • 17.
  • 18.
    • The websiteuses same table as the blog. • The class of the website is “website”, also the class of the blog is “blog”. • The blog has parent_id that means the belonging website.
  • 19.
    mysql> select blog_id,blog_class, blog_parent_id from mt_blog; +---------+------------+----------------+ | blog_id | blog_class | blog_parent_id | +---------+------------+----------------+ | 1 | website | NULL | | 2 | blog | 1 | | 3 | blog | 1 | | 4 | blog | 1 | | 5 | website | NULL | +---------+------------+----------------+ 5 rows in set (0.01 sec)
  • 20.
    new template tags • MTWebsites • MTWebsitePath • MTIfWebsite? • MTWebsiteTimezone • MTWebsiteIfCCLicense • MTWebsiteCCLicenseURL • MTWebsiteHasBlog • MTWebsiteCCLicenseImage • MTBlogParentWebsite • MTWebsiteFileExtension • MTWebsiteIfCommentsOpen • MTWebsiteHost • MTWebsiteID • MTWebsiteRelativeURL • MTWebsiteName • MTWebsiteThemeID • MTWebsiteDescription • MTWebsiteCommentCount • MTWebsiteLanguage • MTWebsitePingCount • MTWebsiteURL • MTWebsitePageCount
  • 21.
    new template tags • MTWebsites • MTWebsitePath • MTIfWebsite? • MTWebsiteTimezone • MTWebsiteIfCCLicense • MTWebsiteCCLicenseURL • MTWebsiteHasBlog • MTWebsiteCCLicenseImage • MTBlogParentWebsite • MTWebsiteFileExtension • MTWebsiteIfCommentsOpen • MTWebsiteHost • MTWebsiteID • MTWebsiteRelativeURL • MTWebsiteName • MTWebsiteThemeID • MTWebsiteDescription • MTWebsiteCommentCount • MTWebsiteLanguage • MTWebsitePingCount • MTWebsiteURL • MTWebsitePageCount
  • 25.
    Now, Movable Type hasa revision history management.
  • 26.
    By default, onlythe entry and the template use it.
  • 27.
  • 28.
    You can useit in your plug-in.
  • 29.
    package MT::Object::MyModel use baseqw ( MT::Object MT::Revisable ); __PACKAGE__->install_properties({ ‘id’ => ‘integer not null auto_increment’, ‘text’ => ‘string(255) revisioned’ # ... }); 1;
  • 30.
    package MT::Object::MyModel use baseqw ( MT::Object MT::Revisable ); __PACKAGE__->install_properties({ ‘id’ => ‘integer not null auto_increment’, ‘text’ => ‘string(255) revisioned’ # ... }); 1;
  • 31.
    package MT::Object::MyModel use baseqw ( MT::Object MT::Revisable ); __PACKAGE__->install_properties({ ‘id’ => ‘integer not null auto_increment’, ‘text’ => ‘string(255) revisioned’ # ... }); 1;
  • 32.
  • 33.
    Movable Type does save a revision automatically.
  • 34.
    If your objectrelated to other object
  • 35.
    You must override ʻpack_revisionʼ and ʻunpack_revisionʼ method on your object.
  • 36.
    sub pack_revision { my $obj = shift; my $values = MT::Revisable::pack_revision( $obj ); # add category placements and tag associations my ( @tags, @cats ); if ( my $tags = $obj->get_tag_objects ) { @tags = map { $_->id } @$tags if @$tags; } # a revision may remove all the tags $values->{__rev_tags} = @tags; my $primary = $obj->category; if ( my $cats = $obj->categories ) { @cats = map { [ $_->id, $_->id == $primary->id ? 1 : 0 ] } @$cats if @$cats; } # a revision may remove all the categories $values->{__rev_cats} = @cats; $values; }
  • 37.
    } sub unpack_revision { if ( my $rev_cats = delete $packed_obj- my $obj = shift; >{__rev_cats} ) { my ($packed_obj) = @_; $obj->clear_cache('category'); MT::Revisable::unpack_revision( $obj, $obj->clear_cache('categories'); @_ ); my ( $cat, @cats ); # restore category placements and tag if ( @$rev_cats ) { associations my ($primary) = grep { $_->[1] } if ( my $rev_tags = delete $packed_obj- @$rev_cats; >{__rev_tags} ) { $cat = MT::Category- delete $obj->{__tags}; >lookup( $primary->[0] ); delete $obj->{__tag_objects}; my $cats = MT::Category- MT::Tag->clear_cache(datasource => >lookup_multi([ map { $_->[0] } @ $obj->datasource, $rev_cats ]); ($obj->blog_id ? (blog_id => my @cats = sort { $a->label cmp $obj->blog_id) : ())); $b->label } grep { defined } @$cats; $obj->{__missing_cats_rev} = 1 require MT::Memcached; if scalar( @cats ) != MT::Memcached->instance- scalar( @$cats ); >delete( $obj->tag_cache_key ); } $obj->cache_property( 'category', if ( @$rev_tags ) { undef, $cat ); my $lookups = MT::Tag- $obj->cache_property( 'categories', >lookup_multi($rev_tags); undef, @cats ); my @tags = grep { defined } @ } $lookups; } $obj->{__tags} = [ map { $_- >name } @tags ]; $obj->{__tag_objects} = @tags; $obj->{__missing_tags_rev} = 1 if scalar( @tags ) != scalar( @$lookups ); } else { $obj->{__tags} = []; $obj->{__tag_objects} = []; }
  • 38.
  • 40.
  • 43.
    Itʼs your Hometo start all actions.
  • 44.
    Also, you canadd your own widget here
  • 45.
    widgets: FeedsWidget: label: Feed Aggregate template: tmpl/widget.tmpl handler: $FeedWidget::Widget::hdlr_widget set: main singular: 1 view: blog
  • 46.
    widgets: FeedsWidget: label: Feed Aggregate template: tmpl/widget.tmpl handler: $FeedWidget::Widget::hdlr_widget set: main singular: 1 view: blog
  • 47.
    widgets: FeedsWidget: label: Feed Aggregate template: tmpl/widget.tmpl handler: $FeedWidget::Widget::hdlr_widget set: main singular: 1 view: blog
  • 48.
    widgets: FeedsWidget: label: Feed Aggregate template: tmpl/widget.tmpl handler: $FeedWidget::Widget::hdlr_widget set: main singular: 1 view: blog
  • 49.
    widgets: FeedsWidget: label: Feed Aggregate template: tmpl/widget.tmpl handler: $FeedWidget::Widget::hdlr_widget set: main singular: 1 view: blog
  • 53.
  • 54.
    Now, all stringsin the Movable Type 5 is utf-8 flagged.
  • 55.
  • 56.
    You must encodeobject by yourself if PublishCharset is not UTF-8.
  • 57.
    sub _hdlr_my_tag { my ( $ctx, $args ) = @_; my $obj = MT::Entry->load( $args->{id}); my $data = $obj->text; # do something... return MT::I18N::encode_text( $data, ‘utf-8’ ); }
  • 58.
    sub _hdlr_my_tag { my ( $ctx, $args ) = @_; my $obj = MT::Entry->load( $args->{id}); my $data = $obj->text; # do something... return MT::I18N::encode_text( $data, ‘utf-8’ ); }
  • 59.
  • 60.
    You are freedfrom obligation of Encode.
  • 61.
    sub _hdlr_my_tag { my ( $ctx, $args ) = @_; my $obj = MT::Entry->load( $args->{id}); my $data = $obj->text; # do something... return $data; }
  • 62.
  • 63.
    • Communicating withan external network. • File input/output without MT::FileMgr. • Saving valuesto columns declared in MT::Object blob format.
  • 64.
    sub _hdlr_my_tag { my ( $ctx, $args ) = @_; my $data; # received from web service. return Encode::decode_utf8( $data ); }
  • 65.
    sub _hdlr_my_tag { my ( $ctx, $args ) = @_; my $data; # received from web service. return Encode::decode_utf8( $data ); }
  • 67.
    Weʼve aimed to... •easy to understanding
  • 68.
    An user whohas ‘manage_pages’ permission. Which actions this user can do?
  • 69.
    Movable Type 4... $app->can_manage_pages(); Movable Type 5... $app->can_do( ‘remove_all_trackbacks_on_webpages’ ); manage_pages: permitted_action: remove_all_trackbacks_on_webpages: 1
  • 71.
  • 72.
    Weʼve aimed to... •easy to understanding • Can be extensible
  • 73.
    permissions: blog.your_permission: group: blog_admin label: Your New Permission order: 350 permitted_action: your_action: 1 your_other_action: 1
  • 75.
    Specify the rolegroup. • blog_admin • auth_pub • sys_admin • blog_upload (only system level) • blog_comment • blog_design
  • 76.
    label The display nameof the permission.
  • 77.
  • 78.
    permitted_action Hash to definea list of actions permitted for hte use who has this permission.
  • 79.
    inherit_from A list ofinheritance origins for this permission. Defined by references to the list.
  • 84.
    Of course, youcan add your menu by plugin.
  • 85.
    applications: cms: menus: tools:my_menu: label: Your Menu Label mode: your_mode order: 150 view: blog
  • 86.
    You can displayyour menu on any dashboard
  • 87.
    applications: cms: menus: tools:my_menu: label: Your Menu Label mode: your_mode order: 150 view: blog
  • 88.
    applications: cms: menus: tools:my_menu: label: Your Menu Label mode: your_mode order: 150 view: blog
  • 90.
    You can restrictyour menu by permission.
  • 91.
    permissions: blog.your_permission: permitted_action: your_action: 1 applications: cms: menus: tools:my_menu: label: Your Menu Label mode: your_mode order: 150 view: blog permit_action: your_action
  • 92.
    If your pluginstill supports MT4 and MT5
  • 93.
    menus: create:my_object:   condition:>   sub { MT->product_version < 5; }  entries:create:   condition: >   sub { MT->product_version >= 5; }
  • 95.
  • 100.
  • 101.
  • 109.
  • 110.
    Thank you forlistening.

Editor's Notes

  • #21 &amp;#x30A6;&amp;#x30A7;&amp;#x30D6;&amp;#x30B5;&amp;#x30A4;&amp;#x30C8;&amp;#x95A2;&amp;#x4FC2;&amp;#x3060;&amp;#x3051;&amp;#x3067;&amp;#x3053;&amp;#x308C;&amp;#x3060;&amp;#x3051;&amp;#x306E;&amp;#x30BF;&amp;#x30B0;&amp;#x304C;&amp;#x8FFD;&amp;#x52A0;&amp;#x3055;&amp;#x308C;&amp;#x3066;&amp;#x3044;&amp;#x307E;&amp;#x3059;&amp;#x304C;&amp;#x3001;&amp;#x30B5;&amp;#x30A4;&amp;#x30C8;&amp;#x3092;&amp;#x898B;&amp;#x3066;&amp;#x3044;&amp;#x305F;&amp;#x3060;&amp;#x3044;&amp;#x305F;&amp;#x65B9;&amp;#x304C;&amp;#x65E9;&amp;#x3044;&amp;#x304B;&amp;#x3068;&amp;#x601D;&amp;#x3044;&amp;#x307E;&amp;#x3059;
  • #23 &amp;#x5272;&amp;#x611B;&amp;#x3057;&amp;#x307E;&amp;#x3059;