BEdita | Semantic Content Management Framework - bloghttp://www.bedita.com/menu/blogBEdita dev blogengFrontend Application Flow and callback methodsTo help the frontend developers BEdita comes with a series of callback methods that allowing to filter and handling data. Understanding how the flow of frontend applications works and which callbacks the developer has in hand is one of the fundamental things to start developing a custom frontend<hr/><p>To fit variegate needs that you can encounter developing a frontend application, BEdita comes with a series of callback methods that allowing to find and handling data. Before having a look at this callbacks let's go to see what happens in a standard frontend flow.</p> <p><strong>note:</strong> the <em style="color: grey">italic grey text parts</em> referred to the next BEdita 3.1 version. In BEdita 3.0.x series is missing.</p> <h2>Frontend Application Flow</h2> <p>Supposing we have a BEdita publication reachable from <code>http://www.example.com</code> and we want to see the contents of a section with nickname <em>section-1</em>. In browser address bar we'll write</p> <p><code>http://www.example.com/section-1</code></p> <p>Everything that doesn't start with <em>pages</em> is handled by <strong>route</strong> method that decide what to do. So if you have a custom method in Pages Controller you can call it in standard CakePHP mode</p> <p><code>http://www.example.com/pages/myCustomMethod</code></p> <p><strong>route</strong> method gets first parameters passed by URL (in our case <em>section-1</em>), check if it's a reserved word as defined in configuration files and eventually try to call method with that name. So you could put in your <strong>bedita-app/config/bedita.cfg.php</strong> the reserved word <em>myCustomMethod</em></p> <p><code>$config["cfgReservedWords"] = array("myCustomMethod");</code></p> <p>and call directly <code>http://www.example.com/myCustomMethod</code></p> <p>If none reserved word is found then BEdita consider the parameter a nickname, check if it corresponding to a section object or not and call respectively <strong>section</strong> method or <strong>content</strong> method. These two methods will load all section and contents data and set to view the array <code>$section</code>.</p> <p>Finally the view is rendered.</p> <h2>Callback Methods</h2> <p>There are two (<em style="color: grey;">four in the next 3.1 release</em>) main callbacks always called that can be used to insert logic before or after controller actions:</p> <ul> <li><em style="color: grey;"><strong style="color: grey;">beforeCheckLogin</strong> (present from next 3.1 release) called by FrontendController::initAttributes method is executed before check login operation is performed. It's useful if you want to skip the user check login operation for specific items setting to true the AppController::$skipCheck attribute. Note that the checkLogin method is called before beditaBeforeFilter.<br /></em></li> <li><strong>beditaBeforeFilter</strong> called by AppController::<strong>beforeFilter</strong>&nbsp; method is executed before every action in the controller;</li> <li><strong>beditaBeforeRender </strong>called by<strong> </strong>AppController::<strong>beforeRender </strong>method is executed after controller action but before view is rendered.</li> <li><em style="color: grey;"><strong style="color: grey;">beditaAfterFilter</strong> (present from next 3.1 release) called by AppController::afterFilter method is executed after the render is done. It's the last thing made by controller.</em></li> </ul> <p>In addition some specific callbacks are called if respective method exists. When a reserved word is found a callback <strong>[reservedWord]BeforeFilter</strong> (<em>my_custom_methodBeforeFilter</em>) is called before reservedWord method and another callback <strong>[reservedWord]</strong><strong>BeforeRender</strong> (<em>my_custom_methodBeforeRender</em>) is called soon after reservedWord method.</p> <p>Similar callbacks are handled in <strong>section</strong> method using the section <em style="color: grey;">(and content from next 3.1 release)</em> nickname replacing <em>"-"</em> with <em>"_"</em> in method name, i.e. <strong>[section-nickname]</strong><strong>BeforeFilter</strong> <em style="color: grey;">(and <strong style="color: grey;">[content-nickname]BeforeFilter</strong> from next 3.1 release)</em> and <strong>[section-nickname]BeforeRender</strong> <em style="color: grey;">(and <strong style="color: grey;">[content-nickname]BeforeRender</strong> from next 3.1 release)</em>. In our example the callbacks will be <em>section_1BeforeFilter()</em> and <em>section_1BeforeRender()</em>.</p> <p>So you can define these callback methods in Pages Controller to customize punctually the way to find results and manipulate the <code>$section</code> array before render view.</p> <p>In particular the <strong>[section-nickname]</strong><strong>BeforeFilter</strong> callback can be used to set parameters and class attributes to put the section method in the condition to find the expected result. For example changing the <code>FrontendController::$sectionOptions</code> attribute like you can see in the blog posts "Customizing Frontend Applications" part <a title="Customizing Frontend Applications [part 1]: divide objects by type in a section" href="http://bedita.com/blog/customizing-frontend-applications-part-1-divide-objects-by-type-in-a-section">1</a>, <a title="Customizing Frontend Applications [part 2]: how to load only selected content in a section" href="http://bedita.com/blog/customizing-frontend-applications-part-2-load-only-selected-content">2</a> and <a title="Customizing Frontend Applications [part 3]: time for pagination" href="http://bedita.com/blog/customizing-frontend-applications-part-3-time-for-pagination">3</a> you can paginate sections' contents, group BEdita objects for type, etc... .</p> <p>Instead the <strong>[section-nickname]</strong><strong>BeforeRender</strong> callback usually can be used to manipulate the $section array that is setted in section method (you can find it in $this-&gt;viewVars["section"]).</p> <h2>Recap</h2> <p>The frontend flow of a section/content request can be sumarized in this way:</p> <ol> <li>browser request</li> <li><em style="color: grey;">call <strong style="color: grey;">beforeCheckLogin</strong> method (from 3.1 BEdita version)</em></li> <li>call <strong>beditaBeforeFilter</strong> method</li> <li>routing section/content method through <strong>route</strong> method</li> <li>if exists call <strong>[section-nickname]BeforeFilter</strong> method</li> <li><em style="color: grey">if exists and content is requested call <strong>[content-nickname]BeforeFilter</strong> method (from 3.1 BEdita version)</em></li> <li>recover section and content data by nickname</li> <li>if exists call <strong>[section-nickname]BeforeRender</strong> method</li> <li><em style="color: grey">if exists and content is requested call <strong style="color: grey">[content-nickname]BeforeRender</strong> method (from 3.1 BEdita version)</em></li> <li>call <strong>beditaBeforeRender</strong> method</li> <li>render view</li> <li><em style="color: grey;">call <strong style="color: grey">beditaAfterFilter</strong> method (from 3.1 BEdita version)</em></li> </ol>Mon, 22 Feb 2010 17:38:12 +0100http://www.bedita.com/menu/blog/frontend-application-flow-and-callback-methodshttp://www.bedita.com/menu/blog/frontend-application-flow-and-callback-methodsCustomizing Frontend Applications [part 3]: time for paginationPaginating items in a frontend application<hr/><p>The third episode of our <em>"Customizing Frontend Applications"</em> saga will be focused on pagination. Sooner or later each web developer/designer working on a web site will have to deal with contents pagination.<br />BEdita comes with an easy way to do it, allowing a default pagination setting for the entire frontend application and/or a specific one for each section you want.</p> <p>Once again we'll use the <code>FrontendController::$sectionOptions</code> attribute, in particular we are interested in <strong>childrenParams</strong> key.</p> <p>Overriding this class attribute in our PagesController we can set a default pagination for all our sections.</p> <p><code> protected $sectionOptions = array(<br />&nbsp;&nbsp;&nbsp; "showAllContents" =&gt; true, <br />&nbsp;&nbsp;&nbsp; "itemsByType" =&gt; false, <br />&nbsp;&nbsp;&nbsp; "childrenParams" =&gt; array(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "order" =&gt; "title", <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "dim" =&gt; 10, <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "dir" =&gt; true<br />&nbsp;&nbsp;&nbsp; )<br />); </code></p> <p>In this way we are saying to show 10 items for page sorting by title<sup><a href="#note1">[1]</a></sup> in ascendant mode. Set dir to false to reverse the order of items. The coupple <code>"page" =&gt; 1</code> is implied but if you want to show your items starting from page 2 you can add it to childrenParams.</p> <p><strong>Change page, sort or page dimension is very very simple</strong>. We can use the named params convention used by CakePHP, so</p> <p><strong>http://www.example.com/section-1/page:2</strong></p> <p>will switch automagically to page 2 and similary we can change the order</p> <p><strong>http://www.example.com/section-1/order:created</strong></p> <p>the order direction</p> <p><strong>http://www.example.com/section-1/dir:0</strong></p> <p>or several things at once</p> <p><strong>http://www.example.com/section-1/page:2/dir:0</strong></p> <p>The only thing you can do it at this point is build your toolbar pagination and to do this you have a toolbar array available inside <code>$section</code> array, for example:</p> <p><code> [toolbar] =&gt; Array (<br />&nbsp;&nbsp;&nbsp; [first] =&gt; 1<br />&nbsp;&nbsp;&nbsp; [prev] =&gt; 1<br />&nbsp;&nbsp;&nbsp; [next] =&gt; 3<br />&nbsp;&nbsp;&nbsp; [last] =&gt; 5<br />&nbsp;&nbsp;&nbsp; [size] =&gt; 9<br />&nbsp;&nbsp;&nbsp; [pages] =&gt; 5<br />&nbsp;&nbsp;&nbsp; [page] =&gt; 2<br />&nbsp;&nbsp;&nbsp; [dim] =&gt; 2<br />&nbsp;&nbsp;&nbsp; [start] =&gt; 3<br />&nbsp;&nbsp;&nbsp; [end] =&gt; 4<br /> )</code></p> <p>where</p> <ul> <li><strong>first</strong> is equal to 0 if we are in the first page</li> <li><strong>prev</strong> is the previous page</li> <li><strong>next</strong> is the next page</li> <li><strong>last</strong> is the last page and is equal to 0 when we are in the last page</li> <li><strong>size</strong> is the total number of items</li> <li><strong>pages</strong> is the total number of pages available</li> <li><strong>page</strong> is the current page number</li> <li><strong>dim</strong> is the dimension of items for page</li> <li><strong>start</strong> is the numeric position of first current page's item</li> <li><strong>end</strong> is the numeric position of last current page's item</li> </ul> <p>So you could build your own helper to show the pagination toolbar or you can use the <a title="API doc" href="http://api.bedita.com/classBeToolbarHelper.html" target="_blank">BeToolbar</a> helper of BEdita core.</p> <h2>Change the default pagination for a section</h2> <p>As usual (if you have read the previous articles <a title="Customizing Frontend Applications [part 1]: divide objects by type in a section" href="/blog/customizing-frontend-applications-part-1-divide-objects-by-type-in-a-section" target="_self">1</a>-<a title="Customizing Frontend Applications [part 2]: how to load only selected content in a section" href="/blog/customizing-frontend-applications-part-2-load-only-selected-content" target="_self">2</a>) you can change the default <code>$sectionOptions["childrenParams"]</code> attribute for a specific section thorugh out the <strong>section-nicknameBeforeFilter</strong> callback.</p> <p>That's it for now.</p> <p>&nbsp;</p> <p><em><sup><a name="note1">[1]</a></sup> Note that "title" is a field of "objects" table used by BEObject model, so if you want to be sure to avoid ambiguous fields you should specify the model field you want to order by i.e. </em><code>"order" =&gt; "BEObject.title</code><em><code>"</code>. We'll see in other post how to filter the selection of items using <strong>"filter"</strong> key in <strong>"childrenParams"</strong>. This filter can be build using fields of other tables that can collide with BEObject fields.</em></p> <p><em><br /></em></p>Mon, 22 Feb 2010 10:41:22 +0100http://www.bedita.com/menu/blog/customizing-frontend-applications-part-3-time-for-paginationhttp://www.bedita.com/menu/blog/customizing-frontend-applications-part-3-time-for-paginationCustomizing Frontend Applications [part 2]: how to load only selected content in a sectionImprove speed performance by narrowing your requests to the API<hr/><p>While programming, you can request the content of a certain section by URL, with something like&nbsp;<strong>http://www.example.com/section-nickname/content-nickname</strong>. The requested content is loaded into the&nbsp;<code>$section["currentContent"]</code> array, while more content &ndash; actually every content in the same section &ndash; is placed into the&nbsp;<code>$section["childContents"]</code> array. This additional content is loaded in "<em>base level mode"</em> (cfr. the API manual, "baseLevel"), which means that only basic informations about various objects are given (such as the title, the description, its ID and a few more).</p> <p>Now this is indeed useful in standard scenarios: when you are showing a particular&nbsp;<em>content</em> and listing, at the same time, related contents in the same section. Imagine you are showing an article and you want to put links to more contents in a contextual menu. This is common, but sometimes you are interested only in a single object, while you don't really need to load all related stuff.</p> <p>In these cases you can improve the data loading performance by excluding this additional content (you actually give up the option of having also&nbsp;<code>$section["childContents"]</code> array). Obviously the improvement will be much more evident when that particular section is burdened, it has got many objects inside.</p> <p>However, moving forward into the discussion started in the previous article <a href="http://staging.bedita.com/blog/customizing-frontend-applications-part-1-divide-objects-by-type-in-a-section" target="_blank">"Customizing Frontend Applications [part 1]: divide objects by type in a section"</a>, we're going to use the Frontend Controller attribute <code>$sectionOptions</code>. This time too, <strong>we may proceed in two different ways, the choice depending on whether we want a custom behavior for a specific section (1) or alternatively we prefer to modify the default behavior for the whole frontend application (2)</strong>.</p> <p>So I'm showing you both:</p> <h3>1. Custom behavior for a section&nbsp;</h3> <p>Like we did in the previous post, we are going to use the <strong>nicknameBeforeFilter</strong> callback: It is automatically&nbsp;called before section data are loaded, so in the controller:</p> <p><code>protected function section-nicknameBeforeFilter() {<br />&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;sectionOptions["showAllContents"] = false;<br />}</code></p> <p>(pay attention to change "section-nickname" with the exact nickname of your section).</p> <p>&nbsp;</p> <h3>2. Change the default behavior</h3> <p>To change the way the API answers to requests, edit your Pages Controller. You have to change the&nbsp;<code>$sectionOptions</code> attribute, by setting the <span style="font-weight: bold; font-family: 'Courier New', Courier, monospace;">showAllContents</span> property to <span style="font-style: italic; font-family: 'Courier New', Courier, monospace;">false</span>:</p> <p><code>protected $sectionOptions = array("showAllContents" =&gt; false, "itemsByType" =&gt; false, "childrenParams" =&gt; array());</code></p> <p>When&nbsp;<strong>showAllContents</strong>&nbsp;is set to <strong>false</strong>, we say to the API to not load all related content when a specific content is requested.</p>Fri, 27 Nov 2009 13:16:47 +0100http://www.bedita.com/menu/blog/customizing-frontend-applications-part-2-load-only-selected-contenthttp://www.bedita.com/menu/blog/customizing-frontend-applications-part-2-load-only-selected-contentCustomizing Frontend Applications [part 1]: divide objects by type in a sectionOrganize your BEdita objects in $section array to have a semantic separation of contents.<hr/><p>With this post we start a series of documents that explain how customize your frontend application for all your needs.</p><hr/><p>In any <em>Frontend Application</em> the standard organization of contents in a section reflects the backend visualization. So, supposing to have a section named "section 1" structured like in <em>figure 1</em>, we'll have in frontend view the array <code>$section</code> with different content types mixed together</p> <p><code> Array(</code><code><br />&nbsp;&nbsp;&nbsp; [id] =&gt; section 1<br />&nbsp;&nbsp;&nbsp; [nickname] =&gt; section-1<br />&nbsp;&nbsp;&nbsp; ....<br />&nbsp;&nbsp;&nbsp; [childContents] =&gt; Array(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [0] =&gt; Array(...)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [1] =&gt; Array(...)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .....&nbsp;&nbsp;&nbsp; )<br />)</code></p> <p>This is ok in many situation i.e. when I want to list contents in sequential order, but&nbsp;when I want contents to assume a specific behavior based on their semantic meaning this structure is limited.</p> <p>In every object array I have a key named <strong>object_type</strong> that identify the type of the item (Document, Event, Gallery, etc...) so we can iterate the $childContents array and check that key to choose the right behavior. But this is not a good practice in some situations: for example if I want that in a 3 columns layout documents are shown in the first column, events in the second and galleries in the third column. Infact I should iterate the <em>childContents</em> array three times. Another example could be this one: we don't know which types of objects are in a section but we want that everyone behave differently.</p> <p>In these cases the <code>$sectionOptions</code> attribute of the FrontendController class comes to help us.</p> <h3>The first solution: semantic separation for all sections</h3> <p>In this first case we want that in our frontend application the objects inside every section are divided by type. To do this we will override the <code>$sectionOptions</code> attribute in Pages Controller like this</p> <p><code> class PagesController extends FrontendController {<br /><br />&nbsp;&nbsp;&nbsp; protected $sectionOptions = array("showAllContents" =&gt; true, "itemsByType" =&gt; true, "childrenParams" =&gt; array());<br /><br />.....<br />} </code></p> <p>setting <strong>itemsByType</strong> to true we force BEdita objects inside a section to be divided by object type. Instead of <strong><em>"chidContents"</em> </strong>we'll have <strong><em>"children"</em> </strong>array</p> <p><code>Array(</code><code><br />&nbsp;&nbsp;&nbsp; [id] =&gt; section 1<br />&nbsp;&nbsp;&nbsp; [nickname] =&gt; section-1<br />&nbsp;&nbsp;&nbsp; ....<br />&nbsp;&nbsp;&nbsp; [children] =&gt; Array(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Document] =&gt; Array(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [0] =&gt; Array(...)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [1] =&gt; Array(...)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Event] =&gt; Array(...)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .....<br />&nbsp;&nbsp;&nbsp; )<br />)</code></p> <h3>The second solution: semantic division only for that section</h3> <p>In this case we'll use the <strong>nicknameBeforeFilter</strong> callback called automatically before section data are loaded (note that "-" char in nickname is replaced with "_" in method name)</p> <p><code>protected function section_1BeforeFilter() {<br />&nbsp;&nbsp;&nbsp;&nbsp; $this-&gt;sectionOptions["itemsByType"] = true;<br />}<br /></code></p> <p>The result will be an array like that above.</p>Mon, 16 Nov 2009 12:08:24 +0100http://www.bedita.com/menu/blog/customizing-frontend-applications-part-1-divide-objects-by-type-in-a-sectionhttp://www.bedita.com/menu/blog/customizing-frontend-applications-part-1-divide-objects-by-type-in-a-sectionEmbedding multimedia objects<p>The BeEmbedMedia helper is used to create and display every type of multimedia object as <strong>Video</strong>, <strong>Audio</strong>, <strong>Image</strong>, <strong>Application</strong> (like Flash object) or generic multimedia file (<strong>BEFile</strong>). This helper is always included in backend AppController, as well as in every frontend application by inheritance, so inserting a video, a Flash swf file or an image is as easy as using a CakePHP helper. The helper uses <a href="http://flowplayer.org" target="_blank">Flowplayer</a> as internal flash player for native visualization of video and audio objects but also allow the embedding of provider players when there's no direct link to <em>flv</em> file (i.e youtube see figure 1, 2). <br />Let's see how:<br /><br />Essentially <strong>this helper provides a function called "object"</strong> that works generically for any Bedita object:<br /><br /><code>public function object ( $obj, $params = null, $htmlAttributes=array() )</code><br /><br />The <code>$obj</code> parameter represent the BEdita object that has to be displayed in the frontend. Generically in your view code, you'll have a multidimensional array:<br /><br /><code>$section["currentContent"]["relations"]["attach"]</code><br /><br />which contains a list of all related media objects, i.e. all the media objects which share a "<strong>relation"</strong> of type "<strong>attach"</strong> with <strong>"currentContent"</strong> inside the <strong>"section"</strong>.</p> <h2>$params</h2> <p><code>$params</code> represent an array of specific parameters related to the type of object to display. There's few parameters handled internally by BEdita. The main of those is <strong>"presentation"</strong> params which define how the multimedia objects have to be shown. This parameter has a default value for any multimedia object so while for an image object will be create a thumbnail, for video object will be loaded the flash player.<br /><br />You can force presentation type passing the value in <code>$params</code> associative array. It can be <strong>"thumb"</strong> , <strong>"full"</strong> or <strong>"link"</strong>.<br />For example, the code:<br /><br /> <code> {assign_associative var="params" presentation="thumb" width=200 mode="crop"}<br />{foreach from=$section.currentContent.relations.attach item="media"}<br />{$beEmbedMedia-&gt;object($media,$params)} <br />{/foreach}</code><br /><br />Will try to show the contents of array "attach" with thumbnails, regardless of the specific object. For example in case of a video object, will display the associated thumbnail if present, while in case of an image stored on BEdita, will try to generate thumbnail runtime or reusing a thumbnail previously created. <br /><br />The <strong>"presentation=full"</strong> type will display the full visualizzation of the object embedding directly the video or the audio or the images object.<br />The code:</p> <p><code>{assign_associative var="params" presentation="full"}</code><br /><code>{foreach from=$section.currentContent.relations.attach item="media"}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {$beEmbedMedia-&gt;object($media,$params)}<br />&nbsp;&nbsp; {/if}<br />{/foreach}</code><br /><br />Will try to display the video and audio object type with the internal default player, if <strong>"useProviderPlayer"</strong> variable is present in <code>$params</code> the function will try to embed the object using directly the related provider player. The image object type will be shown in their real dimension using the original file uploaded.<br /><br />Moreover, <code>$params</code> can contain object-specific parameters such as <strong>flashvar</strong> variables for customize Flowplayer or, more generically, any type of variable that is required to displaying multimedia objects. <br />For examples:<br /><br /><code>{assign_associative var="clips" autoPlay=true}<br />{assign_associative var="flashVars" clip=$clips}<br />{assign_associative var="params" flashvars=$flashVars}<br />{foreach from=$section.currentContent.relations.attach item="media"}<br />&nbsp;&nbsp;&nbsp; {$beEmbedMedia-&gt;object($media,$params)}<br />{/foreach}</code><br /><br />Enable the <strong>autoplay</strong> function, when display a video with flowplayer.<br /><br />The <strong>"presentation=link"</strong> parameter will produce a well formatted anchor pointing to the resource itself, with the title of the object inserted inside anchor tag.<br />Finally the <strong>URLonly</strong> parameter will force the helper to return only the URL, that can be useful when you want use manually the <code><img alt="" /></code> "img" tag.<br /><br /><code>{assign_associative var="params" presentation=link URLonly=true}<br />{foreach from=$section.currentContent.relations.attach item="media"}<br />&nbsp;&nbsp; &lt; img src="{$beEmbedMedia-&gt;object($media,$params)}" alt="" /&gt;<br />{/foreach}</code></p> <h2>$htmlAttributes</h2> <p>The <code>$htmlAttributes</code> represents the html parameters of the embedding object. Here you can specify all the html attributes like <code>rel</code>, <code>width</code>, <code>height</code>, <code>id</code>, etc...</p> <p>&nbsp;</p> <p>These was just an overview of the main features of the BeEmbedMedia helper, you can try by yourself all options and eventually ask help on the official <a href="http://forum.bedita.com" target="_blank">forum</a>. Some useful links are reported in the right column.</p>Mon, 28 Sep 2009 17:49:14 +0200http://www.bedita.com/menu/blog/embedding-media-objecthttp://www.bedita.com/menu/blog/embedding-media-objectBEdita shell: introducing command line tools<p>Command line tools are an important (and not known) part of the BEdita framework.<br />There are many commands available to accomplish many tasks:</p> <ul> <li>export or import a complete instance</li> <li>send notification mails or newsletter</li> <li>create a new BEdita instance</li> <li>check instance status</li> <li>remove cache and compiled templates<br /></li> </ul> <h2>How do I use them?<br /></h2> <p>There is a simple shell/batch script (cake.sh for Linux/Max/Unix cake.bat for Windows) to launch those tasks.<br />Point to the root BEdita directory with the command line where you have bedita-app, bedita-db, cake, vendors directories.</p> <p>Under Linux or MacOSX (or other UNIX-like systems) type:</p> <p><code>./cake.sh bedita help</code></p> <p>Under Windows</p> <p><code>cake.bat bedita help</code><br /><br />You will get some informations and usage hints regarding the main <strong>bedita</strong> script.<br />Now you can play with this script and discover what services it provides.</p> <p>To name a few (without cake.sh/bat):</p> <ul> <li><code>bedita cleanup</code> - cache and compiled templates cleanup </li> <li><code>bedita export/import</code> - exports or imports a complete BEdita instance</li> <li><code>bedita modules</code> - adds/removes instance modules</li> <li><code>bedita checkApp</code> - checks application status, missing config files, db connections, checks main URLs, paths and permissions on filesystem</li> </ul> <p>Besides the main script (<strong>bedita</strong>) there are other BEdita shell tools available:</p> <ul> <li><em><strong>dbadmin</strong></em>: some methods to check/fix some db data, some to insert test objects</li> <li><em><strong>gettext</strong></em>: parses views/php files, extracts i18n entries and updates .po files (gettext format)<br /></li> <li><em><strong>mail</strong></em>: sends notification mail and newsletters</li> <li><em><strong>migrate</strong></em>: data migration scripts from previous BEdita versions</li> <li><em><strong>newsletter</strong></em>: some newsletter related tools (data import)<br /></li> </ul>Wed, 22 Jul 2009 17:33:22 +0200http://www.bedita.com/menu/blog/bedita-shell-introducing-command-line-toolshttp://www.bedita.com/menu/blog/bedita-shell-introducing-command-line-toolsHow to manage free semantic relations<p>One of the most powerful features of <strong>BEdita</strong> is the possibility to define and use <em>free semantic relations between objects</em>. In this article I'm going to show you how build and use them.</p> <h2>BEdita objects</h2> <p><strong>BEdita is completely object-oriented, </strong>so every element of it is an object with a specific <strong>object type</strong>. The object type itself defines some particular behaviors like the possibility to be showed in a certain module, the possibility to stay in the tree structure and the way to relate with other object types. You can find the BEdita object types inside the table <strong>object_types</strong> that contains <em>id</em>, <em>name</em> and <em>module</em> fields. To create a new relations we'll use the <em>id</em> of the object types.</p> <h2>Where do I define relations between objects?<br /></h2> <p>The first thing to know is that these relations have to be defined in a configuration file, in particular in <code>bedita-app/config/bedita.cfg.php</code>. You can find some default relations in <code>bedita-app/config/bedita.ini.php</code> but this file shouldn't be touched (may be overwritten during an update of BEdita), so have a look at the relations in this file only as reference.</p> <p>In <code>bedita.cfg.php</code> you can find the configuration variable <code>$config["objRelationType"]</code> commented. Uncomment it and let's customize your relations.<br /><strong>Choose a name</strong> for your relations for example <em>"speakers"</em>:</p> <p><code> $config["objRelationType"] = array(<br />&nbsp;&nbsp; "speakers" =&gt; array()<br />);</code></p> <p>In this way I'm going to define a free relation named <em>"speakers"</em> that can link all objects. Now go to <strong>Addressbook</strong> module (this module use Card objects, as you can see in object_types table) and click on create <em>"new card"</em>. Have a look at <strong>Relationship tab</strong> and you can see that the new relation appears in it (<em>figure 1</em>).<br />Now you can click on <em>"Connect new items"</em> button to link other objects to this one, change order of related objects by drag &amp; drop (<em>figure 2</em>) and then save the card to estabilish the relation.</p> <p>In this way we have defined the relation for all object types so if you look at other modules like Documents, Events, Galleries, etc... you'll find the <em>"speakers"</em> relation in the <strong>Relationship tab</strong>. But if I want that the relation is estabilished only between some objects, how can I do it?</p> <h2>Customizing a relation between some object types</h2> <p>Suppose that I have to manage a festival site. I can create all festival events thorugh <strong>Events module</strong> and all people that partecipate to the festival through <strong>Addressbook module</strong>. Some of this people will be speakers so I will have to associate the events to the cards of the speakers through the <em>"speakers"</em> relation. I want to use my <em>"speakers"</em> relation only to link events to cards, I don't want to see and to use this relation in Galleries module, for instance. Edit <code>$config["objRelationType"]</code> in this way:</p> <p><code>$config["objRelationType"] = array(</code><code><br />&nbsp;&nbsp; "speakers" =&gt; array(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "left" =&gt; array(34),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "right" =&gt; array(21)<br />&nbsp;&nbsp; )<br />);</code></p> <p>Here I define that the <em>"speakers"</em> relation is estabilished between some object types. On the left I have card objects (<code>34</code> is the <code>id</code> of card in object_types table) and on the right I have event objects (<code>id=21</code>). Note that the order of the object types in <em>"left"</em>, <em>"right"</em> key is indifferent. <br />In this way only in Events and Addressbook mdoules you can see <em>"</em><em>speakers</em><em>"</em> in <strong>Relationship tab</strong>.</p> <p>If you want to use this relation for other object types it's enough add <em>ids</em> to <em>"left"</em> or <em>"right"</em> key so, for example:</p> <p><code>$config["objRelationType"] = array(</code><code><br /> &nbsp;&nbsp; "speakers" =&gt; array(<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "left" =&gt; array(34),<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "right" =&gt; array(21,22)<br /> &nbsp;&nbsp; )<br /> );</code></p> <p>With this definition I can associate documents and events from a card object and I can associate only cards from a document or an event object.</p> <h2>One way relations</h2> <p>The relations are built in both directions by default, so I can see the association from both the objects involved. In some rare case I could to desire that the relation is showed only in one direction. In these cases we can build a one way relation always editing <code>bedita.cfg.php</code> file.</p> <p><code>$config["cfgOneWayRelation"] = array("speakers", "other one way relation");</code></p> <p>Now if I create a <em>"speakers"</em> relation from card to event I will see the relation inside the card object but I will not see it inside the event object.</p> <h2>Relations in frontend</h2> <p>As explained in <a href="http://bedita.com/bedocs/il-primo-frontend">"My first frontend"</a> you'll find the semantic relations between objects in an <strong>array named</strong> <strong>"relations"</strong> so for example in an event related with some card by <em>"speakers"</em> relation I will have</p> <p><code>[relations] =&gt; Array ( </code><code>&nbsp;&nbsp; <br />&nbsp;&nbsp; [speakers] =&gt; array(0 =&gt; card1, 1 =&gt; card2, ....)</code></p> <h2>At the end</h2> <p>At the end of this article you should be able to build your custom semantic relations between objects in simple or complex way to model your <strong>BEdita</strong> instance according to your needs.</p>Fri, 29 May 2009 18:08:58 +0200http://www.bedita.com/menu/blog/how-manage-free-semantic-relationshttp://www.bedita.com/menu/blog/how-manage-free-semantic-relationsHallo BEditaThe first public beta is here!<hr/><p>After two years of hard work we are really pleased to announce the first public beta release of BEdita 3 (pronounced [bi'&epsilon;dita]): a framework for Web2.0 applications that aims to be a standard tool in the next <a title="Web 3.0" href="http://www.scribd.com/doc/2021419/A-More-Revolutionary-Web-Print-Version-International-Herald-Tribune" target="_blank">Web3.0</a> and in the future <a title="Semantic Web" href="http://www.w3.org/2001/sw/" target="_blank">Semantic Web.</a></p> <p>As you may already know, the <em>beta </em>is here <a title="BEdita 3.0 - latest release" href="http://www.bedita.com/be-download" target="_self">http://www.bedita.com/be-download</a></p> <h3><strong>Framework or CMS?</strong><br /></h3> <p><a title="BEdita.com" href="http://www.bedita.com" target="_blank"><strong>BEdita</strong></a> shares many aspects with a&nbsp; <a title="CMS" href="http://www.contentmanager.eu.com/history.htm" target="_blank">CMS (Content Management Systems)</a>, often we call it that way for simplicity, in fact it follows its definition (at least in part): <em>a tool that enables technical and non technical staff to create, edit, manage and finally publish a variety of content (such as text, graphics, video, documents etc). </em>But on the <em>publishing</em> side it doens't have, <em>on purpose</em>, a default unique and finished/ready solution.</p> <p>A good definition of <a title="what is a framework?" href="http://blog.newtonicaonline.com/2008/12/06/what-is-framework" target="_blank">software </a><a title="what is a framework?" href="http://blog.newtonicaonline.com/2008/12/06/what-is-framework" target="_blank">framework </a>may help us understand things better: a <em>framework is </em><em><strong>incomplete, </strong>though concrete, <strong>driving solution </strong>to recurring <strong>high-value </strong>problem<strong>. </strong></em>BEdita actually is:</p> <ol> <li><em>incomplete</em>&ndash; it's not a software that can solve needs/problems of a standard <em>user</em>; instead it's a powerful tool for [web]designers/[web]developers to build <em>frontend </em>applications;</li> <li><em>driving solution to recurring high-value problem</em> &ndash; it's useful in every situation where you may want to create applications (<em>frontend</em>)<em> </em>that handle complex multimedia contents and their semantic relations; for a designer/developer it prevents to challenge and solve typical annoying related issues. </li> </ol> <h3><strong>Architecture<br /></strong></h3> <p>Two are the main elements of the <em>semantic framework</em>:</p> <ol> <li>a <em>backend </em>Web application to manage contents and their semantic relations, with an innovative ergonomic user interface, providing an original chromatic association between object types, extensive use of drag'n'drop and other AJAX techniques; </li> <li>a frontend API, services and specifications to build frontend applications; mainly Web apps, but also desktop/mobile apps taking advantage of its native REST/XML interface. </li> </ol> <p>The <strong>backend</strong> application is unique and the same for every setup or instance, instead more <strong>frontend </strong>applications can be built using an <strong>API </strong>and inheriting from the core system<strong> Model classes and business logic layer</strong>: they can be made of few lines of PHP code, or they can be much more complex. This separation is a choice made for security reasons, efficiency, scalability and to let maximum freedom to the designer/developer.</p> <p>&nbsp;</p>Wed, 13 May 2009 16:33:28 +0200http://www.bedita.com/menu/blog/hallo-beditahttp://www.bedita.com/menu/blog/hallo-bedita