From 4bb9a9080e809187d5c84d4c4bd3e8a718cf8be7 Mon Sep 17 00:00:00 2001 From: Jay Allen Date: Thu, 17 Dec 2009 14:23:37 -0800 Subject: [PATCH 01/10] Creating a repository for the Order plugin, v1.1 --- plugins/Order/config.yaml | 14 +++ plugins/Order/lib/Order/Plugin.pm | 143 ++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 plugins/Order/config.yaml create mode 100644 plugins/Order/lib/Order/Plugin.pm diff --git a/plugins/Order/config.yaml b/plugins/Order/config.yaml new file mode 100644 index 0000000..4616a1f --- /dev/null +++ b/plugins/Order/config.yaml @@ -0,0 +1,14 @@ +name: Order +id: Order +key: Order +description: Collect sets of template output to order by a particular datum. +author_name: Mark Paschal +author_link: http://markpasc.org/mark/ +plugin_link: http://plugins.movabletype.org/order/ +version: 1.1 +tags: + block: + Order: $Order::Order::Plugin::tag_order + OrderItem: $Order::Order::Plugin::tag_order_item + OrderHeader: $Order::Order::Plugin::tag_order_header + OrderFooter: $Order::Order::Plugin::tag_order_footer diff --git a/plugins/Order/lib/Order/Plugin.pm b/plugins/Order/lib/Order/Plugin.pm new file mode 100644 index 0000000..ed8d737 --- /dev/null +++ b/plugins/Order/lib/Order/Plugin.pm @@ -0,0 +1,143 @@ + +package Order::Plugin; + +sub _natural_sort { + sort { + $a->[0] =~ m{ \A [+-]? \d+ }xms && $b->[0] =~ m{ \A [+-]? \d+ }xms + ? $a->[0] <=> $b->[0] + : lc $a->[0] cmp lc $b->[0] + } @_; +} + +sub _regular_sort { + sort { lc $a->[0] cmp lc $b->[0] } @_; +} + +sub _reverse_sort { + sort { lc $b->[0] cmp lc $a->[0] } @_; +} + +sub sort_function_for_args { + my ($args) = @_; + + my $descend = !$args->{sort_order} ? 1 + : $args->{sort_order} eq 'ascend' ? 0 + : 1 + ; + + my $sort; + if ($args->{natural}) { + $sort = $descend ? sub { reverse _natural_sort(@_) } + : \&_natural_sort + ; + } + elsif ($args->{shuffle}) { + require List::Util; + $sort = \&List::Util::shuffle; + } + else { + $sort = $descend ? \&_reverse_sort : \&_regular_sort; + } + + return $sort; +} + +sub _sort_group_ids { + return $a < 0 && 0 < $b ? 1 + : $b < 0 && 0 < $a ? -1 + : $a < 0 ? $b <=> $a + : $a <=> $b + ; +} + +sub tag_order { + my ($ctx, $args, $cond) = @_; + + my %groups = ( items => [] ); + local $ctx->{__stash}{order_items} = \%groups; + local $ctx->{__stash}{order_by_var} = $args->{by} || 'order_by'; + local $ctx->{__stash}{order_header} = q{}; + local $ctx->{__stash}{order_footer} = q{}; + + # Build, but ignore the full build value. + defined($ctx->slurp($args, $cond)) + or return; + + # Ready the regular group of items. + my $items = delete $groups{items}; + my $sort = sort_function_for_args($args); + my @objs = $sort->(@$items); + + # Inject the pinned groups from first place (0) to last (-1). + for my $i (sort _sort_group_ids keys %groups) { + my $items = $groups{$i}; + # TODO: sort and join the group, so it splices as one item, disrupting + # the next groups less? but then they only count as one item for + # offsets and limits. + if ($i >= 0) { + splice @objs, $i, 0, $sort->(@$items); + } + elsif ($i < -1) { + splice @objs, $i + 1, 0, $sort->(@$items); + } + else { + push @objs, $sort->(@$items); + } + } + + # Collapse the transform. + @objs = map { $_->[1] } @objs; + + if (my $offset = $args->{offset}) { + # Delete the first $offset items. + splice @objs, 0, $offset; + } + + if (my $limit = ($args->{lastn} || $args->{limit})) { + if (scalar @objs > $limit) { + # Keep the first $limit items. + splice @objs, $limit; + } + } + + return q{} if !@objs; + return join q{}, $ctx->stash('order_header'), @objs, + $ctx->stash('order_footer'); +} + +sub tag_order_header { + my ($ctx, $args, $cond) = @_; + my $output = $ctx->slurp($args, $cond) + or return; + $ctx->stash('order_header', $output); + return q{}; +} + +sub tag_order_footer { + my ($ctx, $args, $cond) = @_; + my $output = $ctx->slurp($args, $cond) + or return; + $ctx->stash('order_footer', $output); + return q{}; +} + +sub tag_order_item { + my ($ctx, $args, $cond) = @_; + + my $group_id = defined $args->{pin} ? int $args->{pin} : 'items'; + + my $order_var = $ctx->stash('order_by_var'); + local $ctx->{__stash}{vars}{$order_var}; + my $output = $ctx->slurp($args, $cond) + or return; + + my $order_value = $ctx->var($order_var) || q{}; + $order_value =~ s{ \A \s+ | \s+ \z }{}xmsg; + + my $groups = $ctx->stash('order_items'); + my $group = ($groups->{$group_id} ||= []); + push @$group, [ $order_value, $output ]; +} + +1; + From f220f103837a2130285826eaeb16356801e85357 Mon Sep 17 00:00:00 2001 From: Charlie Gorichanaz Date: Tue, 24 May 2011 22:03:28 -0500 Subject: [PATCH 02/10] NOT IN A WORKABLE STATE: Pushing to GitHub to consult with plugin author Signed-off-by: Charlie Gorichanaz --- LICENSE | 2 +- Makefile.PL | 2 +- README.markdown | 29 +++++++++++++--- plugins/Order/config.yaml | 4 ++- plugins/Order/lib/Order/Plugin.pm | 55 +++++++++++++++++++++++++++---- 5 files changed, 79 insertions(+), 13 deletions(-) diff --git a/LICENSE b/LICENSE index 2f290a2..7217050 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Order 1.1 for Movable Type +Order 1.2 for Movable Type Copyright 2008-2009 Six Apart, Ltd. All rights reserved. diff --git a/Makefile.PL b/Makefile.PL index 77983d7..046ad70 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -2,6 +2,6 @@ use ExtUtils::MakeMaker; WriteMakefile( NAME => 'Order', - VERSION => '1.1', + VERSION => '1.2', DISTNAME => 'Order', ); diff --git a/README.markdown b/README.markdown index 2f2802c..af2c1c8 100644 --- a/README.markdown +++ b/README.markdown @@ -1,4 +1,4 @@ -# Order 1.1 for Movable Type # +# Order 1.2 for Movable Type # Collect sets of template output to order by a particular datum. @@ -13,6 +13,8 @@ Unarchive into your Movable Type directory. Use the provided template tags to collect and reorder template content. For example: +UPDATE THIS EXAMPLE TO USE DATEHEADER/FOOTER + @@ -113,7 +115,7 @@ set inside the `mt:OrderItem` tag. Set the `order_by` variable by using the `mt:SetVarBlock` tag or the `setvar="variable name"` global attribute on a tag inside the `mt:OrderItem`. -`mt:OrderItem` has one optional attribute: +`mt:OrderItem` has two optional attributes: ### `pin` ### @@ -157,13 +159,32 @@ even an `mt:OrderItem` pinned to the front with the `pin="0"` attribute. Contains template content that is displayed at the end of the `mt:Order` loop, as long as there are `mt:OrderItem`s to display. -Content from an `mt:OrderFooter` is shown after the last `mt:OrderItem`, or +Content from an `mt:OrderFooter` is shown after the last `mt:OrderItem`, even an `mt:OrderItem` pinned to the end with the `pin="-1"` attribute. +## `mt:OrderDateHeader` ## + +A container tag whose contents will be displayed before the `mt:OrderItem` in context +if it is the first item for a given day. Requires `order_by` variable set inside the +`mt:OrderItem` tag to be an `iso8601` timestamp, formatted `%Y-%m-%dT%H:%M:%SZ`. + + +## `mt:OrderDateFooter` ## + +A container tag whose contents will be displayed after the `mt:OrderItem` in context +if it is the last item for a given day. Requires `order_by` variable set inside the +`mt:OrderItem` tag to be an `iso8601` timestamp, formatted `%Y-%m-%dT%H:%M:%SZ`. + + # Changes # -## 1.1 in development ## +## 1.2 10 May 2011 ## + +* Added `unique` ordering option. + + +## 1.1 10 June 2010 ## * Added `mt:OrderHeader` and `mt:OrderFooter` tags. * Added `shuffle` ordering option. diff --git a/plugins/Order/config.yaml b/plugins/Order/config.yaml index 4616a1f..46181f2 100644 --- a/plugins/Order/config.yaml +++ b/plugins/Order/config.yaml @@ -5,10 +5,12 @@ description: Collect sets of template output to order by a particular datum. author_name: Mark Paschal author_link: http://markpasc.org/mark/ plugin_link: http://plugins.movabletype.org/order/ -version: 1.1 +version: 1.2 tags: block: Order: $Order::Order::Plugin::tag_order OrderItem: $Order::Order::Plugin::tag_order_item OrderHeader: $Order::Order::Plugin::tag_order_header OrderFooter: $Order::Order::Plugin::tag_order_footer + OrderDateHeader: $Order::Order::Plugin::tag_order_date_header + OrderDateFooter: $Order::Order::Plugin::tag_order_date_footer diff --git a/plugins/Order/lib/Order/Plugin.pm b/plugins/Order/lib/Order/Plugin.pm index ed8d737..c147499 100644 --- a/plugins/Order/lib/Order/Plugin.pm +++ b/plugins/Order/lib/Order/Plugin.pm @@ -52,7 +52,7 @@ sub _sort_group_ids { sub tag_order { my ($ctx, $args, $cond) = @_; - + my %groups = ( items => [] ); local $ctx->{__stash}{order_items} = \%groups; local $ctx->{__stash}{order_by_var} = $args->{by} || 'order_by'; @@ -67,7 +67,7 @@ sub tag_order { my $items = delete $groups{items}; my $sort = sort_function_for_args($args); my @objs = $sort->(@$items); - + # Inject the pinned groups from first place (0) to last (-1). for my $i (sort _sort_group_ids keys %groups) { my $items = $groups{$i}; @@ -84,7 +84,13 @@ sub tag_order { push @objs, $sort->(@$items); } } - + + # Mark said to put header/footer logic here, but I put further down + # so limiting and offsets could be taken care of first. We don't want + # to break styles dependent on the header and footer being in place. + + # But now I realize we lost the date information by the collapse... + # Collapse the transform. @objs = map { $_->[1] } @objs; @@ -100,6 +106,28 @@ sub tag_order { } } + # $objs[x] is OrderItem content + + # loop over items in @objs adding headers and footers where necessary + if ($ctx->stash('order_date_header') || $ctx->stash('order_date_footer')) { + MT::log("$#objs"); + MT::log($objs[0]); MT::log($objs[1]); MT::log($objs[2]); + + my $current_date; # hold date to compare against + + if ($ctx->stash('order_date_header')) { + # I don't know how to properly slurp() on the next line to get it to + # use the current order item's context. + # unshift(@objs, $ctx->stash('order_date_header')); + } + + } + + { + my $debug6 = 1; + MT::log('Order plugin ran at '.scalar localtime()) if ($debug6); + } + return q{} if !@objs; return join q{}, $ctx->stash('order_header'), @objs, $ctx->stash('order_footer'); @@ -121,9 +149,21 @@ sub tag_order_footer { return q{}; } -sub tag_order_item { +sub tag_order_date_header { my ($ctx, $args, $cond) = @_; + $ctx->stash('order_date_header', $ctx->stash('tokens')); + return q{}; +} + +sub tag_order_date_footer { + my ($ctx, $args, $cond) = @_; + $ctx->stash('order_date_footer', $ctx->stash('tokens')); + return q{}; +} +sub tag_order_item { + my ($ctx, $args, $cond) = @_; + my $group_id = defined $args->{pin} ? int $args->{pin} : 'items'; my $order_var = $ctx->stash('order_by_var'); @@ -133,10 +173,13 @@ sub tag_order_item { my $order_value = $ctx->var($order_var) || q{}; $order_value =~ s{ \A \s+ | \s+ \z }{}xmsg; - + + my $is_unique = defined $args->{unique} ? true : false; + my $groups = $ctx->stash('order_items'); my $group = ($groups->{$group_id} ||= []); - push @$group, [ $order_value, $output ]; + push @$group, [ $order_value, $output, $is_unique ]; + } 1; From d16441bd4d0d0c13f67aaabb7bb6126c642623fb Mon Sep 17 00:00:00 2001 From: Charlie Gorichanaz Date: Thu, 26 May 2011 01:51:47 -0500 Subject: [PATCH 03/10] NOT WORKABLE, in progress Signed-off-by: Charlie Gorichanaz --- plugins/Order/lib/Order/Plugin.pm | 67 +++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/plugins/Order/lib/Order/Plugin.pm b/plugins/Order/lib/Order/Plugin.pm index c147499..05bb6a2 100644 --- a/plugins/Order/lib/Order/Plugin.pm +++ b/plugins/Order/lib/Order/Plugin.pm @@ -85,15 +85,6 @@ sub tag_order { } } - # Mark said to put header/footer logic here, but I put further down - # so limiting and offsets could be taken care of first. We don't want - # to break styles dependent on the header and footer being in place. - - # But now I realize we lost the date information by the collapse... - - # Collapse the transform. - @objs = map { $_->[1] } @objs; - if (my $offset = $args->{offset}) { # Delete the first $offset items. splice @objs, 0, $offset; @@ -106,23 +97,55 @@ sub tag_order { } } - # $objs[x] is OrderItem content + # $objs[x][0] is YYYYMMDDhhmmss + # $objs[x][1] is OrderItem content + # $objs[x][2] is 0||1 - # loop over items in @objs adding headers and footers where necessary if ($ctx->stash('order_date_header') || $ctx->stash('order_date_footer')) { - MT::log("$#objs"); - MT::log($objs[0]); MT::log($objs[1]); MT::log($objs[2]); - - my $current_date; # hold date to compare against - - if ($ctx->stash('order_date_header')) { - # I don't know how to properly slurp() on the next line to get it to - # use the current order item's context. - # unshift(@objs, $ctx->stash('order_date_header')); + # loop over items in @objs adding headers and footers where necessary + my ($yesterday, $tomorrow) = ('00000000')x2; + my $i = 0; + for my $o (@objs) { + my $today = substr $o->[0], 0, 8; + my $tomorrow = $today; + my $footer = 0; + if (defined $objs[$i+1]) { + $tomorrow = substr($objs[$i+1]->[0], 0, 8); + $footer = $today ne $tomorrow; + } else { + $footer++; + } + my $header = $today ne $yesterday; + $ctx->{current_timestamp} = $o->[0]; + my ($h_html, $f_html) = ('')x2; + if ($header && $ctx->stash('order_date_header')) { + $h_html = $ctx->stash('builder')->build($ctx, $ctx->stash('order_date_header'), {}); + } + if ($footer && $ctx->stash('order_date_footer')) { + $f_html = $ctx->stash('builder')->build($ctx, $ctx->stash('order_date_footer'), {}); + } + + MT::log("$h_html ### $f_html"); + $yesterday = $today; + $i++; } - } +#sub slurp { +# my ( $ctx, $args, $cond ) = @_; +# my $tokens = $ctx->stash('tokens'); +# return '' unless $tokens; +# my $result = $ctx->stash('builder')->build( $ctx, $tokens, $cond ); +# return $ctx->error( $ctx->stash('builder')->errstr ) +# unless defined $result; +# return $result; +#} + + + + # Collapse the transform. + @objs = map { $_->[1] } @objs; + { my $debug6 = 1; MT::log('Order plugin ran at '.scalar localtime()) if ($debug6); @@ -174,7 +197,7 @@ sub tag_order_item { my $order_value = $ctx->var($order_var) || q{}; $order_value =~ s{ \A \s+ | \s+ \z }{}xmsg; - my $is_unique = defined $args->{unique} ? true : false; + my $is_unique = defined $args->{unique} ? 1 : 0; my $groups = $ctx->stash('order_items'); my $group = ($groups->{$group_id} ||= []); From cf3536117c6691d7b7cd83a358e80c5c066ffdc9 Mon Sep 17 00:00:00 2001 From: Charlie Gorichanaz Date: Thu, 26 May 2011 21:48:40 -0500 Subject: [PATCH 04/10] Plugin is functional. Added `unique` attribute. `OrderDateHeader` and `OrderDateFooter` tags don't have correct Date contexts set up yet. Pushing to GitHub to consult Mark Paschal, the plugin author. Signed-off-by: Charlie Gorichanaz --- README.markdown | 42 ++++++++----- plugins/Order/lib/Order/Plugin.pm | 98 ++++++++++++++++--------------- 2 files changed, 80 insertions(+), 60 deletions(-) diff --git a/README.markdown b/README.markdown index af2c1c8..4292ed9 100644 --- a/README.markdown +++ b/README.markdown @@ -11,18 +11,25 @@ Unarchive into your Movable Type directory. # Usage # Use the provided template tags to collect and reorder template content. For -example: +example, to show the last 30 unique entries and ActionStreams items: -UPDATE THIS EXAMPLE TO USE DATEHEADER/FOOTER - - +
- - + +
+

