This repository has been archived by the owner on Oct 11, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Creating a repository for the Order plugin, v1.1
- Loading branch information
0 parents
commit 4bb9a90
Showing
2 changed files
with
157 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
|