File Coverage

blib/lib/Articulate.pm
Criterion Covered Total %
statement 15 21 71.4
branch n/a
condition n/a
subroutine 5 6 83.3
pod 1 1 100.0
total 21 28 75.0


line stmt bran cond sub pod time code
1             package Articulate;
2 5     5   19853 use strict;
  5         6  
  5         168  
3 5     5   20 use warnings;
  5         6  
  5         115  
4              
5 5     5   2686 use Moo;
  5         65193  
  5         30  
6             with 'MooX::Singleton';
7              
8 5     5   8891 use Articulate::Service;
  5         15  
  5         24  
9 5     5   1774 use Module::Load ();
  5         8  
  5         1565  
10             our $VERSION = '0.004';
11              
12             =head1 NAME
13              
14             Articulate - A lightweight Perl CMS Framework
15              
16             =head1 WARNING
17              
18             This is very much in alpha. Things will change. Feel free to build
19             things and have fun, but don't hook up anything business-critical just
20             yet!
21              
22             =head1 SYNOPSIS
23              
24             # (in bin/app.pl)
25             use Dancer;
26             use Dancer::Plugin::Articulate;
27             articulate_app->enable;
28             dance;
29              
30             B provides a content management service for your web app.
31             It's lightweight, i.e. it places minimal demands on your app while
32             maximising 'whipuptitude': it gives you a single interface in code to a
33             framework that's totally modular underneath, and it won't claim any URL
34             endpoints for itself.
35              
36             You don't need to redesign your app around Articulate, it's a service
37             that you call on when you need it, and all the 'moving parts' can be
38             switched out if you want to do things your way.
39              
40             It's written in Perl, the fast, reliable 'glue language' that's perfect
41             for agile web development projects, and currently runs on the L
42             and L web frameworks.
43              
44             =head1 GETTING STARTED
45              
46             Don't forget to install Articulate - remember, it's a library, not an
47             app.
48              
49             # From source:
50             perl Makefile.PL
51             make
52             make test
53             make install
54              
55             Check out the examples in the C folder of the distribution.
56              
57             To add Articulate to your own app, you'll need to:
58              
59             =over
60              
61             =item * add it to your C or similar (see example above) using either L or L.
62              
63             =item * edit your C to configure the components you want (check each of the components for a description of their config options - or just borrow a config from one of the examples)
64              
65             =item * write any custom code you want if you don't like what's there, and just swap it out in the config.
66              
67             =item * polish off your front-end, all the backend is taken care of!
68              
69             =back
70              
71             Curious about how it all fits together? Read on...
72              
73             =head1 DESCRIPTION
74              
75             Articulate is a set of components that work together to provide a
76             content management service that will sit alongside an existing Dancer
77             app or form the basis of a new one.
78              
79             If you want to see one in action, grab the source and run:
80              
81             # If you have Dancer and Dancer::Plugin::Articulate installed:
82             cd examples/plain-speaking
83             perl bin/app.pl -e dancer1
84              
85             # Or, if you have Dancer2 and Dancer2::Plugin::Articulate installed:
86             cd examples/plain-speaking
87             perl bin/app.psgi
88              
89             You can see how it's configured by looking at
90              
91             examples/plain-speaking/config.yml
92              
93             Notice that C doesn't directly load anything but the
94             Articulate plugin (which loads config into this module). Everything you
95             need is in C, and you can replace components with ones
96             you've written if your app needs to do different things.
97              
98             =head2 Request/Response lifecycle summary
99              
100             In a B, you parse user input and pick the parameters you want to
101             send to the B. Have a look at
102             L for some examples. The intention is
103             that routes are as 'thin' as possible: business logic should all be
104             done by some part of the service and not in the route handler. The
105             route handler maps endpoints (URLs) to service requests; structured
106             responses are passed back as return values and are picked up by the
107             B.
108              
109             B pass B to B. A B contains a
110             B (like C) and B (like the B you want to
111             create it at and the B you want to place there). See
112             L for more details.
113              
114             The B is responsible for handling requests for managed
115             content. L B to a service B,
116             asking each in turn if they are willing to handle the request (normally
117             the provider will dertermine this based on the request verb). A
118             provider typically checks a user has suitable permission, then
119             interacts with the content storage system.
120              
121             B is controlled by L. It delegates to a
122             storage class which is configured for actions like C and
123             C.
124              
125             Content is stored in a structure called an B (see
126             L), which has a C (see
127             L), the B (which could be a binary blob
128             like an image, plain text, markdown, XML, etc.) and the associated
129             B or B (which is a hashref).
130              
131             Before items can be placed in storage, the service should take care to
132             run them through B. L delegates
133             this to validators, and if there are any applicable validators, they
134             will check if the content is valid. The content may also be
135             B, i.e. further metadata added, like the time at which the
136             request was made (consult L for details).
137              
138             After items are retrieved from storage, there is the opportunity to
139             B them, for instance by including relevant content from
140             elsewhere which belongs in the response. See
141             L for details on this.
142              
143             If at any time uncaught errors are thrown, including recognised
144             L objects, they are caught and handled by
145             L. L should therefore always
146             return an L object.
147              
148             Once the request finds it back to the Route it will typically be
149             B immediately (see L), and the
150             resulting response passed back to the user.
151              
152             =head2 Components
153              
154             The following classes are persistent, configurable B of the
155             system:
156              
157             =over
158              
159             =item * L
160              
161             =item * L
162              
163             =item * L
164              
165             =item * L
166              
167             =item * L
168              
169             =item * L
170              
171             =item * L
172              
173             =item * L
174              
175             =item * L
176              
177             =item * L
178              
179             =item * L
180              
181             =back
182              
183             =head2 Data Classes
184              
185             The following classes are used for passing request data between
186             components:
187              
188             =over
189              
190             =item * L
191              
192             =item * L
193              
194             =item * L
195              
196             =item * L
197              
198             =item * L
199              
200             =item * L
201              
202             =item * L
203              
204             =item * L
205              
206             =item * L
207              
208             =back
209              
210             =head2 Other modules of interest
211              
212             =over
213              
214             =item * L
215              
216             =item * L
217              
218             =item * L
219              
220             =item * L
221              
222             =item * L
223              
224             =item * L
225              
226             =back
227              
228             =head2 Instantiation
229              
230             Articulate provides a very handy way of creating (or B)
231             objects through your config. The following config, for instance,
232             assignes to the providers attribute (on some other object), an arrayref
233             of four objects, the first created without no arguments, two created
234             with arguments, and a final one created without arguments but using an
235             unusual constructor.
236              
237             providers:
238             - MyProvider::Simple
239             - class: MyProvider::Congfigurable
240             args:
241             verbose: 1
242             - MyProvider::Congfigurable:
243             lax: 1
244             verbose: 1
245             - class: MyProvider::Idiosyncratic
246             constuctor: tada
247              
248             For more details, see L.
249              
250             =head2 Delegation
251              
252             A key part of the flexibility of Articulate is that objects often
253             B functions to other objects (the B)
254              
255             Typically, one class delegates to a series of providers, which are each
256             passed the same arguments in turn. L is a
257             good example of this. Sometimes the response from one provider will
258             halt the delegation - see L for an example
259             of this.
260              
261             Occasionally, only one provider is possible, for instance
262             L. In this case there is a substitution
263             rather than a delegation.
264              
265             =cut
266              
267             =head1 METHOD
268              
269             =head3 enable
270              
271             Sets up the routes. This does not happen at construction so you can
272             control the point at which routes are declared.
273              
274             =head1 ATTRIBUTES
275              
276             =head3 enabled
277              
278             Please do not set this directly, use C instead.
279              
280             =head3 routes
281              
282             The packages which provide routes for Articulate. See
283             L and L for more
284             details.
285              
286             =head3 components
287              
288             The different working pieces of the Articulate app. Components all have
289             access to each other indirectly and they provide features across
290             Articulate; see L for more details.
291              
292             =cut
293              
294             sub enable {
295 0     0 1   my $self = shift;
296 0           foreach my $route ( @{ $self->routes } ) {
  0            
297 0           $route->app($self);
298 0           $route->enable;
299             }
300 0           $self->enabled(1);
301             }
302              
303             has enabled => (
304             is => 'rw',
305             default => sub { 0 }
306             );
307              
308             has routes => (
309             is => 'rw',
310             default => sub { [] },
311             coerce => sub {
312             Module::Load::load('Articulate::Syntax');
313             Articulate::Syntax::instantiate_array(@_);
314             },
315             trigger => sub {
316             my $self = shift;
317             my $orig = shift;
318             $_->app($self) foreach @$orig;
319             },
320             );
321              
322             has components => (
323             is => 'rw',
324             default => sub { {} },
325             coerce => sub {
326             my $orig = shift;
327             Module::Load::load('Articulate::Syntax');
328             Articulate::Syntax::instantiate_selection($orig);
329              
330             },
331             trigger => sub {
332             my $self = shift;
333             my $orig = shift;
334             $orig->{$_}->app($self) foreach keys %$orig;
335             },
336             );
337              
338             =head1 BUGS
339              
340             Bugs should be reported to the L
341             tracker|https://github.com/pdl/Articulate/issues>. Pull Requests
342             welcome!
343              
344             =head1 COPYRIGHT
345              
346             Articulate is Copyright 2014-2015 Daniel Perrett. You are free to use
347             it subject to the same terms as perl: see the LICENSE file included in
348             this distribution for what this means.
349              
350             Currently Articulate is bundled with versions of other software whose
351             license information you can access from the LICENSE file.
352              
353             =cut
354              
355             1;