+ + + +
+ + + + @@ -30,15 +37,15 @@ UPDATE THIS EXAMPLE TO USE DATEHEADER/FOOTER - - + + - + <$mt:StreamActionDate format="%Y%m%d%H%M%S"$> - +

">_16.png" width="12" height="12"> " class="actionlink">

-
- + +
@@ -144,6 +151,12 @@ attribute is considered. That is, if you order 11 items, pin one to `-1` (last), and use `limit="10"` on the `mt:Order` tag, the pinned item will *not* be shown (it was the eleventh of ten items). +### `unique` ### + +In cases where two or more `mt:OrderItem`s have the same `order_by` value, the +same first 18 characters of content and the attribute `unique` set to the value +`1`, all duplicate `mt:OrderItem`s are removed. + ## `mt:OrderHeader` ## @@ -167,20 +180,21 @@ even an `mt:OrderItem` pinned to the end with the `pin="-1"` attribute. A container tag whose contents will be displayed before the `mt:OrderItem` in context if it is the first item for a given day. Requires `order_by` variable set inside the -`mt:OrderItem` tag to be an `iso8601` timestamp, formatted `%Y-%m-%dT%H:%M:%SZ`. +`mt:OrderItem` tag to be a timestamp formatted `%Y%m%d%H%M%S`. ## `mt:OrderDateFooter` ## A container tag whose contents will be displayed after the `mt:OrderItem` in context if it is the last item for a given day. Requires `order_by` variable set inside the -`mt:OrderItem` tag to be an `iso8601` timestamp, formatted `%Y-%m-%dT%H:%M:%SZ`. +`mt:OrderItem` tag to be a timestamp formatted `%Y%m%d%H%M%S`. # Changes # ## 1.2 10 May 2011 ## +* Added `mt:OrderDateHeader` and `mt:OrderDateFooter` tags. * Added `unique` ordering option. diff --git a/plugins/Order/lib/Order/Plugin.pm b/plugins/Order/lib/Order/Plugin.pm index 05bb6a2..eba254b 100644 --- a/plugins/Order/lib/Order/Plugin.pm +++ b/plugins/Order/lib/Order/Plugin.pm @@ -85,6 +85,22 @@ sub tag_order { } } + # Remove nonunique items if specified + # Unique if unique order_key+first 18 chars of item + # TODO: don't trigger this block if no unique flags set + { + my $j = 0; + my %used; + for my $obj (@objs) { + if ($obj->[2]) { + my $hash = $obj->[0].substr($obj->[1],0,18); + splice (@objs, $j, 1) if exists $used{$hash}; + $used{$hash}++; + } + $j++; + } + } + if (my $offset = $args->{offset}) { # Delete the first $offset items. splice @objs, 0, $offset; @@ -102,55 +118,43 @@ sub tag_order { # $objs[x][2] is 0||1 if ($ctx->stash('order_date_header') || $ctx->stash('order_date_footer')) { - # loop over items in @objs adding headers and footers where necessary - my ($yesterday, $tomorrow) = ('00000000')x2; - my $i = 0; - for my $o (@objs) { - my $today = substr $o->[0], 0, 8; - my $tomorrow = $today; - my $footer = 0; - if (defined $objs[$i+1]) { - $tomorrow = substr($objs[$i+1]->[0], 0, 8); - $footer = $today ne $tomorrow; - } else { - $footer++; + # loop over items in @objs adding headers and footers where necessary + my ($yesterday, $tomorrow) = ('00000000')x2; + my $i = 0; + for my $o (@objs) { + my $today = substr $o->[0], 0, 8; + my $tomorrow = $today; + my $footer = 0; + if (defined $objs[$i+1]) { + $tomorrow = substr($objs[$i+1]->[0], 0, 8); + $footer = $today ne $tomorrow; + } else { + $footer++; + } + my $header = $today ne $yesterday; + $ctx->{current_timestamp} = $o->[0]; + # $args->{ts} = $o->[0]; # TROUBLESHOOTING DATE CONTEXT + my ($h_html, $f_html) = ('')x2; + if ($header && $ctx->stash('order_date_header')) { + my $result = $ctx->stash('builder')->build($ctx, $ctx->stash('order_date_header'), {}); + return $ctx->error( $ctx->stash('builder')->errstr ) unless defined $result; + $h_html = $result; + } + if ($footer && $ctx->stash('order_date_footer')) { + my $result = $ctx->stash('builder')->build($ctx, $ctx->stash('order_date_footer'), {}); + return $ctx->error( $ctx->stash('builder')->errstr ) unless defined $result; + $f_html = $result; + } + $objs[$i][1] = $h_html.$o->[1].$f_html; +MT::log("(".$h_html.") BODY (".$f_html.")"); + $yesterday = $today; + $i++; } - my $header = $today ne $yesterday; - $ctx->{current_timestamp} = $o->[0]; - my ($h_html, $f_html) = ('')x2; - if ($header && $ctx->stash('order_date_header')) { - $h_html = $ctx->stash('builder')->build($ctx, $ctx->stash('order_date_header'), {}); - } - if ($footer && $ctx->stash('order_date_footer')) { - $f_html = $ctx->stash('builder')->build($ctx, $ctx->stash('order_date_footer'), {}); - } - - MT::log("$h_html ### $f_html"); - $yesterday = $today; - $i++; - } } -#sub slurp { -# my ( $ctx, $args, $cond ) = @_; -# my $tokens = $ctx->stash('tokens'); -# return '' unless $tokens; -# my $result = $ctx->stash('builder')->build( $ctx, $tokens, $cond ); -# return $ctx->error( $ctx->stash('builder')->errstr ) -# unless defined $result; -# return $result; -#} - - - # Collapse the transform. @objs = map { $_->[1] } @objs; - { - my $debug6 = 1; - MT::log('Order plugin ran at '.scalar localtime()) if ($debug6); - } - return q{} if !@objs; return join q{}, $ctx->stash('order_header'), @objs, $ctx->stash('order_footer'); @@ -197,7 +201,10 @@ sub tag_order_item { my $order_value = $ctx->var($order_var) || q{}; $order_value =~ s{ \A \s+ | \s+ \z }{}xmsg; - my $is_unique = defined $args->{unique} ? 1 : 0; + my $is_unique = 0; + if (defined $args->{unique} && $args->{unique}) { + $is_unique = 1; + } my $groups = $ctx->stash('order_items'); my $group = ($groups->{$group_id} ||= []); @@ -205,5 +212,4 @@ sub tag_order_item { } -1; - +1; \ No newline at end of file From 21e5e473b12ec193e595678a23e754553e93e847 Mon Sep 17 00:00:00 2001 From: Charlie Gorichanaz Date: Fri, 27 May 2011 03:21:10 -0500 Subject: [PATCH 05/10] Added mt:OrderDate function tag. Signed-off-by: Charlie Gorichanaz --- README.markdown | 9 ++++++++- plugins/Order/config.yaml | 2 ++ plugins/Order/lib/Order/Plugin.pm | 29 +++++++++++++---------------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/README.markdown b/README.markdown index 4292ed9..ad93391 100644 --- a/README.markdown +++ b/README.markdown @@ -21,7 +21,7 @@ example, to show the last 30 unique entries and ActionStreams items:
-

