The best way to learn how to use the WebCore is by example. See the documentation for more information.
The requested URL is always shown first; if a page uses one or more WebCore templates, those are shown afterwards.
00 <?php
01 include_once ('software/webcore_init.php');
02 $Page->title->subject = 'Features';
03 $Page->location->append ('WebCore', './');
04 $Page->location->append ('Features');
05 $Page->start_display ();
06 ?>
07 <div class="main-box">
08 <div class="columns text-flow">
09 <div>
10 <p>Before getting too deep into individual features, take a look at <a href="why.php">Why
11 earthli WebCore?</a> It describes the philosophy behind this framework. Once you've
12 got that under your belt, read on to see just how much the WebCore offers.</p>
13 <p>When you program with the WebCore, the different stages of preparing a web
14 page are clearly defined and well-supported.</p>
15 <ul>
16 <li>First, you decide which data you want to show in a page. Use <a href="#searching">searches</a>,
17 <a href="#lists">lists</a> or directly <a href="#database">query</a> to request
18 your objects from the <a href="#environment">application</a>.</li>
19 <li>The request is filtered through the current <a href="#users">login</a>,
20 which has certain <a href="#security">permissions</a> in the given <a href="#folders">context</a>.</li>
21 <li>Lists of objects and individual objects are <a href="#rendering">rendered</a>,
22 each object using <a href="#icons">icons</a> and <a href="#munger">formatting</a>
23 to return a consistent, compliant page to the <a href="#browser">browser</a>.</li>
24 </ul>
25 <h2>Your content</h2>
26 <h3><a id="users"></a>Users</h3>
27 <p>Pretty much any marginally-interactive website needs to address the concept
28 of logging in. As soon as you have stuff that some people can do and others can't,
29 you're going to need a solid <em>user concept</em>.</p>
30 <p>The WebCore provides a pretty deep implementation of users, including auto-registered
31 anonymous users. All users, registered and anonymous, are treated equally;
32 anonymous users are uniquely identified by IP address and can be restricted with
33 permissions just like normal users.</p>
34 <p>The user itself has a bunch of properties like name, home page, etc. already
35 implemented. And, last but certainly not least, a pretty smooth avatar
36 implementation lets your users customize their online appearance. WebCore
37 applications can easily use this icon in different places to make users stand
38 out.</p>
39 <p>Users can be shared across applications and handled with the same login; an
40 application can also define its own users. See <a href="#sharing">sharing</a>
41 for more information.</p>
42 <p>Logging in, logging out, applying user and content permissions: it's all
43 taken care of for you. See <a href="#security">security</a> for more information
44 about how it works.</p>
45 <h3 id="folders">Folders</h3>
46 <p>Almost any website you can think of is separated into sections. If you're
47 listing movies and movie reviews, you might break them up into genre. Photo
48 albums are broken up by year or destination. Some areas might be private or
49 allowed only for certain users.</p>
50 <p>Any earthli WebCore application can have as many folders as you like, nested
51 as deeply as you like. While you can define keywords and categories for free
52 searching and association, it's still nice to be able to apply at least a
53 rudimentary hierarchy to your data.</p>
54 <p>Folders are also the framework in which you define your application's <a href="#security">security</a>.
55 Subfolders automatically inherit permissions from their parent folder.</p>
56 <h3 id="comments">Comments</h3>
57 <p>As soon as you start to mix online content with online users, you've got <em>opinions</em>.
58 You can't have a community unless your users can talk to each other. The earthli
59 WebCore provides a general solution to comments that integrate into any
60 application.</p>
61 <p>Comments can be nested (so they answer each other) and presented in pages (so
62 you don't have to serve enormous pages). There are a bunch of view options, like
63 threaded or flat viewing.</p>
64 <h3 id="attachments">Attachments</h3>
65 <p>As with comments, its not long before you realize that text isn't the only
66 type of content your site has. You need a generic way to get binary content onto
67 your site and keep it organized. If you've got an article with 3 pictures, it
68 would be nice if those pictures were deleted if you deleted the article. Storage
69 space isn't free, right?</p>
70 <p>Attachments can be made for any object in a WebCore application: folders,
71 users, comments, even your custom application objects. Image attachments are
72 automatically detected and stored with a thumbnail (if you want one); other file
73 types get a type-specific icon. Since zip-file handling is integrated, a zip
74 attachment displays its file contents when viewed.</p>
75 <p>Once you've attached a file, you can easily show it in your text as a
76 thumbnail or full image. Check out <a href="text_formatting.php#paths">paths</a>
77 to find out more.</p>
78 <h3 id="history">History</h3>
79 <p class="quote-block">"Who changed what when?"</p>
80 <p>When you're a publisher (and on the web, we're all publishers!), you've got
81 to be concerned with auditing or tracking the <em>history</em> of the stuff you've
82 got on your website. It's important to a user to know when an item was created
83 and when it was last updated. When you're running a site, you want to know who
84 made changes to it.</p>
85 <p>Your site users are usually just concerned with when an item was last updated,
86 but you may want to know everything that's ever happened to it. Has it ever been
87 deleted? Why was it brought back? When?
88 <p>The earthli WebCore uses 'auditable' objects, which track their entire
89 histories as a series of 'actions' that occurred to a website object, like an
90 article, a comment, a folder or even a user. Pretty much everything is trackable.</p>
91 <h3 id="searching">Searching</h3>
92 <p>You've got all of your stuff in a database and users are making comments and
93 stories all the time. Now they want to find something. Well, you've got a nice <a href="#folders">folder</a>
94 hierarchy to help them out, right? The earthli WebCore offers much more powerful
95 searching than that.</p>
96 <ul>
97 <li>All objects in a WebCore application (your own objects, comments, users, etc.)
98 can be searched.</li>
99 <li>Constrain and sort by almost any field in an object.</li>
100 <li>Full-text search on any combination of text fields.</li>
101 <li>A powerful API makes adding new fields a snap. User-friendly forms and
102 search results are automatically generated for you.</li>
103 </ul>
104 <p>The WebCore's search engine runs on top of the <a href="#database">database</a>
105 layer. It takes care of displaying the search form and applying search
106 parameters to the query.</p>
107 <p>You can save searches and retrieve their results again later. So, you can do
108 cool things like
109 <span class="quote-inline">
110 "find all recipes made by Bob in the last week"
111 </span>
112 and always be able to check out what Bob's been up to.</p>
113 <p>You can also leave parameters open when you save the search, and let the
114 WebCore fill it in from the context. So, if you're on Alice's home page and you
115 run the search from above, you'd see all the recipes Alice made in the last week.</p>
116 <p>The WebCore uses searches to define your default interface, showing the lists
117 of different types of objects available. Users can redefine and add to these to
118 customize the interface to suit them. Searches work hand-in-hand with <a href="#lists">lists</a>
119 to help you get the most out of a WebCore application.</p>
120 <h3 id="lists">Lists</h3>
121 <p>With <a href="#searching">searches</a> you ask the database a question. The
122 database returns a list of objects as an answer. Now you want to do something
123 with them: print, email, delete, etc. You can select one of more items from a
124 search result and act on it directly, but what if one search result can't
125 contain everything you want?</p>
126 <p>That's where <em>lists</em> come in. You can take any or all of the objects
127 from a search result and move them to a list. Then you can run another search
128 and add some more objects to that list. You can delete objects from a list. When
129 your list is ready, print it, email it or just leave it. It'll be there when you
130 come back.</p>
131 <p>Searches define views on the database, but lists just store a fixed set of
132 objects that isn't necessarily based on a single query. </p>
133 <ul>
134 <li>You can make a list of stories you'd like to read and delete them from the
135 list as you finish them.</li>
136 <li>You can make a list of your all-time favorite funny comments or your
137 favorite pictures.</li>
138 <li>You can make lists of anything, just like you can search anything, so you
139 can make a list of users to be your "buddy list".</li>
140 <li>You can do a lot with the objects in a list: print, delete, purge, email,
141 even edit them! You can gather a whole bunch of objects and edit them all in one
142 big batch: a huge time-saver!
143 <li>Use temporary lists as you browse and search your way through an application.
144 When you're done with your research, delete the list.</li>
145 <li>Unlike searches, List contents don't change unless you change them.</li>
146 </ul>
147 <p>You don't need to do anything special to make lists work with your own
148 application objects. If your objects are searchable, they're listable.</p>
149 <h3 id="drafts">Drafts</h3>
150 <p>People will be using your application from everywhere. If your application
151 objects have a lot of text, users may not always be ready to publish their work
152 right away. You want to be able to save to the server, but keep other users away
153 from it until you're done.</p>
154 <p>The WebCore offers just that with <em>drafts</em>. If you define an object as
155 draftable, the form for it is automatically generated with a 'Save as draft'
156 button. Come back to the site later, <a href="#searching">search</a> for your
157 draft and keep working. When you're ready, you <a href="#publishing">publish</a>
158 it.</p>
159 <h2>Making it work</h2>
160 <h3 id="environment">Environment</h3>
161 <p>The WebCore gathers disparate PHP variables and functions that are really
162 useful when building web pages into a sensible object-oriented API.</p>
163 <ul>
164 <li>The <em>environment</em> provides url information, redirecting, exception
165 handling, basic date/time services and more.</li>
166 <li>The <em>page</em> handles rendering and global configuration.</li>
167 <li><em>Applications</em> manage your data objects and create global objects
168 like text-formatters, mailers and more.</li>
169 <li>A global <em>profiler</em> lets you time different parts of your code to see
170 what's slowing you down.</li>
171 <li>A global <em>logger</em> supports many output options, including a separate
172 JavaScript-driven window, so you can avoid using 'echo' for debugging. The
173 WebCore uses this log heavily and will show you what's going on when something
174 goes wrong.</li>
175 </ul>
176 <p>There are other classes and functions for file-handling, zip files and
177 different exception handlers. When an error occurs, all associated information
178 is automatically gathered and can be sent by the user via email.</p>
179 <h3 id="security">Security</h3>
180 <p>You can't escape it. As soon as you have an interactive system, you've got to
181 consider who gets to do what. Even if you don't spend a second actually thinking
182 about it, you've implicitly decided that everyone gets to do everything.</p>
183 <p>Most web sites probably don't want that.</p>
184 <p>Everything you do in an earthli WebCore application is based on a logged-in-user
185 (see <a href="#users">users</a> for more information). Even if no actual user
186 has logged in, the system assumes the rights of an anonymous user. The user in
187 the application answers the question
188 <span class="quote-inline">
189 "Is this operation allowed here?"
190 </span>
191 </p>
192 <p>If you look more carefully at that question, you see it's got two important
193 parts: <em>operation</em> and <em>location</em> ('here').
194 <ul>
195 <li>Operations are 'view', 'edit', 'delete' and so on -- the usual suspects.</li>
196 <li>Each object <em>type</em> (comments, folders, users, etc.) can be controlled
197 individually.</li>
198 <li>Objects can also add their own specialized privileges to this list. (e.g. <a href="./#projects">Projects</a>
199 defines 'Can assign' for job objects.)</li>
200 <li>Folders define the permissions that are used for all objects in that folder.
201 They inherit permissions from their parent by default.</li>
202 </ul>
203 <p>You will, of course, still need a super-user who's rights can't be limited by
204 folder permissions. That's where user permissions come in. User permissions
205 override folder permissions by either always granting or always denying a
206 privilege. They also define privileges that are not folder-dependent (like login
207 or offline privileges).</p>
208 <ul>
209 <li>You can make your super-user by defining a user that grants all rights.</li>
210 <li>You can automatically ban a user by denying all rights.</li>
211 <li>'default' rights for registered and anonymous users are set using the same
212 system.</li>
213 </ul>
214 <p>You can also define user groups to apply folder permissions to lists of users.
215 That way, you say that your folder allows certain privileges for the group 'Editors'
216 and others for the group 'Moderators'. You can control who gets to do what by
217 changing membership in those groups.</p>
218 <h3 id="database">Database</h3>
219 <p>Dynamic websites are built with databases: static content is so 90's. MySQL
220 has a lot of name recognition and the WebCore has run on it since its earliest
221 days. But, this doesn't mean that it can <em>only</em> run on MySQL.</p>
222 <p>All references to PHP's data functions are made through a database
223 abstraction layer. All SQL is produced by query objects which map your requests
224 onto the underlying database. When you work with a WebCore application, you
225 rarely, if ever, have to write even a snippet of SQL. This centralization makes
226 your application much more mobile and flexible. If you want to try out
227 PostGreSQL, you don't have to modify a thing: just switch your database type.</p>
228 <p>With the WebCore, you don't set up SQL and execute loops and call database-dependent
229 functions. You work only with objects and list of objects returned by queries.</p>
230 <h3 id="storage">Storage</h3>
231 <p>The <a href="#database">database</a> section shows how your application <em>reads</em>
232 data without you writing any SQL. But, your application defines objects that
233 need to <em>store</em> data.</p>
234 <p>There's another abstract layer here that makes creating and updating objects
235 a piece of cake. If you define or extend objects, you just give the name of the
236 field, its type and its value, and the WebCore takes care of marshalling and
237 validating it into the database.</p>
238 <p>Again, no more SQL for you. Just call 'store' and you're done.</p>
239 <h3><a id="trash_can"></a>Trash can</h3>
240 <p>To make sure that content is always findable and restorable, WebCore
241 applications can use a 'trash-can'. Users can delete objects and they'll
242 disappear from their interface, but users with 'view hidden' privileges can
243 still see them and restore them or purge them from the database for good.</p>
244 <ul>
245 <li>Insulate your users against lost data</li>
246 <li>Since nothing's ever deleted right away, an admin can recover data for a
247 user.</li>
248 <li>Objects can be explictly purged from the database. You can, of course, set
249 up your application to directly purge all objects, skipping the trash can
250 completely.</li>
251 </ul>
252 <p>Hidden objects also lets moderators or admins hide portions of the
253 application while it is under maintenance and smoothly show it again when its
254 ready. <a href="#drafts">Drafts</a> are implemented on top of this system.</p>
255 <h3 id="locations">Locations</h3>
256 <p>Once you've got a bunch of content on your site, you need to be careful: it
257 gets pretty fragile and you're not allowed to move it around too much. Links
258 will break and you'll have missing images and styles popping up in the most
259 unpleasant places.</p>
260 <p>The WebCore lets you define <em>locations</em>, which you use throughout your
261 code as aliases to resources you need. That way, you just update the alias and
262 move the files and your website keeps happily purring along. You can even move
263 stuff to other servers without updating any of your content.</p>
264 <p>A standard application defines areas for <a href="#icons">icons</a>, <a href="#skinning">styles</a>
265 and scripts. There are even some special ones that are object-dependent, like 'attachment'
266 and 'thumbnail'. You can add your own locations and reference them just like the
267 built-in ones.</p>
268 <p>See <a href="text_formatting.php#paths">paths</a> for more information on
269 referring to resources.</p>
270 <h3 id="forms">Forms</h3>
271 <p>If you've done any web development, you know that forms take up the lion's
272 share of your coding and testing time. You've got so much to consider: display,
273 validation, value-conversion, error-handling: the list goes on and on.</p>
274 <p>The WebCore defines an extensive forms library. Forms define a list of fields
275 and indicate how each field is loaded from and stored to the object it
276 represents. Form rendering is separated into another layer, so your application
277 can redefine the look of all forms from a central location.</p>
278 <p>Almost all conceivable control implementations are supported and tested: from
279 all of the standard text fields and drop-downs to truly elegant and simple
280 support for grouped controls like lists of radio buttons or checkboxes.</p>
281 <p>All you have to do for your form is:</p>
282 <ul>
283 <li>Decide which fields it has. You can set the name, type, required status,
284 description and much more.</li>
285 <li>Map values from your data representation (usually an object) to your fields.</li>
286 <li>Map values from the submitted form back to your data.</li>
287 <li>Draw the form with the WebCore's abstract rendering API.</li>
288 <li>Marshalling data from the request object into the right form is handled
289 automatically</li>
290 </ul>
291 <p>It's so much easier and better-looking to use a form object, you'll never
292 hand-code a form again.</p>
293 <h3 id="upload">Uploads</h3>
294 <p>Uploading is tightly integrated with the <a href="#forms">forms</a> library,
295 but it's so hard, it merits its own section. It's hard because of several
296 reasons.</p>
297 <ul>
298 <li>The WebCore shields you from varying browser uploading behavior.</li>
299 <li>PHP also behaves differently depending on the version.</li>
300 <li>You're moving files around on the server -- the WebCore takes care of error-handling
301 for you.</li>
302 <li>The WebCore integrates uploading into the forms library, offering only-upload-once
303 support, which transparently stores uploaded files even if the form didn't
304 validate, so users only have to upload once.</li>
305 </ul>
306 <p><a href="#attachments">Attachments</a> is built on top of this API and it
307 makes nice use of <a href="#icons">icons</a> to show users which kind of file
308 they've uploaded.</p>
309 <h3 id="publishing">Publishing</h3>
310 <p>Once your site is online and you've got users, you probably want to be able
311 to let them know when you've updated your site. This opens up a whole new can of
312 worms, though.</p>
313 <ul>
314 <li>Whom do you notify? You need a list of subscribers and they need to be able
315 to say when and what you send. Spam's a bit of a touchy subject these days.</li>
316 <li>When do you notify? What does it mean to update a site? There are changes
317 you probably don't want to notify subscribers of.</li>
318 </ul>
319 <p>Again, the earthli WebCore provides quite a bit of support in this department.
320 The notion of subscribers is pretty deeply rooted in the library and based on
321 the auditing system described in <a href="#history">history</a>.</p>
322 <p>When you make a change to a website object, you've got the option of
323 modifying the history action that gets created for that change: you can modify
324 the title (email subject) and decide whether messages even get sent at all.
325 Publishing scripts can be set up to troll the database at regular intervals,
326 sending out messages for unprocessed actions.</p>
327 <p>As a user, you've got a load of options to control how much you get and when.</p>
328 <ul>
329 <li>You can set your schedule (immediately, hourly, daily, etc.) and organize
330 your notifications to be grouped into bulk emails.</li>
331 <li>You can, of course, select HTML or plain text format.</li>
332 <li>From the content side, you can subscribe to entire folders or to individual
333 objects. You can even subscribe to a user so you're informed whenever that user
334 does something (our stalking feature).</li>
335 </ul>
336 <h3 id="sharing">Sharing</h3>
337 <p>Since WebCore applications are built on the same base, they can easily share
338 large parts of the database to integrate them even more tightly.</p>
339 <ul>
340 <li>Users are shared by default, allowing your users to browse multiple
341 applications on your site with a single login.</li>
342 <li>You can also elect to share user permissions, giving users the same non-content-specific
343 permissions in all applications.</li>
344 <li>Even tighter integration shares <em>folders</em>, giving all your
345 applications the same structure. Tighter still shares folder permissions too; if
346 users can create content in a folder in one application, they can do so in all
347 the others. Administer all of your applications at once!</li>
348 <li>Global resources like themes and icons are also shared, by default.</li>
349 </ul>
350 <h3 id="customizing">Customization</h3>
351 <p class="quote-block">How do you deploy one of these applications to your own
352 website?</p>
353 <p>The WebCore automatically searches for configuration files in a 'plugins'
354 folder outside of the WebCore code folder. You can grab the default
355 initialization files, customize them and save them here. There are a lot of
356 options to help you get the application seamlessly integrated into your website
357 (you can even make your own <a href="#skinning">skin</a>).</p>
358 <p>On top of that, some applications, like <a href="./#projects">Projects</a>,
359 let you customize right from a web interface.</p>
360 <p class="quote-block">The WebCore is a development platform. How do you develop
361 in it?</p>
362 <p>So you want to customize an existing application: add a field to an object or
363 just change the way a list looks. All objects: data objects, lists, renderers,
364 mailers etc. are created centrally. If you want the WebCore to create a
365 different object for a particular type, say 'Comment renderer', you just
366 register your own class name and file location and the application creates and
367 uses that one instead.</p>
368 <p>All you do is make sure that your object supports the right interface (which
369 you can easily do by inheriting from the class you're replacing) and it will
370 integrate seamlessly. The objects used in the WebCore and its applications are
371 extensively <a href="documentation.php">documented</a>.</p>
372 <p>Existing WebCore applications use the same exact mechanism to 'customize' a
373 default application, so you can develop your own applications in the same way.
374 All modifications, from the smallest tweaks to the biggest overhauls, are
375 supported with the same approach.</p>
376 <p>Store your personal class definitions in the 'plugins' folder and you won't
377 overwrite anything when you upgrade the WebCore or the base application files.</p>
378 <h2>Making it look good</h2>
379 <h3 id="skinning">Skinning (Themes)</h3>
380 <p>All earthli WebCore template pages are defined using a strict set of CSS
381 styles, which are easy to override to provide your own color and style for your
382 application. You can make a bunch of them and let users pick the one they want
383 to use. There are several to get you started in the default package.</p>
384 <p>You can even redefine the header/footer layout by defining your own template
385 and placing specially-named elements in your layout so the WebCore can put the
386 page together the way you want it. Tell your style to use your template instead
387 of the default one and you're all set. This is perfect for adapting a WebCore
388 application to an existing web-site's style. There are a couple of layouters
389 included in your basic package too.</p>
390 <p>If you want to go further and change the layout of the <em>content</em> of
391 pages, like the way a list is displayed or the information displayed with an
392 object, you'll have to head on over to <a href="#customizing">customization</a>.</p>
393 <h3 id="munger">Text formatting</h3>
394 <p>The WebCore provides a powerful formatting language that looks like HTML, but <em>isn't</em>.
395 The formatting tags and attributes mirror HTML for familiarity, but are actually
396 transformed to the target content by the <em>munger</em> (named after the <a href="http://developer.apple.com/documentation/mac/Text/Text-329.html">Apple
397 toolbox function</a>). This HTML-independent language can just as well be
398 transformed to other formats as well. A Plain text formatter is used to generate
399 nicely-formatted emails.</p>
400 <p>Treating all user-entered text in this way has a lot of benefits.</p>
401 <ul>
402 <li>It guarantees compliant HTML, so your pages don't get bent out of shape by
403 invalid user content.</li>
404 <li>In fact, the forms library integrates a validator that keeps users from even <em>entering</em>
405 invalid content. It reports all errors with line and character position to help
406 them pinpoint their errors.</li>
407 <li>It prevents users from deliberately entering malicious HTML, like JavaScript
408 that loops endlessly or pops up other windows.</li>
409 <li>Lines that should be single-line (like titles) simply don't generate block
410 content and the validator flags non-single-line tags like lists.</li>
411 <li>As mentioned above, it's much easier to export other formats.</li>
412 </ul>
413 <p>To see what the tag format looks like, check out the <a href="text_formatting.php">text
414 formatting manual</a>.</p>
415 <h3 id="rendering">Rendering</h3>
416 <p>The earthli WebCore provides a lot of display classes to render your
417 application objects into a page. There are trees, grids, calendars, toolbars and
418 more.</p>
419 <ul>
420 <li>Grids work directly with <a href="#database">queries</a>, displaying the
421 desired rows and columns and paginating automatically for large lists.</li>
422 <li>Toolbars, or <em>buttons</em>, are login-sensitive, automatically showing
423 only buttons for users the logged-in user is allowed to do.</li>
424 <li>Trees render as DHTML or static, depending on the <a href="#browser">browser</a>.</li>
425 <li>Print-preview pages are automatically generated. There are even print
426 options that are specific to the type of object being printed (<a href="./#projects">Projects</a>
427 makes heavy use of this to make very flexible changelists).</li>
428 </ul>
429 <p>Every object also has an individual renderer, which shows all information for
430 that object. These renderers are used everywhere when showing objects, so no
431 more hunting through dozens of web pages with search/replace to get everything
432 up-to-date.</p>
433 <p>This is very cool because the object's home page uses the HTML output to show
434 the object as HTML, print-preview usually uses the HTML renderer too and emails
435 use the HTML or plain text rendering to show the object. And, as you'll see in <a href="#customizing">customization</a>,
436 you can hook in your own renderer for an object and the WebCore will
437 automatically use your renderer everywhere.</p>
438 <h3 id="browser">Browser</h3>
439 <p>Most websites have at least a feature or two that doesn't work on all
440 browsers. For these things, you'd like to know who's asking for a page and send
441 back the best possible version for it.</p>
442 <p>The WebCore's browser detection is a <a href="../browser_detector/">home-grown
443 algorithm</a> and lets you work with <em>capabilities</em> instead of browser
444 types. You don't need to know which browsers support which features, you just
445 ask if a feature is supported and the WebCore takes care of the rest.</p>
446 <p>So it's simple for your pages to ask if a browser handles DHTML. The WebCore
447 takes care of figuring out which browser you're actually using (and the <a href="../browser_detector/">algorithm</a>
448 really is quite good at ignoring spoofing) and knowing which browsers can do
449 what.</p>
450 <h3 id="imaging">Images</h3>
451 <p>A lot of websites post pictures in all sorts of formats. PHP can read the
452 files, figure out how big they are, even resize and reformat them. The WebCore
453 makes all of this functionality accessible and transparent with an image object.
454 You can use it to generate thumbnails of files (JPG or PNG) you've uploaded (like the
455 <a href="#attachments">attachments</a> do), so you don't have that 1280x1024 game screenshot in the middle
456 of your news page. The WebCore applications use the image library to seamlessly
457 offer robust attachments; Albums uses it to make uploading pictures a snap.</p>
458 <p>WebCore images can also automatically extract EXIF information, so all of the
459 information stored by your digital camera doesn't go lost when you add a picture
460 to your site. The WebCore even extracts some EXIF information on older versions
461 of PHP that don't have native EXIF support.</p>
462 <h3 id="icons">Icons and Avatars</h3>
463 <p>You're probably thinking "icons ... big deal".</p>
464 <p>Take a look at any desktop application; there are icons everywhere. You want
465 to make sure you can use icons for labels, buttons and just about everywhere.
466 You don't really want to refer to a specific image file; what if you want to
467 change it at some point?</p>
468 <p>The WebCore defines 'sets' of icons, which can be coordinated with <a href="#skinning">themes</a>
469 to provide a consistent look to your application. You can use <a href="text_formatting.php#paths">paths</a>
470 to refer to these icon resources and make sure you get the right one.</p>
471 <p>The WebCore comes with two sets of icons: a set of GIFs and a set of PNGs.
472 You can add your own to these sets or make a whole new one. There is a whole
473 framework for adding new avatar icons via browser and objects like folders and
474 users have a predefined field for their icon.</p>
475 <h3 id="printing">Printing</h3>
476 <p>As mentioned in <a href="#skinning">skinning</a>, earthli templates use strict CSS for all
477 rendering and display. That makes printing a snap and all renderers and objects are
478 "print-aware" and optimize their rendering for print formats. Print lists or items
479 or just a single one. Making your own objects print nicely is a breeze using the
480 library support.</p>
481 <h3 id="rss">RSS</h3>
482 <p>In addition to <a href="#publishing">publishing</a> by email, earthli applications
483 can be published as RSS feeds. Folder and application home pages have default feeds which
484 are recognized by most modern browsers (shows up as a blue RSS icon in the address bar).
485 Making new ones is easy, as there are base classes for rendering the feed itself and for
486 rendering WebCore objects in a feed. The default implementation simply uses the existing
487 HTML renderers, so any object you can display in a page can be published in an RSS feed
488 instantly. All earthli applications have excellent-looking RSS feeds without any extra
489 work whatsoever.</p>
490 <h3 id="archives">Archives</h3>
491 <p>It's likely that an attachment or an upload is a zip file. The WebCore provides
492 an easy-to-use callback-based API that makes displaying, extracting and working
493 with archives easy. Even if PHP doesn't have the necessary extraction functions,
494 the WebCore uses a third-party library to read the zip file. Your software doesn't
495 change depending on PHP version - it neither knows nor cares which version is used.</p>
496 <p><a href="#attachments">Attachments</a> use the zip libraries to display the list
497 of files inside an uploaded archive. Albums uses them to provide multi-image batch
498 uploading. The batch job extracts each file from the archive, generates a thumbnail
499 using the <a href="#imaging">image</a> library and create a picture entry in the
500 database.</p>
501 <h2>Where to?</h2>
502 <h3 id="future">The future</h3>
503 <p>A product like the earthli WebCore is never finished. There are always things
504 that could be done better or cool features that could be added. Here are some
505 that we're aware of:</p>
506 <ul>
507 <li>Multi-language support in all templates and text.</li>
508 <li>Add a web-interface for administration. Configuration is still done only
509 through config files written in PHP. A user-friendly admin interface to set the
510 myriad available parameters would be helpful.</li>
511 <li>Quizzes and voting supported in an application. As soon as you want quizzes,
512 you have to ask "who gets to make/edit quizzes? ... can users comment on quizzes?
513 " and you realize you need to define these in an application context too. Here's
514 where you can use <a href="#sharing">sharing</a> to tightly integrate with
515 another application.</li>
516 <li>Categories/keywords for objects for improved searching.</li>
517 <li>A moderation system for rating objects/comments/etc. A rudimentary vote
518 gathering system would be good for a start. Almost any application could use a "what
519 did you think about this item?" feature. Moderation-specific permissions could
520 be easily integrated.</li>
521 <li>User tracking -- who's online, how much you've been online, when you were
522 last online. What's new since you last browsed here. Also a pretty low-level
523 feature that any application should be able to snap in.</li>
524 <li>User permissions assignable by group. Groups assignable to groups.</li>
525 </ul>
526 <p>As you can see, once you start thinking about library vs. applications, you
527 can think of a lot of features that aren't really application-specific. Isn't it
528 much cooler to implement integrated moderation when you know it's going to be
529 used in <em>any</em> application instead of just one?</p>
530 <p>And remember, the earthli WebCore and applications are <a href="license.php">open
531 source</a>, so feel free to <a href="download.php">download</a> and pitch in!</p>
532 </div>
533 <div class="right-sidebar">
534 <h2>Your content</h2>
535 <ul>
536 <li><a href="#users">Users</a></li>
537 <li><a href="#folders">Folders</a></li>
538 <li><a href="#comments">Comments</a></li>
539 <li><a href="#attachments">Attachments</a></li>
540 <li><a href="#history">History</a></li>
541 <li><a href="#searching">Searching</a></li>
542 <li><a href="#lists">Lists</a></li>
543 <li><a href="#drafts">Drafts</a></li>
544 </ul>
545 <h2>Making it work</h2>
546 <ul>
547 <li><a href="#environment">Environment</a></li>
548 <li><a href="#security">Security</a></li>
549 <li><a href="#database">Database</a></li>
550 <li><a href="#storage">Storage</a></li>
551 <li><a href="#trash_can">Trash can</a></li>
552 <li><a href="#locations">Locations</a></li>
553 <li><a href="#forms">Forms</a></li>
554 <li><a href="#upload">Uploads</a></li>
555 <li><a href="#publishing">Publishing</a></li>
556 <li><a href="#sharing">Sharing</a></li>
557 <li><a href="#customizing">Customization</a></li>
558 </ul>
559 <h2>Making it look good</h2>
560 <ul>
561 <li><a href="#skinning">Skinning</a></li>
562 <li><a href="#munger">Text formatting</a></li>
563 <li><a href="#rendering">Rendering</a></li>
564 <li><a href="#browser">Browser</a></li>
565 <li><a href="#imaging">Images</a></li>
566 <li><a href="#icons">Icons and Avatars</a></li>
567 <li><a href="#printing">Printing</a></li>
568 <li><a href="#rss">RSS</a></li>
569 <li><a href="#archives">Archives</a></li>
570 </ul>
571 <h2>Where to?</h2>
572 <ul>
573 <li><a href="#future">The future</a></li>
574 </ul>
575 </div>
576 </div>
577 </div>
578 <?php $Page->finish_display (); ?>
579