+

@@ -190,11 +190,18 @@ if it is the last item for a given day. Requires `order_by` variable set inside `mt:OrderItem` tag to be a timestamp formatted `%Y%m%d%H%M%S`. +## `mt:OrderDate` ## + +A function tag that works like an `mt:Date` tag, for use within `mt:OrderDateHeader` +and `mt:OrderDateFooter` blocks. + + # Changes # ## 1.2 10 May 2011 ## * Added `mt:OrderDateHeader` and `mt:OrderDateFooter` tags. +* Added `mt:OrderDate` tag. * Added `unique` ordering option. diff --git a/plugins/Order/config.yaml b/plugins/Order/config.yaml index 46181f2..f4da46d 100644 --- a/plugins/Order/config.yaml +++ b/plugins/Order/config.yaml @@ -14,3 +14,5 @@ tags: OrderFooter: $Order::Order::Plugin::tag_order_footer OrderDateHeader: $Order::Order::Plugin::tag_order_date_header OrderDateFooter: $Order::Order::Plugin::tag_order_date_footer + function: + OrderDate: $Core::MT::Template::Context::_hdlr_date diff --git a/plugins/Order/lib/Order/Plugin.pm b/plugins/Order/lib/Order/Plugin.pm index eba254b..66623c2 100644 --- a/plugins/Order/lib/Order/Plugin.pm +++ b/plugins/Order/lib/Order/Plugin.pm @@ -85,15 +85,17 @@ sub tag_order { } } - # Remove nonunique items if specified - # Unique if unique order_key+first 18 chars of item - # TODO: don't trigger this block if no unique flags set - { + my $test_unique = 0; + for my $obj (@objs) { + $test_unique = 1 if $obj->[2]; + } + if ($test_unique) { + use Digest::MD5 qw(md5_base64); my $j = 0; my %used; for my $obj (@objs) { if ($obj->[2]) { - my $hash = $obj->[0].substr($obj->[1],0,18); + my $hash = md5_base64($obj->[0].$obj->[1]); splice (@objs, $j, 1) if exists $used{$hash}; $used{$hash}++; } @@ -113,12 +115,9 @@ sub tag_order { } } - # $objs[x][0] is YYYYMMDDhhmmss - # $objs[x][1] is OrderItem content - # $objs[x][2] is 0||1 - if ($ctx->stash('order_date_header') || $ctx->stash('order_date_footer')) { # loop over items in @objs adding headers and footers where necessary + my $builder = $ctx->stash('builder'); my ($yesterday, $tomorrow) = ('00000000')x2; my $i = 0; for my $o (@objs) { @@ -133,20 +132,18 @@ sub tag_order { } my $header = $today ne $yesterday; $ctx->{current_timestamp} = $o->[0]; - # $args->{ts} = $o->[0]; # TROUBLESHOOTING DATE CONTEXT my ($h_html, $f_html) = ('')x2; if ($header && $ctx->stash('order_date_header')) { - my $result = $ctx->stash('builder')->build($ctx, $ctx->stash('order_date_header'), {}); - return $ctx->error( $ctx->stash('builder')->errstr ) unless defined $result; + my $result = $builder->build($ctx, $ctx->stash('order_date_header'), {}); + return $ctx->error( $builder->errstr ) unless defined $result; $h_html = $result; } if ($footer && $ctx->stash('order_date_footer')) { - my $result = $ctx->stash('builder')->build($ctx, $ctx->stash('order_date_footer'), {}); - return $ctx->error( $ctx->stash('builder')->errstr ) unless defined $result; + my $result = $builder->build($ctx, $ctx->stash('order_date_footer'), {}); + return $ctx->error( $builder->errstr ) unless defined $result; $f_html = $result; } $objs[$i][1] = $h_html.$o->[1].$f_html; -MT::log("(".$h_html.") BODY (".$f_html.")"); $yesterday = $today; $i++; } @@ -212,4 +209,4 @@ sub tag_order_item { } -1; \ No newline at end of file +1; From ac5677160a5cfa0c7dcd50e2bcd89fd401d1f0e1 Mon Sep 17 00:00:00 2001 From: Charlie Gorichanaz Date: Thu, 2 Jun 2011 02:57:08 -0500 Subject: [PATCH 06/10] Removed `unique` attribute, added `local` to one line. Signed-off-by: Charlie Gorichanaz --- README.markdown | 28 +++++++++++++--------------- plugins/Order/lib/Order/Plugin.pm | 29 +++-------------------------- 2 files changed, 16 insertions(+), 41 deletions(-) diff --git a/README.markdown b/README.markdown index ad93391..3731225 100644 --- a/README.markdown +++ b/README.markdown @@ -29,8 +29,8 @@ example, to show the last 30 unique entries and ActionStreams items: - - + + @@ -38,14 +38,18 @@ example, to show the last 30 unique entries and ActionStreams items: - - - <$mt:StreamActionDate format="%Y%m%d%H%M%S"$> - -

">_16.png" width="12" height="12"> " class="actionlink">

-
+ + + + + + <$mt:StreamActionDate format="%Y%m%d%H%M%S"$> + +

">_16.png" width="12" height="12"> " class="actionlink">

+
+
- +
@@ -151,12 +155,6 @@ attribute is considered. That is, if you order 11 items, pin one to `-1` (last), and use `limit="10"` on the `mt:Order` tag, the pinned item will *not* be shown (it was the eleventh of ten items). -### `unique` ### - -In cases where two or more `mt:OrderItem`s have the same `order_by` value, the -same first 18 characters of content and the attribute `unique` set to the value -`1`, all duplicate `mt:OrderItem`s are removed. - ## `mt:OrderHeader` ## diff --git a/plugins/Order/lib/Order/Plugin.pm b/plugins/Order/lib/Order/Plugin.pm index 66623c2..cc89958 100644 --- a/plugins/Order/lib/Order/Plugin.pm +++ b/plugins/Order/lib/Order/Plugin.pm @@ -84,25 +84,7 @@ sub tag_order { push @objs, $sort->(@$items); } } - - my $test_unique = 0; - for my $obj (@objs) { - $test_unique = 1 if $obj->[2]; - } - if ($test_unique) { - use Digest::MD5 qw(md5_base64); - my $j = 0; - my %used; - for my $obj (@objs) { - if ($obj->[2]) { - my $hash = md5_base64($obj->[0].$obj->[1]); - splice (@objs, $j, 1) if exists $used{$hash}; - $used{$hash}++; - } - $j++; - } - } - + if (my $offset = $args->{offset}) { # Delete the first $offset items. splice @objs, 0, $offset; @@ -131,7 +113,7 @@ sub tag_order { $footer++; } my $header = $today ne $yesterday; - $ctx->{current_timestamp} = $o->[0]; + local $ctx->{current_timestamp} = $o->[0]; my ($h_html, $f_html) = ('')x2; if ($header && $ctx->stash('order_date_header')) { my $result = $builder->build($ctx, $ctx->stash('order_date_header'), {}); @@ -198,14 +180,9 @@ sub tag_order_item { my $order_value = $ctx->var($order_var) || q{}; $order_value =~ s{ \A \s+ | \s+ \z }{}xmsg; - my $is_unique = 0; - if (defined $args->{unique} && $args->{unique}) { - $is_unique = 1; - } - my $groups = $ctx->stash('order_items'); my $group = ($groups->{$group_id} ||= []); - push @$group, [ $order_value, $output, $is_unique ]; + push @$group, [ $order_value, $output]; } From 679451a60d89259b1638e2d0ca1cf330e363a21a Mon Sep 17 00:00:00 2001 From: Charlie Gorichanaz Date: Sun, 9 Oct 2011 00:43:59 -0500 Subject: [PATCH 07/10] Implemented `_hdlr_order_date()` to allow `` to ignore the `utc` attribute if provided, so the timestamp doesn't get double offset. Signed-off-by: Charlie Gorichanaz --- README.markdown | 13 +++--- plugins/Order/config.yaml | 2 +- plugins/Order/lib/Order/Plugin.pm | 73 +++++++++++++++++++++++++++---- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/README.markdown b/README.markdown index 3731225..4656ef0 100644 --- a/README.markdown +++ b/README.markdown @@ -20,8 +20,8 @@ example, to show the last 30 unique entries and ActionStreams items:
-
-

+
+

@@ -177,21 +177,22 @@ even an `mt:OrderItem` pinned to the end with the `pin="-1"` attribute. ## `mt:OrderDateHeader` ## A container tag whose contents will be displayed before the `mt:OrderItem` in context -if it is the first item for a given day. Requires `order_by` variable set inside the +if it is the first item for a given day. Requires `order_by` variable set inside the `mt:OrderItem` tag to be a timestamp formatted `%Y%m%d%H%M%S`. ## `mt:OrderDateFooter` ## A container tag whose contents will be displayed after the `mt:OrderItem` in context -if it is the last item for a given day. Requires `order_by` variable set inside the +if it is the last item for a given day. Requires `order_by` variable set inside the `mt:OrderItem` tag to be a timestamp formatted `%Y%m%d%H%M%S`. ## `mt:OrderDate` ## A function tag that works like an `mt:Date` tag, for use within `mt:OrderDateHeader` -and `mt:OrderDateFooter` blocks. +and `mt:OrderDateFooter` blocks. Does not take a `utc` attribute or support the +`relative` option of the `format` attribute. # Changes # @@ -200,8 +201,6 @@ and `mt:OrderDateFooter` blocks. * Added `mt:OrderDateHeader` and `mt:OrderDateFooter` tags. * Added `mt:OrderDate` tag. -* Added `unique` ordering option. - ## 1.1 10 June 2010 ## diff --git a/plugins/Order/config.yaml b/plugins/Order/config.yaml index f4da46d..737baa2 100644 --- a/plugins/Order/config.yaml +++ b/plugins/Order/config.yaml @@ -15,4 +15,4 @@ tags: OrderDateHeader: $Order::Order::Plugin::tag_order_date_header OrderDateFooter: $Order::Order::Plugin::tag_order_date_footer function: - OrderDate: $Core::MT::Template::Context::_hdlr_date + OrderDate: $Order::Order::Plugin::_hdlr_order_date diff --git a/plugins/Order/lib/Order/Plugin.pm b/plugins/Order/lib/Order/Plugin.pm index cc89958..f4b6c7c 100644 --- a/plugins/Order/lib/Order/Plugin.pm +++ b/plugins/Order/lib/Order/Plugin.pm @@ -1,6 +1,7 @@ - package Order::Plugin; +use MT::Util qw(format_ts); # Required by _hdlr_order_date() below + sub _natural_sort { sort { $a->[0] =~ m{ \A [+-]? \d+ }xms && $b->[0] =~ m{ \A [+-]? \d+ }xms @@ -52,7 +53,7 @@ sub _sort_group_ids { sub tag_order { my ($ctx, $args, $cond) = @_; - + my %groups = ( items => [] ); local $ctx->{__stash}{order_items} = \%groups; local $ctx->{__stash}{order_by_var} = $args->{by} || 'order_by'; @@ -67,7 +68,7 @@ sub tag_order { my $items = delete $groups{items}; my $sort = sort_function_for_args($args); my @objs = $sort->(@$items); - + # Inject the pinned groups from first place (0) to last (-1). for my $i (sort _sort_group_ids keys %groups) { my $items = $groups{$i}; @@ -84,7 +85,7 @@ sub tag_order { push @objs, $sort->(@$items); } } - + if (my $offset = $args->{offset}) { # Delete the first $offset items. splice @objs, 0, $offset; @@ -125,7 +126,7 @@ sub tag_order { return $ctx->error( $builder->errstr ) unless defined $result; $f_html = $result; } - $objs[$i][1] = $h_html.$o->[1].$f_html; + $objs[$i][1] = $h_html.$o->[1].$f_html; $yesterday = $today; $i++; } @@ -169,7 +170,7 @@ sub tag_order_date_footer { sub tag_order_item { my ($ctx, $args, $cond) = @_; - + my $group_id = defined $args->{pin} ? int $args->{pin} : 'items'; my $order_var = $ctx->stash('order_by_var'); @@ -179,11 +180,67 @@ sub tag_order_item { my $order_value = $ctx->var($order_var) || q{}; $order_value =~ s{ \A \s+ | \s+ \z }{}xmsg; - + my $groups = $ctx->stash('order_items'); my $group = ($groups->{$group_id} ||= []); push @$group, [ $order_value, $output]; - +} + +sub _hdlr_order_date { + ## This was taken from the Melody project's source code at + ## https://github.com/openmelody/melody/blob/master/lib/MT/Template/ContextHandlers.pm#L11358 + ## Code to handle relative dates and the UTC attribute were removed + ## Any bugs found in that code likely will need to be fixed here as well + my ( $ctx, $args ) = @_; + my $ts = $args->{ts} || $ctx->{current_timestamp}; + my $tag = $ctx->stash('tag'); + return + $ctx->error( + MT->translate( + "You used an [_1] tag without a date context set up.", + "MT$tag" + ) + ) unless defined $ts; + my $blog = $ctx->stash('blog'); + unless ( ref $blog ) { + my $blog_id = $blog || $args->{offset_blog_id}; + if ($blog_id) { + $blog = MT->model('blog')->load($blog_id); + return $ctx->error( + MT->translate( 'Can\'t load blog #[_1].', $blog_id ) ) + unless $blog; + } + } + my $lang + = $args->{language} + || $ctx->var('local_lang_id') + || ( $blog && $blog->language ); + if ( my $format = lc( $args->{format_name} || '' ) ) { + my $tz = 'Z'; + my $so = ( $blog && $blog->server_offset ) + || MT->config->TimeOffset; + my $partial_hour_offset = 60 * abs( $so - int($so) ); + if ( $format eq 'rfc822' ) { + $tz = sprintf( "%s%02d%02d", + $so < 0 ? '-' : '+', + abs($so), $partial_hour_offset ); + } + elsif ( $format eq 'iso8601' ) { + $tz = sprintf( "%s%02d:%02d", + $so < 0 ? '-' : '+', + abs($so), $partial_hour_offset ); + } + if ( $format eq 'rfc822' ) { + ## RFC-822 dates must be in English. + $args->{'format'} = '%a, %d %b %Y %H:%M:%S ' . $tz; + $lang = 'en'; + } + elsif ( $format eq 'iso8601' ) { + $args->{format} = '%Y-%m-%dT%H:%M:%S' . $tz; + } + } ## end if ( my $format = lc( ...)) + my $mail_flag = $args->{mail} || 0; + return format_ts( $args->{'format'}, $ts, $blog, $lang, $mail_flag ); } 1; From 12152f3733982c8ac29ea6903d123c3f62a3b312 Mon Sep 17 00:00:00 2001 From: Charlie Gorichanaz Date: Mon, 10 Oct 2011 22:06:16 -0500 Subject: [PATCH 08/10] Adjusted mt:OrderDate handler to directly use _hdlr_date() while zeroing any set 'utc' attribute and removed previously required included package. Signed-off-by: Charlie Gorichanaz --- README.markdown | 3 +- plugins/Order/lib/Order/Plugin.pm | 62 ++++--------------------------- 2 files changed, 8 insertions(+), 57 deletions(-) diff --git a/README.markdown b/README.markdown index 4656ef0..396a98b 100644 --- a/README.markdown +++ b/README.markdown @@ -191,8 +191,7 @@ if it is the last item for a given day. Requires `order_by` variable set inside ## `mt:OrderDate` ## A function tag that works like an `mt:Date` tag, for use within `mt:OrderDateHeader` -and `mt:OrderDateFooter` blocks. Does not take a `utc` attribute or support the -`relative` option of the `format` attribute. +and `mt:OrderDateFooter` blocks. Does not take a `utc` attribute. # Changes # diff --git a/plugins/Order/lib/Order/Plugin.pm b/plugins/Order/lib/Order/Plugin.pm index f4b6c7c..a48085c 100644 --- a/plugins/Order/lib/Order/Plugin.pm +++ b/plugins/Order/lib/Order/Plugin.pm @@ -1,7 +1,5 @@ package Order::Plugin; -use MT::Util qw(format_ts); # Required by _hdlr_order_date() below - sub _natural_sort { sort { $a->[0] =~ m{ \A [+-]? \d+ }xms && $b->[0] =~ m{ \A [+-]? \d+ }xms @@ -187,60 +185,14 @@ sub tag_order_item { } sub _hdlr_order_date { - ## This was taken from the Melody project's source code at - ## https://github.com/openmelody/melody/blob/master/lib/MT/Template/ContextHandlers.pm#L11358 - ## Code to handle relative dates and the UTC attribute were removed - ## Any bugs found in that code likely will need to be fixed here as well - my ( $ctx, $args ) = @_; - my $ts = $args->{ts} || $ctx->{current_timestamp}; - my $tag = $ctx->stash('tag'); - return - $ctx->error( - MT->translate( - "You used an [_1] tag without a date context set up.", - "MT$tag" - ) - ) unless defined $ts; - my $blog = $ctx->stash('blog'); - unless ( ref $blog ) { - my $blog_id = $blog || $args->{offset_blog_id}; - if ($blog_id) { - $blog = MT->model('blog')->load($blog_id); - return $ctx->error( - MT->translate( 'Can\'t load blog #[_1].', $blog_id ) ) - unless $blog; - } + my ($ctx, $args) = @_; + # Order dates are already UTC (or at least shouldn't be messed with after ordering). + if ($args->{utc}) { + my $tag = $ctx->stash('tag'); + return $ctx->error(qq{The mt:$tag doesn't support a utc attribute: items were already ordered by these dates, so can't readjust them for UTC after the fact.}); } - my $lang - = $args->{language} - || $ctx->var('local_lang_id') - || ( $blog && $blog->language ); - if ( my $format = lc( $args->{format_name} || '' ) ) { - my $tz = 'Z'; - my $so = ( $blog && $blog->server_offset ) - || MT->config->TimeOffset; - my $partial_hour_offset = 60 * abs( $so - int($so) ); - if ( $format eq 'rfc822' ) { - $tz = sprintf( "%s%02d%02d", - $so < 0 ? '-' : '+', - abs($so), $partial_hour_offset ); - } - elsif ( $format eq 'iso8601' ) { - $tz = sprintf( "%s%02d:%02d", - $so < 0 ? '-' : '+', - abs($so), $partial_hour_offset ); - } - if ( $format eq 'rfc822' ) { - ## RFC-822 dates must be in English. - $args->{'format'} = '%a, %d %b %Y %H:%M:%S ' . $tz; - $lang = 'en'; - } - elsif ( $format eq 'iso8601' ) { - $args->{format} = '%Y-%m-%dT%H:%M:%S' . $tz; - } - } ## end if ( my $format = lc( ...)) - my $mail_flag = $args->{mail} || 0; - return format_ts( $args->{'format'}, $ts, $blog, $lang, $mail_flag ); + return $ctx->_hdlr_date($args); } + 1; From 8f779dd4c4ac45d5e4702cbe8d903c4dd1512a6c Mon Sep 17 00:00:00 2001 From: Charlie Gorichanaz Date: Mon, 10 Oct 2011 22:07:26 -0500 Subject: [PATCH 09/10] Adjusted date in readme Signed-off-by: Charlie Gorichanaz --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 396a98b..374d153 100644 --- a/README.markdown +++ b/README.markdown @@ -196,7 +196,7 @@ and `mt:OrderDateFooter` blocks. Does not take a `utc` attribute. # Changes # -## 1.2 10 May 2011 ## +## 1.2 10 October 2011 ## * Added `mt:OrderDateHeader` and `mt:OrderDateFooter` tags. * Added `mt:OrderDate` tag. From cf8e947d62195b71207f7974cf4449ce2a173fcd Mon Sep 17 00:00:00 2001 From: Charlie Gorichanaz Date: Mon, 10 Oct 2011 22:07:26 -0500 Subject: [PATCH 10/10] Adjusted date and made a correction in readme Signed-off-by: Charlie Gorichanaz --- README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.markdown b/README.markdown index 396a98b..58c5eb1 100644 --- a/README.markdown +++ b/README.markdown @@ -126,7 +126,7 @@ set inside the `mt:OrderItem` tag. Set the `order_by` variable by using the `mt:SetVarBlock` tag or the `setvar="variable name"` global attribute on a tag inside the `mt:OrderItem`. -`mt:OrderItem` has two optional attributes: +`mt:OrderItem` has one optional attribute: ### `pin` ### @@ -196,7 +196,7 @@ and `mt:OrderDateFooter` blocks. Does not take a `utc` attribute. # Changes # -## 1.2 10 May 2011 ## +## 1.2 10 October 2011 ## * Added `mt:OrderDateHeader` and `mt:OrderDateFooter` tags. * Added `mt:OrderDate` tag.