Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - CMS and E-Commerce

830 Articles
article-image-installing-and-using-openfire
Packt
21 Oct 2009
6 min read
Save for later

Installing and Using Openfire

Packt
21 Oct 2009
6 min read
The Openfire instant messaging server is very easy to install. In fact, it's totally newbie-proof. So much so, that unlike other complex server software, even if you've never setup up Openfire before, you'll be able to get it up and running on your first try. If you're sceptical, by the time we are done with this short article, we'll have ourselves a fully-functional Openfire server that will register users and connect with clients. Preparing Your System Openfire is a cross-platform server and can be installed under Linux, Solaris, Mac, or Windows operating system environments. Openfire reserves its enormity for its users. When it comes to system requirements, Openfire is very suave and a perfect gentleman who has very moderate demands. You don't need to spend much time preparing your system for installing Openfire. Just pick out the environment you're comfortable with—Windows or one of the popular Linux distributions such as Fedora, Debian, or Ubuntu, and you're good to go. You don't have to run around getting obscure libraries or worry about mismatched versions. But like any hard-working gentleman, Openfire has a thing for caffeine, so make sure you have Java on your system. No need to run to the kitchen—this isn't the Java in the cupboard. Openfire is written in the Java programming language, so it'll need a Java Runtime Environment (JRE) installed on your system. A JRE creates a simple (breathable, so to say) environment for Java applications to live and function in. It's available as a free download and is very easy to install. If you're installing under Windows, just skip to the "Installing Under Windows" section later in the article. Linux Users Get Your Cuppa! Sun's Java Runtime Environment is available as a free download from Sun's website (http://www.java.com/en/download/linux_manual.jsp) or it can also be installed from your distribution's software management repositories. Users of RPM-based systems can safely skip this section because the Openfire installer for their distribution already includes a JRE. On the other hand, users of Debian-based systems such as Ubuntu will have to install the JRE before installing Openfire. Thanks to the popular apt-get package management system, there isn't much to installing the JRE. Because Sun's JRE isn't free and is also not an open source software, most Linux distributions make the JRE package available in their non-free tree. If the following command doesn't work, check out the detailed installation instructions for your specific distribution, at  https://jdk-distros.dev.java.net. Open a console and issue the following command: $ sudo apt-get install sun-java6-jre Now the apt-get system will automatically fetch, install, and activate the JRE for you! Meet The Protagonists This article is about making sure that you have no trouble installing one file. This one file is the Openfire installer and it is available in multiple flavors. The four flavors we're concerned with aren't as exotic as Baskin Robbins' 31 flavors but that doesn't make the decision any easier. The Openfire project releases several installers. The four flavors we're concerned with are: Openfire-3.5.2-1.i386.rpm: RPM package for Fedora Linux and other RPM-based variants Openfire_3.5.2_all.deb: DEB package for Debian, Ubuntu Linux and their derivates Openfire_3_5_2.tar.gz: Compressed "tarball" archive that'll work on any Linux distribution Openfire_3_5_2.exe: Openfire installer for Windows We'll cover installing Openfire from all of these files, so that you may use Openfire from your favorite Linux distribution or from within Windows. Just to reiterate here, the Windows installer and the RPM Linux installer both bundle the JRE, while the other other versions do not. The Actual Install-Bit Alright, so you have the Java JRE setup and you've downloaded the Openfire installer. In this section, we'll install Openfire server from the various versions we discussed in the last section. Let's first install from the source tarball. The first step when dealing with .tar.gz source archive is to extract the files. Let's extract ours under /tmp and then move the extracted directory under /opt. # tar zxvf openfire_3_5_2.tar.gz# mv openfire /opt Now we'll create a non-priviledged user and group for running Openfire. # groupadd openfire# useradd -d /opt/openfire -g openfire openfire Next, we'll change ownership of the openfire/directory to the newly-created user and group. # chown -R openfire:openfire /opt/openfire Believe it or not, that's it! You've just installed Openfire server. Surprised? Get ready for more. It gets even simpler if you install using the precompiled RPM or DEB binaries. In the case of RPM, Openfire is installed under /opt/openfire and in case of the DEB file, Openfire resides under /etc/openfire. On RPM-based systems such as Fedora and its derivates (as root), use: # rpm -ivh openfire-3.5.2-1.i386.rpm On DEB-based systems such as Debian, Ubuntu, and so on, use: $ sudo dpkg -i openfire_3.5.2_all.deb Voila! You're done. Now, who thought my "installing Openfire is totally newbie-proof" comment was an exaggeration? Running Openfire on Linux/Unix So, we now have Openfire on our favourite Linux distribution, whichever distribution this may be. Now it's time to fire it up and get going. Depending on how you installed Openfire, the procedure to start it varies a little. If you've installed Openfire from the RPM or DEB, you'll be pleased to know that the Openfire developers have already done most of the hard work for you. These binaries contain some custom handling for the RedHat/Debian-like environments. You can start and stop Openfire just like any other service on your system: # /etc/init.d/openfire startStarting Openfire: You can also view the other options available: # /etc/init.d/openfireUsage /etc/init.d/Openfire {start|stop|restart|status|condrestart|reload} On the other hand, if you've installed Openfire using the .tar.gz archive, you can start and stop Openfire using the bin/openfire script in your Openfire installation directory. First, change to the user that owns the /opt/openfire directory: # su - openfire# cd /opt/openfire/bin/# ./openfire startStarting Openfire And now you have Openfire up and running! If you are using a firewall, which you most probably are, make sure to forward traffic on ports 5222 and 5223 (for SSL) which clients use for connecting with the Openfire server. Also forward traffic on port 7777 for file transfer. Linux users can skip the next section on installing Openfire under Windows and move directly to the section that discusses the preliminary Openfire setup.
Read more
  • 0
  • 0
  • 5933

article-image-ajax-dynamic-content-and-interactive-forms
Packt
21 Oct 2009
7 min read
Save for later

AJAX / Dynamic Content and Interactive Forms

Packt
21 Oct 2009
7 min read
Essentially, AJAX is an acronym for Asynchronous JavaScript and XML, and it is the technique of using JavaScript and XML to send and receive data between a web browser and a web server. The biggest advantage this technique has is that you can dynamically update a piece of content on your web page or web form with data from the server (preferably formatted in XML), without forcing the entire page to reload. The implementation of this technique has made it obvious to many web developers that they can start making advanced web applications (sometimes called RIAs—Rich Interface Applications) that work and feel more like software applications, instead of like web pages. Keep in mind that the word AJAX is starting to have its own meaning (as you'll also note its occasional use here as well as all over the web as a proper noun, rather than an all-cap acronym). For example, a Microsoft web developer may use VBScript instead of JavaScript to serve up Access Database data that is transformed into JSON (not XML) using a .NET server-side script. Today, that guy's site would still be considered an AJAX site, rather than an AVAJ site (yep, AJAX just sounds cooler). In fact, it's getting to the point where just about anything on a website (that isn't in Flash) that slides, moves, fades, or pops up without rendering a new browser window is considered an 'Ajaxy' site. In truth, a large portion of these sites don't truly qualify as using AJAX, they're just using straight-up JavaScripting. Generally, if you use cool JavaScripts in your WordPress site, it will probably be considered 'Ajaxy', despite not being asynchronous or using any XML. Want more info on this AJAX business? The w3schools site has an excellent introduction to AJAX, explaining it in straight-forward, simple terms. They even have a couple of great tutorials that are fun and easy to accomplish, even if you only have a little HTML, JavaScript, and server-side script (PHP or ASP) experience (no XML experience required) (http://w3schools.com/ajax/). You Still Want AJAX on Your Site? OK! You're here and reading this article because you want AJAX in your WordPress site. I only ask you take the just discussed into consideration and do one or more of the following to prepare. Help your client assess their site's target users first. If everyone is web 2.0 aware, using newer browsers, and are fully mouse-able, then you'll have no problems, AJAX away. But if any of your users are inexperienced with RIA (Rich Interface Application) sites or have accessibility requirements, take some extra care. Again, it's not that you can't or shouldn't use AJAX techniques, just be sure to make allowances for these users. You can easily adjust your site's user expectations upfront, by explaining how to expect the interface to act. Again, you can also offer alternative solutions and themes for people with disabilities or browsers that can't accommodate the AJAX techniques. Remember to check in with Don't Make Me Think, that Steve Krug book I for help with any interface usability questions you may run into. Also, if you're really interested in taking on some AJAX programming yourself, I highly recommend AJAX and PHP by Cristian Darie, Bogdan Brinzarea, Filip Chereches-Tosa, and Mihai Bucica. In it, you'll learn the ins and outs of AJAX development, including handling security issues. You'll also do some very cool stuff like make your own Google-style auto-suggest form and a drag-and-drop sortable list (and that's just two of the many fun things to learn in the book). So, that said, you're now all equally warned and armed with the knowledgeable resources I can think to throw at you. Let's get to it; how exactly do you go about getting something 'Ajaxy' into your WordPress site? Plug-ins and Widgets In these next few sections we're going to cover plug-ins and widgets. Plug-ins and widgets are not a part of your theme. They are additional files with WordPress compatible PHP code that are installed separately into their own directories in your WordPress installation (again, not in your theme directory). Once installed, they are available to be used with any theme that is also installed in your WordPress installation. Even though plug-ins and widgets are not the part of your theme, you might have to prepare your theme to be compatible with them. Let's review a bit about plug-ins and widgets first. Plug-ins WordPress has been built to be a lean, no frills publishing platform. Its simplicity means that with a little coding and PHP know-how, you can easily expand WordPress's capabilities to tailor to your site's specific needs. Plug-ins were developed so that even without a little coding and PHP know-how, users could add extra features and functionality to their WordPress site painlessly, via the Administration Panel. These extra features can be just about anything—from enhancing the experience of your content and forms with AJAX, to adding self-updating 'listening/watching now' lists, Flickr feeds, Google Map info and Events Calendars; you name it, someone has probably written a WordPress plug-in for it. Take a look at the WordPress Plug-in page to see what's available: http://wordpress.org/extend/plugins/ Widgets Widgets are basically just another plug-in! The widget plug-in was developed by AUTOMATTIC (http://automattic.com/code/widgets/), and it allows you to add many more kinds of self-updating content bits and other useful 'do-dads' to your WordPress site. Widgets are intended to be smaller and a little more contained than a full, stand-alone plug-in, and they usually display within the side bar of your theme (or wherever you want; don't panic if you're designing a theme without a sidebar). If you're using WordPress version 2.2 and up, the widget plug-in has become a part of WordPress itself, so you no longer need to install it before installing widgets. Just look through the widget library on WordPress's widget blog and see what you'd like! (http://widgets.wordpress.com/) Trying to download Widgets but the links keep taking you to Plug-in download pages? You'll find that many WordPress Widgets 'piggyback' on WordPress Plug-ins, meaning you'll need the full plug-in installed in order for the widget to work or the widget is an additional feature of the plug-in. So don't be confused when searching for widgets and all of a sudden you're directed to a plug-in page. WordPress Widgets are intended to perform much the same way Mac OS's Dashboard Widgets and Windows Vista Gadgets work. They're there to offer you a quick overview of content or data and maybe let you access a small piece of often used functionality from within a full application or website, without having to take the time to launch the application or navigate to the website directly. In a nutshell, widgets can be very powerful, while at the same time, just don't expect too much. Getting Your Theme Ready for Plug-ins and Widgets In this article, we'll take a look at what needs to be done to prepare your theme for plugins and widgets. Plug-in Preparations Most WordPress Plug-ins can be installed and will work just fine with your theme, with no extra effort on your part. You'll generally upload the plug-in into your wp_content/plugins directory and activate it in your Administration Panel. Here are a few quick tips for getting a plug-in displaying well in your theme: When getting ready to work with a plug-in, read all the documentation provided with the plug-in before installing it and follow the developer's instructions for installing it (don't assume just because you've installed one plug-in, they all get installed the same way). Occasionally, a developer may mention the plug-in was made to work best with a specific theme, and/or the plug-in may generate content with XHTML markup containing a specific CSS id or class rule. In order to have maximum control over the plug-in's display, you might want to make sure your theme's stylesheet accommodates any id or class rules the plug-in outputs. If the developer mentions the plug-in works with say, the Kubrick theme, then, when you install the plug-in, view it using the Kubrick theme (or any other theme they say it works with), so you can see how the plug-in author intended the plug-in to display and work within the theme. You'll then be able to duplicate the appropriate appearance in your theme.
Read more
  • 0
  • 0
  • 2348

article-image-customizing-plugins-joomla-15x-part-2
Packt
21 Oct 2009
8 min read
Save for later

Customizing Plugins in Joomla! 1.5x (Part 2)

Packt
21 Oct 2009
8 min read
Step 2: Plan out our changes Just like with our module, we are going to be systematic about our customization. This keeps us organized and reduces the chances for mistakes. Really, these changes are so simple we could probably just dive in and do them, but we want to build good habits for when we want to customize more complex extensions. Step 2.1: Decide on our changes Our plugin is going to be essentially the same, hiding or showing parts of our content depending on a particular condition. Only we want to change it so the condition we use is user's subscription and not their user group. We will need to put in some code to search the database for the visitor's subscription information. We also want to clean out any code we don't need, such as the description HTML page and images. We will go a little bit further and rename our extension and functions. One day we may want to distribute this plugin to get some traffic to our site, and help other developers like ourselves. Also, seeing as we are going to rebuild most of this plugin, let's put a short description in to remind us what it is for, or in case we hire another developer to help with our site later, they can see what it does. Step 2.2: Mark out our changes Remember that before we actually make our changes, we want to go through the code and mark them with comments first. This way we are forced to think the whole process through from start to finish before we write any code, and we can see any potential problems before they happen. This beats finding them after we have spent a few hours writing code, and wasting that time going back to repair them. en-GB.plg_content_njaccess.ini First, we are going to edit our language file, en-GB.plg_content_njaccess.ini. If we were making a complex component, we would usually keep the language file open the entire time, and add new entries to it every time we wanted to put some text onto the screen. But our plugin is pretty much a 'behind the scenes' plugin so we don't need much text. So what text do we need? Well, as we discussed above, when we hide some content from a user, we probably want to display a message that tells them that it has been hidden, and that they should get a subscription to read it. We also want to remove the current rich description and replace it with simpler, normal text. So let's add a note to our current code, NINJACONTENT=<IFRAME SRC="../plugins/content/njaccess/njaccess_desc.html" WIDTH=600 HEIGHT=600 FRAMEBORDER=0 SCROLLING=yes></IFRAME> that tells us to delete it completely. Then we will add a note to write our description and message in its place. # TODO-Remove thisNINJACONTENT=<IFRAME SRC="../plugins/content/njaccess/njaccess_desc.html" WIDTH=600 HEIGHT=600 FRAMEBORDER=0 SCROLLING=yes></IFRAME># TODO-Add plain text description# TODO-Add message for hidden text Wait a minute! What are these hashes? We haven't seen them before. Up until now we were told that comments were either double slashes (//), enclosing slash asterisks (/* … */), or for HTML some long tags (<!-- … -->). Well, .ini files are different from our .php files, and are processed differently. As a result, they use a different symbol to indicate for comments. So now, we can add # to our list of comment symbols, but for .ini (language) files only. njaccess.php Next, open up njaccess.php. As we are basically re-writing this plugin, we might as well change the name of this file and all the functions to something more relevant. // TODO-Rename this file// Ensure this file is being included by a parent file. defined('_JEXEC') or die( "Direct Access Is Not Allowed" );jimport('joomla.eventplugin');// TODO- Rename the class to match our new filenameclass plgContentNJaccess extends JPlugin {// TODO- Rename this constructorfunction plgContentNJaccess( &$subject ){... We don't have any parameters, so we can remove the parameter loading from the constructor. ...parent::__construct( $subject );// TODO-Remove these as we have no need for parameters$this->_plugin = JPluginHelper::getPlugin( 'Content','ninjaacess' );$this->_params = new JParameter( $this->_plugin->params );} We are renaming everything, so we should rename our regex tags and the function call via preg_replace_callback as well. function onPrepareContent(&$article, &$params, $limitstart) {// TODO- Adjust our regex to look for a shorter tag// and one collector function between the tags$regex = "#{njaccess(.*?)}(.*?){/njaccess}#s";// TODO- Rename the function call$article->text = preg_replace_callback($regex,array($this,"njaccess"), $article->text);return true;}// TODO- Rename the functionfunction njaccess(&$matches) { We also want to remove any references to the ACL. We do want to continue to load the user information though, as we need their user id (if logged in) to compare it to the subscriptions in the AEC tables. $user = &JFactory::getUser();// TODO- Remove the next 3 lines as we don't need ACL$acl = &JFactory::getACL();$myRealGid = intval( $acl->get_group_id( $user->usertype ) );$accessLevels = ''; We are only going to have one collector pattern now, so only one set of information, the text to be shown/hidden, needs to be collected. To do this, we need to change all the references to $matches[2] into $matches[1] and remove the old $matches[1] checks. // TODO-change this to matches[1] as we only have// one collector now$output= $matches[2];// TODO-Remove thisif (@$matches[1]) {$accessLevels = explode(",", trim($matches[1]));} Lastly, we need to replace the main processing with a query to check our visitor's user id against the AEC subscription tables for an active paying subscription. // TODO-Replace this with a query searching for the// user's id in the subscriptions table, searching// for a paying subscriptionif (in_array($myRealGid,$accessLevels))return $output;// TODO- Get the visitor's id if available.// If a guest (id = 0) then skip this and display// the please subscribe message// TODO- Look for the id in the AEC subscriptions// table, and check if they have a valid, paid// subscription. If so, return the text// if not, skip it and return the message// TODO- Instead of blank, return our message from our// language filereturn "";}} njaccess.xml Finally, we come to our njaccess.xml file. Comments can be made into XML files in the same way as HTML <!-- … -->. For our XML manifest, we have a few things to do. At first, we want to rename everything from njaccess, including the manifest itself. <?xml version="1.0" encoding="utf-8"?><install version="1.5" type="plugin" group="content"><!-- TODO- Rename this file and plugin --><name>Ninja Access</name><author>Daniel Chapman</author><creationDate>February 2008</creationDate><copyright>(C) 2008 Ninja Forge</copyright><license>http://www.gnu.org/copyleft/gpl.html GNU/GPL</license><authorEmail>daniel@ninjaforge.com</authorEmail><authorUrl>www.ninjaforge.com</authorUrl> Also, let's change the version number of our new plugin to 1.0. Then change the description as well, to suit what we put into our language file. <!-- TODO- Change to 1.0 --><version>1.1</version><!-- TODO- Change to match our language file --><description>NINJACONTENT</description> Then, we want to remove all the unnecessary files from the description <!-- TODO- Remove unneeded files --><files><filename plugin="njaccess">njaccess.php</filename><filename>njaccess/njaccess_desc.html</filename><filename>njaccess/js/ninja.js</filename><filename>njaccess/images/logo.jpg</filename><filename>njaccess/images/ninjoomla.png</filename><filename>njaccess/images/firefox2.gif</filename><filename>njaccess/images/jcda.png</filename><filename>njaccess/images/validation_xhtml.png</filename><filename>njaccess/images/validation_css.png</filename><filename>njaccess/images/info.png</filename><filename>njaccess/images/change.png</filename><filename>njaccess/images/inst.png</filename><filename>njaccess/images/tabbg.gif</filename><filename>njaccess/images/tab2.png</filename><filename>njaccess/images/gnugpl.png</filename></files> Finally, rename the reference to our language file to suit the new filename: <params></params><!-- TODO- Rename the language file --><languages><language tag="en-GB">en-GB.plg_content_njaccess.ini</language></languages></install>
Read more
  • 0
  • 0
  • 1662

article-image-social-bookmarking-mediawiki
Packt
21 Oct 2009
4 min read
Save for later

Social Bookmarking - MediaWiki

Packt
21 Oct 2009
4 min read
Traditionally, bookmarking was done through Internet browsing software, such as Internet Explorer, Safari, Firefox, or Opera. With social bookmarking, your bookmarks are not confined to one browser, but are stored online. The following two options are available for enabling social bookmarking on your website: Link to each individual social bookmarking service that you wish to use Use a social bookmarking aggregator such as Socializer or AddThis Even if you do not have links to allow visitors to bookmark your website, many services allow their users to install toolbars in their browser, which allows your website to be added anyway. Adding these links will help to spread your wiki and its new skin very fast. Individual Social Bookmarking Services There are huge numbers of social bookmarking services on the Internet, and quite a number of these have become reasonably popular. We will look at some of the more popular bookmarking services such as: Mister Wong Furl Facebook Your Wiki's Audience One thing to consider before adding social bookmarking service links to your wiki is your audience. For instance, if your wiki is technology-related, you may find it better to use Digg than Facebook, as Digg is more popular than Facebook for your wiki's intended audience. If your wiki's visitors are primarily from Germany, you may find Mister Wong more useful than Furl, because Mister Wong is more popular with the German users. There are many other social bookmarking services available, including Del.icio.us (http://del.icio.us) and StumbleUpon (http://stumbleupon.com), which you can use after asking your wiki's visitors by means of a poll, or following simple experimentation. Example of Audience durhamStudent (http://durhamStudent.co.uk) is a niche website aimed at students of Durham University in the UK: The durhamStudent website uses both the methods of social bookmarking discussed earlier, providing links for eKstreme's Socializer and a link to an individual bookmarking service, Facebook: Facebook was linked individually here because it is incredibly popular among the students at Durham University (indeed, the Durham network is only open to those with a university email address). Although Facebook's bookmarking service is accessible through Socializer, it is also linked separately as the website's target audience is more likely to use that service than any other. Mister Wong Mister Wong, http://www.mister-wong.com, is popular with German and other European users (though not so much in Great Britain), and allows the users to store their bookmarks while maintaining their privacy, with the ability to set bookmarks as "public" or "private". Generally, the social bookmarking services ask for two pieces of information when creating a link from your website to them: the URL (address) of the page or website you want to add, and the title of that page or website, as you wish it to be posted. Linking to Mister Wong To link to Mister Wong, create a link where you want your social bookmark to be shown in your MediaWiki template in the following format: http://www.mister-wong.com/index.php?action=addurl&bm_url=www.example. com &bm_description=Your+Website Spaces are automatically escaped with a "+" sign by the majority of social bookmarking services. You don't have to worry about properly escaping spaces in the title of your link when linking to bookmarking services. To use these services with MediaWiki, we will be required to use some PHP. In particular, we will need the following: The page's title, which we can get with <?php $this->text('pagetitle') ?>. The website's address, retrievable with <?php $this->urlencode('serverurl') ?>. For simplicity, we will assume that our visitors will always want to bookmark JazzMeet's homepage, http://www.jazzmeet.com. Thus, the code in our MediaWiki template would appear as follows: <a href= "http://www.mister-wong.com/index.php?action=addurl&bm_url=www.jazzmeet.com &bm_description=JazzMeet" title="Bookmark JazzMeet with Mister Wong">Bookmark JazzMeet with Mister Wong</a> What Mister Wong Users See If a visitor to your wiki decides to bookmark your wiki with Mister Wong, they will be greeted with a screen similar to the following, with fields for the address of the website (URL), title, related keywords ("tags"), and a comment about the website: They are also given the option to bookmark as either "public", allowing other Mister Wong users to see it, or "private", which restricts the bookmarked website to their account only.
Read more
  • 0
  • 0
  • 2078

article-image-customizing-plugins-joomla-15x-part-1
Packt
21 Oct 2009
9 min read
Save for later

Customizing Plugins in Joomla! 1.5x (Part 1)

Packt
21 Oct 2009
9 min read
The code used in this article can be downloaded from here. Plugin composition and operation     Like a module, in its simplest form, a plugin can consist of only two files, a PHP file with the actual code for the plugin, and an XML manifest that tells Joomla! what to do with the plugin. Despite this apparent simplicity, plugins are very powerful, and more difficult to understand than modules and components. Plugins are designed to run at certain times during the execution of our site, and they perform actions that can only be done at these times. For example, in our sample site we want to hide some of our content from guests, and only show it to paid subscribers. This action can only be performed when we are actually preparing the content to be displayed, because we need to wait until we identify if the viewer is a guest or subscriber, and then make the changes to the content dynamically. In a different example, checking if a subscriber's subscription is valid is something that only needs to be done when they try to login, and not on every page load. Plugin types Plugins are divided into eight types, as follows: Authentication Content Editors Editors-XTD Search System User XML-RPC Authentication Authentication plugins are designed to allow the site to check the user's authentication against a variety of sources. The default is to check the user's authentication against a username and password stored in the Joomla! database, which, as of Joomla! 1.5, will be the username and password fields in the #__user table (#__ is the table prefix we chose when setting up Joomla!). However, any source with a public API can be used to verify someone's authentication details. Common uses are LDAP, OpenID, a Google account, a subscription, community component, and more. On our site, for example, we are already using an authentication plugin to verify the subscriptions of users when they attempt to login. Content Possibly the most commonly used of all plugins, content plugins allow content items to be modified or have additional features added to them. We could, for example, use content plugins to cloak email addresses, embed audio or video into our pages, or do text replacements. We can even embed components and modules into our pages via plugins. We will later look at a content plugin that we will use to hide and show content depending on a user's subscription. Editors Editors plugins add WYSIWYG editors that we can use when editing our content. We installed JCE on our site earlier, which is the most popular Joomla! editor plugin as of this publication according to Joomla.org. Editors-XTD Editors-XTD (extended) plugins allow us to add additional buttons to the editors. The Image, Read more, and Pagebreak buttons on the default Joomla! WYSIWYG editor, for example, are actually plugins. Search Search plugins allow us to search through the data from different components. By default, Joomla! comes with plugins that search through content articles and the Contacts and Weblinks components. These can be expanded upon by creating or installing search plugins for other extensions. System System plugins are arguably the most powerful and most flexible types of plugins for Joomla!, as they can execute at several different pre-defined points during the execution of a Joomla! page plugin. They can be used to perform a vast array of functions, such as loading extra scripts or CSS into the header of a web page, redirecting people away from pages, logging statistics, and more. User User plugins allow us to perform actions at different times with respect to users. Such times include logging in and out, and also when saving changes to a user's profile. User plugins are often used to create a "bridge" between Joomla! and other web applications (such as the phpBB forum or the osCommerce e-commerce platform.). XML-RPC XML-RPC plugins are for communicating between our Joomla! site and other external applications, such as a desktop application or a different web site. Plugin events As a Joomla! site loads a page, it steps through a series of events as part of that process. The events it steps through are determined by the type of page it is loading. Plugins are always tied to one or more of these events, and are executed during those events as required. When loading a page of content, for example, we would step through a mix of the system and some of the content events. When loading the same page for editing, we will step through the system events, different content events, and also possibly editor events. The events triggered in Joomla! are: Authentication onAuthenticate Content onPrepareContent onAfterDisplayTitle onBeforeDisplayContent onBeforeContentSave onAfterContentSave Editors onInit onGetContent onSetContent onSave onDisplay onGetInsertMethod Editors XTD (Extended) onDisplay Search onSearch onSearchAreas System onAfterInitialise onAfterRoute onAfterDispatch onAfterRender User onLoginUsexr onLoginFailure onLogoutUser onLogoutFailure onBeforeStoreUser onAfterStoreUser onBeforeDeleteUser onAfterDeleteUser XML-RPC onGetWebServices Most of these events are easy to understand from their name, but just in case, more information can be found on the Joomla! documentation wiki at http://docs.joomla.org/CategoryPlugins. Some events are only activated at specific times, such as onAuthenticate, which is only activated when someone logs into their account. Others are activated on every page load. Content events are activated on all content pages and only on content pages, not on pages with components other than com_content. Content plugins are also only executed on the main body content itself and don't have access to the template or other module data. So a text replacement content plugin, for example, wouldn't change any text in modules or the template, only in the main content itself. It is actually possible for modules and components to manually activate plugin events with clever programming, but this is not the default Joomla! behavior. It is usually done when a developer wants to apply content plugin restrictions/changes to a module. Plugin order Aside from the events and types, there is a third important factor to consider when setting up our plugins. That is the order in which the plugins of a particular type are executed. This order is best observed on the Plugin Manager screen that can be found under the Extensions menu. The order in which the plugins execute is something not many people think about, but is really quite powerful and useful. This is because the plugins which execute later, can then use the output or effects of the earlier executing plugins as input. For example, imagine we have a plugin that displays different text for different user types, and we have another plugin that reads certain text values and replaces them with embedded video or audio. If we wanted to be able to show different videos to different groups, then we could use the first plugin to generate the different command strings for the second plugin, and have it generate them based on the user type. The second plugin, our media embedding plugin, doesn't even know that the first plugin exists. All it knows is which videos it needs to display based on what is in the content item. If the media plugin executes first, then it will generate both videos regardless of the user type. As another example, imagine we have some sort of external application and we log users into it after they authenticate via an authentication plugin. We need to make sure that this plugin is executed after all of our other authentication plugins that may check a user's credentials or account status. Otherwise, someone may get logged into our external application even though they were prevented from login into our Joomla! site. So a hacker, for example, could get access to our external application without needing to even successfully get into our main site. This was all because we had the order of our plugins wrong. So when we install and activate plugins, it is well worth taking the time to double check that everything happens in the order it is meant to be in. If one of our plugins is not behaving how it should, it might be worth checking the order to see if another plugin is conflicting with it. Customizing a Plugin Now that we have a better understanding of how our plugins work and fit together, we are going to try our hand at customizing one for our site. This will hopefully give us the understanding and confidence to make any other customizations we need in the future. As with modules, it is often easier to find a plugin that does most of what we want it to do and then make changes to it so that it meets our needs more completely. Looking back over our goals, one that requires a plugin is that we want to limit access to certain parts of our content to only our paying subscribers. This effect is going to be best achieved via content plugin, so we chose the Ninja Access plugin to fill this need. To use Ninja Access we first need to mark the content we want to restrict with special tags and indicate the user groups we want to see what is contained within the tags. When the page is produced, the plugin reads the visitor's user group and then compares it to the ones in the list provided by the tag. If the user groups match, then the content is displayed, if not, then it is hidden. For example: {njaccess 0}shows only to guest users{/njaccess}{njaccess 18,19,20,21,23,24,25}shows to all users who are not a guest{/njaccess} The numbers in the examples above indicate the default Joomla! user group ids. The most important ones are: 0 = Guests 18 = Registered 24 = Administrators 25 = Super Administrators We could use this as it is, but as we don't have a component installed to create new access groups, it won't be very flexible. We could get into trouble in the future if we decide to let people register without getting a subscription, or create a free subscription. In this instance, we will have paying and free subscribers all in the number 18 user group. Also, as we are always going to be restricting the same groups, we don't really need to type the parameters in every single time. Making our plugins always restrict the same groups automatically will save us some time and reduce mistakes. Lastly, do we really need to type njaccess every time? Let's shorten it to something like soc—subscriber only content. For our first dilemma, a better idea than groups might be to associate the access to certain AEC subscriptions that are currently active. That way if people's subscriptions expire, or they get a free account, the content is still properly controlled regardless of their user groups.
Read more
  • 0
  • 0
  • 2042

article-image-building-crud-application-zk-framework
Packt
21 Oct 2009
5 min read
Save for later

Building a CRUD Application with the ZK Framework

Packt
21 Oct 2009
5 min read
An Online Media Library There are some traditional applications that could be used to introduce a framework. One condition for the selection is that the application should be a CRUD (Create —Read—Update—Delete) application. Therefore, an 'Online Media Library', which has all four operations, would be appropriate. We start with the description of requirements, which is the beginning of most IT projects. The application will have the following features: Add new media Update existing media Delete media Search for the media (and show the results) User roles (administrator for maintaining the media and user accounts for browsing the media) In the first implementation round the application should only have some basic functionality that will be extended step by step. A media item should have the following attributes: A title A type (Song or Movie) An ID which could be defined by the user A description An image The most important thing at the start of a project is to name it. We will call our project ZK-Medialib. Setting up Eclipse to Develop with ZK We use version 3.3 of Eclipse, which is also known as Europa release. You can download the IDE from http://www.eclipse.org/downloads/. We recommend using the version "Eclipse IDE for Java EE Developers". First we have to make a file association for the .zul files. For that open the Preferences dialog with Window | Preferences. After that do the following steps: Type Content Types into the search dialog. Select Content Types in the tree. Select XML in the tree. Click Add and type *.zul. See the result. The steps are illustrated in the picture below: With these steps, we have syntax highlighting of our files. However, to have content assist, we have to take care about the creation of new files. The easiest way is to set up Eclipse to work with zul.xsd. For that open the Preferences dialog with Window | Preferences. After that do the following steps: Type XML Catalog into the search dialog. Select XML Catalog in the tree. Press Add and fill out the dialog (see the second dialog below). See the result. Now we can easily create new ZUL files with the following steps: File | New | Other, and select XML: Type in the name of the file (for example hello.zul). Press Next. Choose Create XML file from an XML schema file: Press Next. Select Select XML Catalog entry. Now select zul.xsd: Now select the Root Element of the page (e.g. window). Select Finish. Now you have a new ZUL file with content assist. Go into the generated attribute element and press Alt+Space. Setting up a New Project The first thing we will need for the project is the framework itself. You can download the ZK framework from http://www.zkoss.org. At the time of writing, the latest version of ZK is 2.3.0. After downloading and unzipping the ZK framework we should define a project structure. A good structure for the project is the directory layout from the Maven project (http://maven.apache.org/). The structure is shown in the figure below. The directory lib contains the libraries of the ZK framework. For the first time it's wise to copy all JAR files from the ZK framework distribution. If you unzip the distribution of the version 2.3.0 the structure should look like the figure below. The structure below shows the structure of the ZK distribution. Here you can get the files you need for your own application. For our example, you should copy all JAR files from lib, ext, and zkforge to the WEB-INF/lib directory of your application. It's important that the libraries from ext and zkforge are copied direct to WEB-INF/lib. Additionally copy the directories tld and xsd to the WEB-INF directory of your application. Now after the copy process, we have to create the deployment descriptor (web.xml) for the web application. Here you can use web.xml from the demo application, which is provided from the ZK framework. For our first steps, we need no zk.xml (that configuration file is optional in a ZK application). The application itself must be run inside a JEE (Java Enterprise Edition) Webcontainer. For our example, we used the Tomcat container from the Apache project (http://tomcat.apache.org). However, you can run the application in each JEE container that follows the Java Servlet Specification 2.4 (or higher) and runs under a Java Virtual Machine 1.4 (or higher). We create the zk-media.xml file for Tomcat, which is placed in conf/Catalina/localhost of the Tomcat directory. <Context path="/zk-media" docBase="D:/Development/workspaces/workspace-zk-medialib/ZK-Medialib/src/main/webapp" debug="0"privileged="true" reloadable="true" crossContext="false"><Logger className="org.apache.catalina.logger.FileLogger"directory="D:/Development/workspaces/workspace-zk-medialib/logs/ZK-Medialib" prefix="zkmedia-" suffix=".txt" timestamp="true"/></Context> With the help of this context file, we can directly see the changes of our development, since, we set the root of the web application to the development directory.  
Read more
  • 0
  • 0
  • 7568
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-selinux-highly-secured-web-hosting-python-based-web-applications
Packt
21 Oct 2009
10 min read
Save for later

SELinux - Highly Secured Web Hosting for Python-based Web Applications

Packt
21 Oct 2009
10 min read
When contemplating the security of a web application, there are several attack vectors that you must consider. An outsider may attack the operating system by planting a remote exploit, exercising insecure operating system settings, or brandishing some other method of privilege escalation. Or, the outsider may attack other sites contained in the same server without escalating privileges. (Note that this particular discussion does not touch upon the conditions under which an attack steals data from a single site. Instead, I'm focusing on the ability to attack different applications on the same server.) With hosts providing space for large numbers of PHP-based sites, security can be difficult as the httpd daemon traditionally runs under the same Unix user for all sites. In order to prevent these kinds of attacks from occurring, you need to concentrate on two areas: Preventing the site from reading or modifying the data of another site, and Preventing the site from escalating privileges to tamper with the operating system and bypass user-based restrictions. There are two toolboxes you use to accomplish this. In the first case, you need to find a way to run all of your sites under different Linux users. This allows the traditional Linux filesystem security model to provide protection against a hacked site attacking other sites on the same server. In the second case, you need to find a way to prevent a privilege escalation to begin with and barring that, prevent damage to the operating system should an escalation occur. Let's first take a look at a method to run different sites under different users. The Python web framework provides several versatile methods by which applications can run. There are three common methods: first, using Python's built-in http server; second, running the script as a CGI application; and third, using mod_python under Apache (similar to what mod_perl and mod_php do). These methods have various disadvantages: respectively, a lack of scalability, performance issues due to CGI application loading, and the aforementioned “all sites under one user” problem. To provide a scalable, secure, high-performance framework, you can turn to a relatively new delivery method: mod_wsgi. This Apache module, created by Graham Dumpleton, provides several methods by which you can run Python applications. In this case, we'll be focusing on the “daemon” mode of mod_wsgi. Much like mod_python, the daemon mode of mod_wsgi embeds a Python interpreter (and the requisite script) into a httpd instance. Much like with mod_python, you can configure sites based on mod_wsgi to appear at various locations in the virtual directory tree and under different virtual servers. You can also configure the number and behavior of child daemons on a per-site basis. However, there is one important difference: with mod_wsgi, you can configure each httpd instance to run as a different Linux user. During operation, the main httpd instance dispatches requests to the already-running mod_wsgi children, producing performance results that rival mod_python. But most importantly, since each httpd instance is running under a different Linux user, you can apply Linux security mechanisms to different sites running on one server. Once you have your sites running on a per-user basis, you should next turn your attention to preventing privilege escalation and protecting the operating system. By default, the Targeted mode of SELinux provided by RedHat Enterprise Linux 5 (and its free cousins such as CentOS) provides strong protection against intrusions from httpd-based applications. Because of this, you will need to configure SELinux to allow access to resources such as databases and files that reside outside of the normal httpd directories. To illustrate these concepts, I'll guide you as you install a Trac instance under mod_wsgi. The platform is CentOS 5. As a side note, it's highly recommended that you perform the installation and SELinux debugging in a XEN instance so that your environment only contains the software that is needed. The sidebar explains how to easily install the environment that was originally used to perform this exercise, and I will assume that is your primary environment. There are a few steps that require the use of a C compiler – namely, the installation of Trac – and I'll guide you through migrating these packages to your XEN-based test environment. Installing Trac In this example, you'll use a standard installation of Trac. Following the instructions provided in the URL in the Resource section, begin by installing Trac 0.10.4 with ClearSilver 0.10.5 and SilverCity 0.9.7. (Note that with many Python web applications such as Trac and Django, “installing” the application means that you're actually installing the libraries necessary for Python to run the application. You'll need to run a script to create the actual site.) Next, create a PostgreSQL user and database on a different machine. If you are using XEN for your development machine, you can use a PostgreSQL database running in your main DOM0 instance; all we are concerned with is that the PostgreSQL instance is accessed on a different machine over the network. (Note that MySQL will also work in this example, but SQLite will not. In this case, we need a database engine that is accessed over the network, not as a disk file.) After that's done, you'll need to create an actual Trac site. Create a directory under /opt, such as /opt/trac. Next, run the trac_admin command and enter the information prompted. trac-admin /opt/trac initenv Installing mod_wsgi You can find mod_wsgi at the source listed in the Resources. After you make sure the httpd_devel package is installed, installing mod_wsgi is as simple as extracting the tarball and issuing the normal ./configure and 'make install' commands. Running Trac under mod_wsgi If you look under /opt/trac, you'll notice two directories: one labeled apache, and one with the label of the project that you assigned when you installed this instance of Trac. You'll start by creating an application script in the apache directory. The application script is listed in Listing 1. Listing 1: /opt/trac/apache/trac.wsgi #!/usr/bin/python import sys sys.stdout = sys.stderr import os os.environ['TRAC_ENV'] = '/opt/trac/test_proj' import trac.web.main application = trac.web.main.dispatch_request (Note the 'sys.stdout = sys.stderr' line. This is necessary due to the way WSGI handles communications between the Python script and the httpd instance. If there is any code in the script that prints to STDOUT (such as debug messages), then the httpd instance can crash.) After creating the application script, you'll modify httpd.conf to load the wsgi module and set up the Trac application. After the LoadModule lines, insert a line for mod_wsgi: LoadModule wsgi_module modules/mod_wsgi.so Next, go to the bottom of httpd.conf and insert the text in Listing 2. This text configures the wsgi module for one particular site; it can be used under the default httpd configuration as well as under VirtualHost directives. Listing 2: Excerpt from httpd.conf: WSGIDaemonProcess trac user=trac_user group=trac_user threads=25 WSGIScriptAlias /trac /opt/trac/apache/trac.wsgi WSGIProcessGroup trac WSGISocketPrefix run/wsgi <Directory /opt/trac/apache> WSGIApplicationGroup %{GLOBAL} Order deny,allow Allow from all </Directory> Note the WSGIScriptAlias identifier. The /trac keyword (first parameter) specifies where in the directory tree the application will exist. With this configuration, If you go to your server's root address, you'll see the default CenOS splash page. If you add /trac after the address, you'll hit your Trac instance. Save the httpd.conf file. Finally, add a Linux user called trac_user. It is important that this user should not have login privileges. When the root httpd instance runs and encounters the WSGIDaemonProcess directive noted above, it will fork itself as the user specified in the directive; the fork will then load Python and the indicated script.     Securing Your Site In this section, I'll focus on the two areas noted in the introduction: User based security and SELinux. I will touch briefly on the theory of SELinux and explain the nuts and bolts of this particular implementation in more depth. I highly recommend that you read the RedHat Enterprise Linux Deployment Guide for the particulars about how RedHat implements SELinux. As with all activities involving some risk, if you plan to implement these methods, you should retain the services of a qualified security consultant to advise you about your particular situation. Setting up the user-based security is not difficult. Because the HTTPD instance containing Python and the Trac instance will run under the Trac user, you can safely set everything under /opt/trac/test_project for read and execute (for directories) for user and none for group/all. By doing this, you will isolate this site from other sites and users on the system. Now, let's configure SELinux. First, you should verify that your system is running the proper Policy and Mode. On your development system, you'll be using the Targeted policy in its Permissive mode. If you choose to move your Python applications to a production machine, you would run under the Targeted policy, in the Enforcing mode. The Targeted policy is limited to protecting the most popular network services without making the system so complex as to prevent user-level work from being done. It is the only mode that ships with RedHat 5, and by extension, CentOS 5. In Permissive mode, SELinux policy violations are trapped and sent to the audit log, but the behavior is allowed. In enforcing mode, the violation is trapped and the behavior is not allowed. To verify the Mode, run the Security Level Configuration tool from the Administration menu. The SELinux tab, shown in Figure 1, allows you to adjust the Mode. After you have verified that SELinux is running in Permissive mode, you need to do two things. First, you need to change the Type of the files under /opt/trac. Second, you need to allow Trac to connect to the Postgres database that you configured when you installed Trac. First, you need to tweak the SELinux file types attached to the files in your Trac instance. These file types dictate what processes are allowed to access them. For example, /etc/shadow has a very restrictive 'shadow' type that only allows a few applications to read and write it. By default, SELinux expects web-based applications – indeed, anything using Apache – to reside under /var/www. Files created under this directory have the SELinux Type httpd_sys_content_t. When you created the Trac instance under /opt/trac, the files were created as type usr_t. Figure 2 shows the difference between these labels To properly label the files under /opt, issue the following commands as root: cd /optchcon -R -t httpd_user_content_t trac/ After the file types are configured, there is one final step to do: allow Trac to connect to PostgreSQL. In its default state, SELinux disallows outbound network connections for the httpd type. To allow database connections, issue the following command: setsebool -P httpd_can_network_connect_db=1 In this case, we are using the -P option to make this setting persistent. If you omit this option, then the setting will be reset to its default state upon the next reboot. After the setsebool command has been run, start HTTPD by issuing the following command: /sbin/service httpd start If you visit the url http://127.0.0.1/trac, you should see the Trac screen such as that in Figure 3.    
Read more
  • 0
  • 0
  • 8965

article-image-theming-modules-drupal-6
Packt
21 Oct 2009
5 min read
Save for later

Theming Modules in Drupal 6

Packt
21 Oct 2009
5 min read
Our Target Module: What We Want Before we begin developing a module, here's a brief overview of what we want to accomplish. The module we will write in this article is the Philosophy Quotes module (philquotes will be our machine-readable name). The goal of this module will be to create a block that displays pithy philosophical quotes. We will implement the following features: Quotes should be stored along with other basic content, making it possible to add, modify, and delete this content in exactly the same way that we create other articles. Since our existing themes aren't aware of this quotes module, it must provide some default styling. We will progress through the creation of this module by first generating a new "quote" content type, and then building a theme-aware module. Creating a Custom Content Type As Drupal evolved, it incorporated an increasingly sophisticated method for defining content. Central to this system is the idea of the content type. A content type is a definition, stored in Drupal's database, of how a particular class of content should be displayed and what functionality it ought to support. Out of the box, Drupal has two defined content types: Page and Story. Pages are intended to contain content that is static, like an "About Us" or "Contact Us" page. Stories, on the other hand, are intended to contain more transient content—news items, blog postings, and so on. Creating new pages or stories is as simple as clicking on the Create Content link in the default menu. Obviously, not all content will be classified as either a page or a story, and many sites will need specialized content types to adequately represent a specific class of content. Descriptions of events, products, component descriptions, and so on might all be better accomplished with specialized content types. Our module is going to display brief quotes. These quotes shouldn't be treated like either articles or pages. For example, we wouldn't want a new quote to be displayed along with site news in the center column of our front page. Thus, our quotes module needs a custom content type. This content type will be very simple. It will have two parts: the text of the quote and the origin of the quote. For example, here's a famous quote: The life of man [is] solitary, poor, nasty, brutish, and short.—Thomas Hobbes. The text of this quote is "The life of man [is] solitary, poor, nasty, brutish, and short", and the origin in this example is Thomas Hobbes. We could have been more specific and included the title of the work (Leviathan) or even the exact page reference, edition, and so on. But all this information, in our simple example, would be treated as the quote's origin. Given the simplicity of our content type, we can simply use the built-in Drupal content type tool to create the new type. To generate even more sophisticated content types, we could install the CCK (Content Creation Kit) module, and perhaps some of the CCK extension modules. CCK provides a robust set of tools for defining custom fields, data types, and features. But here our needs are simple, so we won't need any additional modules or even any custom code to create this new content type. Using the Administration Interface to Create a Content Type The process of creating our custom content type is as simple as logging into Drupal and filling out a form. The content type tool is in Administer | Content management | Content types. There are a couple of tabs at the top of the page: Clicking the Add content type tab will load the form used to create our new content type. On this form, we need to complete the Name and Type fields—the first with a human-friendly name, and the second with a computer-readable name. Description is often helpful. In addition to these fields, there are a few other form fields under the Submission form settings and Workflow settings that we need to change. In the Submission form settings section, we will change the labels to match the terminology we have been using. Instead of Title and Body, our sections will be Origin and Text. Changing labels is a superficial change. While it changes the text that is displayed to users, the underlying data model will still refer to these fields as title and body. We will see this later in the article. In the Workflow settings section, we need to make sure that only Published is checked. By default, Promoted to front page is selected. That should be disabled unless you want new quotes to show up as content in the main section of the front page. Once the form is complete, pressing the Save content type button will create the new content type. That's all there is to it. The Create content menu should now have the option of creating a new quote: As we continue, we will create a module that displays content of type quote in a block. Before moving on, we want a few pieces of content. Otherwise, our module would have no data to display. Here's the list of quotes (as displayed on Administer | Content management | Content) that will constitute our pool of quotations for our module.  
Read more
  • 0
  • 0
  • 1855

article-image-installing-drupal-themes
Packt
21 Oct 2009
5 min read
Save for later

Installing Drupal Themes

Packt
21 Oct 2009
5 min read
The large and active community of developers that has formed around Drupal guarantees a steady flow of themes for this popular CMS. The diversity of that community also assures that there will be a wide variety of themes produced. Add into the equation the existence of a growing number of commercial and open source web designs and you can be certain that somewhere out there is a design that is close to what you want. The issue becomes identifying the sources of themes and designs, and determining how much work you want to do yourself. You can find both design ideas and complete themes on the Web. You need to decide whether you want to work with an existing theme, or convert a design into a theme, or whether you want to start from scratch, unburdened by any preliminary constraints or alien code. For purposes of this article, we will be dealing with finding, installing, and then uninstalling an existing and current Drupal theme. This article assumes you have a working Drupal installation, and that you have access to the files on your server. Finding Additional Themes There are several factors to consider when determining the suitability of an existing theme. The first issue is compatibility. Due to changes made to Drupal in the 5.x series, older themes will not work properly with Drupal 5.x. Accordingly, your first step is to determine which version of Drupal you are running. To find the version information for your installation, go to Administer | Logs | Status Report. The first line of the Status Report tabular data will show your version number. If you do not see the Status Report option, then you are probably using a Drupal version earlier than 5.x. We suggest you upgrade as this book is for Drupal 5.x. If you know your Drupal version, you can confirm whether the theme you are considering is usable on your system. If the theme you are looking at doesn't provide versioning information, assume the worst and make sure you back up your site before you install the questionable theme. Once you're past the compatibility hurdle, your next concern is system requirements; does the theme require any additional extensions to work properly? Some themes are ready to run with no additional extensions required. Many themes require that your Drupal installation include a particular templating engine. The most commonly required templating engine is PHPTemplate. If you are running a recent instance of Drupal, you will find that the PHPTemplate engine is installed by default. You can also download a variety of other popular templating engines, including Smarty and PHPTal from http://drupal.org/project/Theme+engines.Check carefully whether the theme you've chosen requires you to download and install other extensions. If so, track down the additional extensions and install them first, before you install your theme. A good place to start looking for a complete Drupal theme is, perhaps not surprisingly, the official Drupal site. At Drupal.org, you can find a variety of downloads, including both themes and template engines. Go to http://drupal.org/project/Themes to find a listing of the current collection of themes. All the themes state very clearly the version compatibility and whether there are any prerequisites to run the theme. In addition to the resources on the official Drupal site, there is an assortment of fan sites providing themes. Some sites are open source, others commercial, and a fair number are running unusual licenses (most frequently asking that footers be left intact with links back to their sites). Some of the themes available are great; most are average. If your firm is brand sensitive, or your design idiosyncratic, you will probably find yourself working from scratch. Regardless of your particular needs, the theme repositories are a good place to start gathering ideas. Even if you cannot find exactly what you need, you sometimes find something with which you can work. An existing set of properly formed theme files can jump start your efforts and save you a ton of time. If you wish to use an existing theme, pay attention to the terms of usage. You can save yourself (or your clients) major headaches by catching any unusual licensing provisions early in the process. There's nothing worse than spending hours on a theme only to discover its use is somehow restricted. One source for designs with livable usage policies is the Open Source Web Design site, http://www.oswd.org, which includes a repository of designs, all governed by open source licensing terms. The down side of this resource is that all you get is the design—not the code, not a ready-made theme. You will need to convert the design into a usable theme. For this article, let's search out a completed theme and for the sake of simplicity, let's take one from the official Drupal site. I am going to download the Gagarin theme from Drupal.org. I'll refer to this theme as a working example of some ofthe steps below. You can either grab a copy of the same theme or you can use another—the principles are the same regardless. Gagarin is an elegant little theme from Garamond of the Russian Drupal community. Gagarin is set up for a two-column site (though it can be run in three columns) and works particularly well for a blog site.
Read more
  • 0
  • 0
  • 2836

article-image-article-marketing-cms-blogs-and-online-magazines-improve-sales
Packt
21 Oct 2009
9 min read
Save for later

Article Marketing on CMS, Blogs, and Online Magazines to Improve Sales

Packt
21 Oct 2009
9 min read
Dynamic Content: What and Why? What do we actually mean when we call it "dynamic"? Does it mean the content itself changes while the customer is browsing through the website? Here, we mean that the content of the whole website changes as time goes by, and more and more content is added. At this stage, it doesn't really matter who or what adds the content—whether it's the Administrator of the osCommerce website, or the website's visitors, or customers, or if the content is downloaded from another source (another website). Why is dynamic content important for osCommerce? It's not only important for osCommerce, but for any website that is supposed to generate traffic and has goals to attract more visitors. The more professional, detailed, and interesting the content of the site is, the more customers will find it potentially useful to visit the website again and read newly posted materials. If the content of the website changes quite often, it will keep constantly growing with the flow of visitors. For online stores, including osCommerce dynamic content is especially important. First of all, it attracts more visitors who are interested in reading new and updated content to the website. It attracts more target audience visitors, who are likely to become customers and existing customers who are likely to become return customers. And all this without any advertising expenses involved! Then, well prepared content increases the visitor's confidence and helps to increase the "visitor to customer" conversion rates. Finally, keyword-rich content is well indexed by search engine crawlers, and search engines are more likely to put a website that constantly updates higher in search results than a website that doesn't. So publishing dynamic content on an osCommerce site may increase the number of visitors, make the website more noticeable in search engines, and also increase the number of sales. How Can We Make Users Participate? By inviting not only readers but also writers it is possible to publish even more articles, news, reviews, etc. Such an approach may also help a lot in attracting users and converting them into customers, as they will know your osCommerce online store as a place in the Internet where they can both buy goods online and read what other customers have to say, express their thoughts, and participate in discussions, etc. Here are several ways to invite users and customers of the website to participate in creating dynamic content: First and most important, is to make customers and website users aware of apossibility to participate and post content or just comments on other posts. Give them technical means to participate. Ask them to describe their own experience or opinion on a productor service. Ask them how you could improve your services and product range. Even though it's extremely important to get feedback and content from users and customers of an online store, the Administrator of such a site should be ready to fight SPAM, fraudulent posts and content, copyright violations, and content that harasses, abuses, or threatens other users or customers. Different Types of Dynamic Content in osCommerce There can be multiple types of dynamic content present in osCommerce. There are osCommerce contributions and website authoring and building techniques and methods that allow for dynamic content to be added to an osCommerce online store. In this article, we will specifically focus on articles, and how they can used for marketing on various blogs and online magazines. CMS, Blogs, and Online Magazines Article marketing means that you will write articles about your field of interest and distribute them for publication on other websites, blogs, and ezines with a link back to your site. Each time your article is published on a website you get a one-way link to your site. As with most good things, this method has been pounced upon by Internet marketers and the net is flooded with a lot of low-quality articles. However, if you produce meaningful articles, you can still get a lot of benefit by distributing your articles. By publishing articles in your own online store, you not only get better indexed by search engines, but what's more important provide useful information to your customers who may be seeking for it. What can the articles be about? Articles can be about products or series of products available forpurchase online. Articles can be about specific features of products and help customers to choose the product they want based on the detailed explanation of what this or that feature actually means. This sort of articles are called "buying guides". Also, in the articles, authors can compare features of several products and provide comprehensive information on what is the best choice forwhat needs. Articles can contain information on the best practice, tips, and tricks for using certain products advertised in the online store. Such articles help customers imagine how they would use this or that product, which increases chances for customers to buy the product online. Articles can be about some interesting facts related to the products sold online (similar to how Starbucks write in their brochures about water supplies in dry regions where their coffee grows). Articles can be about tendencies in certain industries, related to the products available in the online store. Actually blog posts would not be that different to the articles, except that an article is supposed to be more detailed and informative than a blog post. Also, in the blog posts the author often can ask the readers to comment on certain questions/topics to make the discussion live and initiate opinion exchange. When running a business blog, it makes sense to create several categories where the articles could be sorted. This way the customers will be able to find previous posts more easily, and also the blog author(s) will have certain goals, like, for example, to write to each category regularly. Online magazines would contain articles grouped by certain theme and would be issued/updated regularly. With both articles and blog posts, a facility to leave a comment is important to make the customers participate in discussion. For search engine optimization purposes and for better user (reader)-to-customer conversion, links to the related products advertised on the online store can be added to each article or blog post, or be published alongside it. Besides a facility to publish articles in other websites and online magazines, there are a number of content management solutions that can be integrated into the online store. But first, we will consider a very effective and free way to publish content on the Internet. Open encyclopedia Wikipedia.org allows for publishing content. Of course the content needs to be properly prepared and be very detailed and to the point. But if you have anything to say about the products advertised in the online store, the technology that stands behind those products, or e-commerce approach that stands behind the online store, that qualifies to become an article in the electronic encyclopedia—a post in Wikipedia would be one of the most effective ways to promote your online store, its technology, and products. Existing Content Management Solutions There are a number of open-source solutions available to an osCommerce store owner that could be used to publish content directly on the website. We will consider several of the most popular ones, and also general integration practices with osCommerce. osCommerce Information System and News Desk osCommerce Information system is a publicly available contribution that can be downloaded from the osCommerce Contributions website at http://addons.oscommerce.com/info/1709. It allows managing content of pages like Terms and Conditions, Privacy Policy, etc. osCommerce Newsdesk contribution allows for creating multi-level categories of articles and actually posting articles into the categories. It has support for multiple languages and each article can be posted in several languages. It also has built-in support for the so called WYSIWYG HTML editor, so that the Administrator of the online store can create nice-looking HTML content directly in the Administration panel of the osCommerce online store, with no use of any additional HTML authoring tools. Posted articles can be added to the front end of the online store, either into an information box in one of the side columns, or displayed on one page, groupedby categories. Posting an article is really easy. In the Administration panel, one has to fill in the article name, abstract, content, and may also want to fill in page title and keywords for the sake of SEO. Articles can be posted in different topics (categories), and the system allows for a multi-level tree of categories to be built in the Administration panel of the site. When posting an article, one can also select author from thedrop-down list. Authors are managed separately. It becomes possible to add the Tell a Friend box on the Article page, this is configured in the options in the Administration panel. Reviews can be submitted by readers, and, once a review gets approved by the Administrator, the website displays it on the Article page, along with the Article text. Yet another very important feature includes a facility to assign certain products to articles. Once a product gets assigned to an article, a link to the product information page appears underneath the text of the article. This feature works really well for SEO, and also, it helps customers who would be interested in products that are described in the associated article to find them easily. This solution, which is available for free and can be downloaded from the osCommerce website (http://addons.oscommerce.com/info/1026) can address the needs of an online shop by allowing posting articles to the website, running online magazines, creating buying guides, and so on.  
Read more
  • 0
  • 0
  • 1590
article-image-creating-efficient-reports-visual-studio
Packt
21 Oct 2009
5 min read
Save for later

Creating efficient reports with Visual Studio

Packt
21 Oct 2009
5 min read
Report Services, Analysis Services, and Integration Services are the three pillars of Business Intelligence in Microsoft's vision that continues to evolve. Reporting is a basic activity, albeit one of the most important activities of an organization because it provides a specialized and customized view of the data of various forms (relational, text, xml etc) that live in data stores. The report is useful in making business decisions, scheduling business campaigns, or assessing the competition. The report itself may be required in hard copy in several document formats such as DOC, HTML, PDF, etc. Many times it is also required to be retrieved in an interactive form from the data store and viewed on a suitable interface, including a web browser. The Microsoft SQL Server 2005 Reporting Services, popularly known by its acronym SSRS, provides all that is necessary to create and manage reports and deploy them on a report server with output available in several document formats. The reader will greatly benefit from reading the several articles detailed in the author's Hodentek Blog. The content for the articles were developed using VS 2003, VS 2005, SQL 2000 and SQL 2005. (For more resources on Microsoft, see here.) The content for the present tutorial uses a Visual Studio 2008 Professional and a Microsoft SQL Server Compact 3.5 embeddable database for its data. In Visual Studio a Report Design Wizard guides you through fashioning a report from your choices. Create a Windows Project in VS2008 Create a new project from File | New | Project. Provide a name instead of the default name (WindowsApplicaiton1). This is changed to ReportDesign for this tutorial as shown in the next figure. VS 2008 supports multi-version targeting. In the top right of the New Project window you can see that this report is targeted for the NET 2.0 Framework Version and can be published to a Net 2.0 web site. Slightly enlarge the Form1. Drag and drop the Microsoft Report Viewer control shown in the next figure on to the form from the Toolbox. This has the same functionality as the ReportViewer control in VS 2005 as shown in the next figure. The control will be housed on the form as shown in the next figure. You can display the tasks needed to configure the Report Viewer by clicking on the Smart Task as shown in the same figure. The report will have all the functionalities like print, save to different formats, navigating through pages, etc. Working with the Report Wizard Now click on the Design a new report task. The opens the Report Wizard window as shown in the figure. Read the instructions on this page carefully. Click on the Next Button. This displays the Data Source Configuration Wizard shown in the next figure. Choosing a Data Source The application can obtain data from these different resources. Click on the Database icon and then click on the Next button. This displays the window where you need to select a connection to the data source. If there are existing connections you should be able to see them in the drop-down list box. Making a Connection to Get Data Click on the New Connection button. This brings up the Add Connection window showing a default connection to a Microsoft SQL Server Compact 3.5.NET Framework Data Provider. It also shows the location to be My Computer. This source can be changed by clicking on the Change... button. This will bring up the Change Data Source window where you can choose. As found in this version you have the following options: Microsoft SQL Server option lets you connect to SQL 2000 or 2005 using the .NET Framework Data Provider for SQL Server. Microsoft SQL Server Compact 3.5 lets you connect to a database file. Microsoft SQL Server Database File lets you connect to a Local Microsoft SQL Server Instance including a SQL Express. Although it is not explicitly stated what these versions are. For this tutorial the Compact 3.5 will be used (also uses a .NET Framework Data Provider of Compact 3.5). Click on the OK button in the Change Data Source window. VS 2008 installation also installs a database file on the computer for the SQL Server Compact 3.5. Click on Browse button (you could also create one if you like, herein it will be browsed). This brings up the Select SQL Server Compact 3.5 Database File window with the default location where the database file is parked as shown in the next figure. Click on the Northwind icon in the window and click on the Open button. This updates the Add Connection window with this information as shown in the next figure. You may test the connection by hitting the Test Connection button which should display a successful outcome as shown in the next figure. There is no need for a password as you are the owner. Click OK twice and this will take you back to the Data Source Configuration Wizard updating the connection information which you may review as shown in the next figure. Click on the Next button. This brings up the Microsoft Visual Studio message window giving you the option to bring this data source to your project.    
Read more
  • 0
  • 0
  • 6528

article-image-implementing-document-management-alfresco-3-part1
Packt
21 Oct 2009
5 min read
Save for later

Implementing Document Management in Alfresco 3- part1

Packt
21 Oct 2009
5 min read
Managing spaces A space in Alfresco is nothing but a folder that contains content as well as sub spaces. The space users are the users invited to a space to perform specific actions such as editing content, adding content, discussing a particular document, and so on. The exact capability that a given user has within a space is a function of their role, or rights. Let's consider the capability of creating a sub-space. By default, in order to create a sub-space, one of the following must apply: The user is the administrator of the system The user has been granted the Contributor role The user has been granted the Coordinator role The user has been granted the Collaborator role Similarly, to edit space properties, a user will need to be the administrator or be granted a role that gives them rights to edit the space. These roles include Editor, Collaborator and Coordinator. Space is a smart folder Space is a folder with additional features, such as, security, business rules, workflow, notifications, local search capabilities, and special views. The additional features, which make the space a smart folder, are explained as follows: Space security: You can define security at the space level. You can designate a user or a group of users who can perform certain actions on the content in a space. For example, on the Marketing Communications space in the Intranet, you can specify that only users in the marketing group can add content, and other users can only see the content. Space business rules: Business rules, such as transforming content from Microsoft Word to Adobe PDF and sending notifications when content gets into a space, can be defined at the space level. Space workflow: You can define and manage the content workflow on a space. Typically, you will create a space for the content that needs to be reviewed, and a space for the content that has been approved. You will create various spaces for dealing with the different stages that the work flows through, and Alfresco will manage the movement of the content between those spaces. Space events: Alfresco triggers events when content moves into a space, when content moves out of a space, or when content is modified within a space. You can capture such events at the space level, and trigger certain actions, such as sending email notifications to certain users. Space aspects: Aspects are additional properties and behavior that can be added to the content, based on the space in which it resides. For example, you can define a business rule to add customer details to all of the customer contract documents that are in your intranet's Sales space. Space search: Alfresco search functions can be limited to a space. For example, if you create a space called Marketing, then you can limit the search to documents within the Marketing space, instead of searching the entire site. Space syndication: Content in a space can be syndicated by applying RSS feed scripts to a space. You can apply RSS feeds to your News space, so that other applications and web sites can subscribe to this feed for news updates. Space content: Content in a space can be versioned, locked, checked-in and checked-out, and managed. You can specify certain documents in a space to be versioned, and others not. Space network folder: Space can be mapped to a network drive on your local machine, enabling you to work with the content locally. For example, by using CIFS interface, a space can be mapped to the Windows network folder. Space dashboard view: Content in a space can be aggregated and presented using special dashboard views. For example, the Company Policies space can list all of the latest policy documents, that have been updated in the past one month or so. You can create different views for Sales, Marketing, and Finance departmental spaces. Why space hierarchy is important Like regular folders, a space can have child spaces (called sub spaces). These sub spaces can have further sub spaces of their own. There is no limitation on the number of hierarchical levels. However, the space hierarchy is very important for all of the reasons specified above, in the previous section. Any business rules and security defined for a space is applicable to all of the content and sub spaces within that space. Your space hierarchy should look similar to the following screenshot: A space in Alfresco enables you to define various business rules, a dashboard view, properties, workflow, and security for the content belonging to each department. You can decentralize the management of your content by providing access to departments at the individual space levels. The example of the Intranet space should contain sub spaces, as shown in the preceding screenshot. You can create spaces by logging in as the administrator. It is also very important to set the security (by inviting groups of users to these spaces).
Read more
  • 0
  • 0
  • 2006

article-image-apache-ofbiz-service-engine-part-1
Packt
21 Oct 2009
6 min read
Save for later

Apache OFBiz Service Engine: Part 1

Packt
21 Oct 2009
6 min read
Defining a Service We first need to define a service. Our first service will be named learningFirstService. In the folder ${component:learning}, create a new folder called servicedef. In that folder, create a new file called services.xml and enter into it this: <?xml version="1.0" encoding="UTF-8" ?> <services xsi:noNamespaceSchemaLocation="http://www.ofbiz.org/dtds/services.xsd"> <description>Learning Component Services</description> <service name="learningFirstService" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="learningFirstService"> <description>Our First Service</description> <attribute name="firstName" type="String" mode="IN" optional="true"/> <attribute name="lastName" type="String" mode="IN" optional="true"/> </service> </services> In the file ${component:learning}ofbiz-component.xml, add after the last <entity-resource> element this: <service-resource type="model" loader="main" location="service def/services.xml"/> That tells our component learning to look for service definitions in the file ${component:learning}servicedefservices.xml. It is important to note that all service definitions are loaded at startup; therefore any changes to any of the service definition files will require a restart! Creating the Java Code for the Service In the package org.ofbiz.learning.learning, create a new class called LearningServices with one static method learningFirstService: package org.ofbiz.learning.learning; import java.util.Map; import org.ofbiz.service.DispatchContext; import org.ofbiz.service.ServiceUtil; public class LearningServices { public static final String module = LearningServices.class.getName(); public static Map learningFirstService(DispatchContext dctx, Map context){ Map resultMap = ServiceUtil.returnSuccess("You have called on service 'learningFirstService' successfully!"); return resultMap; } } Services must return a map. This map must contain at least one entry. This entry must have the key responseMessage (see org.ofbiz.service.ModelService.RESPONSE_MESSAGE), having a value of one of the following: success or ModelService.RESPOND_SUCCESS error or ModelService.RESPOND_ERROR fail or ModelService.RESPOND_FAIL By using ServiceUtil.returnSuccess() to construct the minimal return map, we do not need to bother adding the responseMessage key and value pair. Another entry that is often used is that with the key successMessage (ModelService.SUCCESS_MESSAGE). By doing ServiceUtil.returnSuccess("Some message"), we will get a return map with entry successMessage of value "Some message". Again, ServiceUtil insulates us from having to learn the convention in key names. Testing Our First Service Stop OFBiz, recompile our learning component and restart OFBiz so that the modified ofbiz-component.xml and the new services.xml can be loaded. In ${component:learning}widgetlearningLearningScreens.xml, insert a new Screen Widget: <screen name="TestFirstService"> <section> <widgets> <section> <condition><if-empty field-name="formTarget"/></condition> <actions> <set field="formTarget" value="TestFirstService"/> <set field="title" value="Testing Our First Service"/> </actions> <widgets/> </section> <decorator-screen name="main-decorator" location="${parameters.mainDecoratorLocation}"> <decorator-section name="body"> <include-form name="TestingServices" location="component://learning/widget/learning/LearningForms.xml"/> <label text="Full Name: ${parameters.fullName}"/> </decorator-section> </decorator-screen> </widgets> </section> </screen> In the file ${component:learning}widgetlearningLearningForms.xml, insert a new Form Widget: <form name="TestingServices" type="single" target="${formTarget}"> <field name="firstName"><text/></field> <field name="lastName"><text/></field> <field name="planetId"><text/></field> <field name="submit"><submit/></field> </form> Notice how the formTarget field is being set in the screen and used in the form. For now don't worry about the Full Name label we are setting from the screen. Our service will eventually set that. In the file ${webapp:learning}WEB-INFcontroller.xml, insert a new request map: <request-map uri="TestFirstService"> <event type="service" invoke="learningFirstService"/> <response name="success" type="view" value="TestFirstService"/> </request-map> The control servlet currently has no way of knowing how to handle an event of type service, so in controller.xml we must add a new handler element immediately under the other <handler> elements: <handler name="service" type="request" class="org.ofbiz.webapp.event.ServiceEventHandler"/> <handler name="service-multi" type="request" class="org.ofbiz.webapp.event.ServiceMultiEventHandler"/> We will cover service-multi services later. Finally add a new view map: <view-map name="TestFirstService" type="screen" page="component://learning/widget/learning/LearningScreens.xml#TestFirstService"/> Fire to webapp learning an http OFBiz request TestFirstService, and see that we have successfully invoked our first service: Service Parameters Just like Java methods, OFBiz services can have input and output parameters and just like Java methods, the parameter types must be declared. Input Parameters (IN) Our first service is defined with two parameters: <attribute name="firstName" type="String" mode="IN" optional="true"/> <attribute name="lastName" type="String" mode="IN" optional="true"/> Any parameters sent to the service by the end-user as form parameters, but not in the services list of declared input parameters, will be dropped. Other parameters are converted to a Map by the framework and passed into our static method as the second parameter. Add a new method handleInputParamaters to our LearningServices class. public static Map handleParameters(DispatchContext dctx, Map context){ String firstName = (String)context.get("firstName"); String lastName = (String)context.get("lastName"); String planetId= (String)context.get("planetId"); String message = "firstName: " + firstName + "<br/>"; message = message + "lastName: " + lastName + "<br/>"; message = message + "planetId: " + planetId; Map resultMap = ServiceUtil.returnSuccess(message); return resultMap; } We can now make our service definition invoke this method instead of the learningFirstService method by opening our services.xml file and replacing: <service name="learningFirstService" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="learningFirstService"> with: <service name="learningFirstService" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="handleParameters"> Once again shutdown, recompile, and restart OFBiz. Enter for fields First Name, Last Name, and Planet Id values Some, Name, and Earth, respectively. Submit and notice that only the first two parameters went through to the service. Parameter planetId was dropped silently as it was not declared in the service definition. Modify the service learningFirstService in the file ${component:learning}servicedefservices.xml, and add below the second parameter a third one like this: <attribute name="planetId" type="String" mode="IN" optional="true"/> Restart OFBiz and submit the same values for the three form fields, and see all three parameters go through to the service.  
Read more
  • 0
  • 0
  • 3399
article-image-buttons-menus-and-toolbars-ext-js
Packt
20 Oct 2009
5 min read
Save for later

Buttons, Menus, and Toolbars in Ext JS

Packt
20 Oct 2009
5 min read
The unsung heroes of every application are the simple things like buttons, menus, and toolbars. In this article by Shea Frederick, Steve 'Cutter' Blades, and Colin Ramsay, we will cover how to add these items to our applications. Our example will contain a few different types of buttons, both with and without menus. A button can simply be an icon, or text, or both. Toolbars also have some mechanical elements such as spacers and dividers that can help to organize the buttons on your toolbars items. We will also cover how to make these elements react to user interaction. A toolbar for every occasion Just about every Ext component—panels, windows, grids can accept a toolbar on either the top or the bottom. The option is also available to render the toolbar standalone into any DOM element in our document. The toolbar is an extremely flexible and useful component that will no doubt be used in every application. Ext.Toolbar: The main container for the buttons Ext.Button: The primary handler for button creation and interaction Ext.menu: A menu Toolbars Our first toolbar is going to be rendered standalone in the body of our document. We will add one of each of the main button types, so we can experiment with each: Button—tbbutton: This is the standard button that we are all familiar with. Split Button—tbsplit: A split button is where you have a default button action and an optional menu. These are used in cases where you need to have many options in the same category as your button, of which there is a most commonly used default option. Menu—tbbutton+menu: A menu is just a button with the menu config filled in with options. Ext.onReady(function(){ new Ext.Toolbar({ renderTo: document.body, items: [{ xtype: 'tbbutton', text: 'Button' },{ xtype: 'tbbutton', text: 'Menu Button', menu: [{ text: 'Better' },{ text: 'Good' },{ text: 'Best' }] },{ xtype: 'tbsplit', text: 'Split Button', menu: [{ text: 'Item One' },{ text: 'Item Two' },{ text: 'Item Three' }] }] });}); As usual, everything is inside our onReady event handler. The items config holds all of our toolbars elements—I say elements and not buttons because the toolbar can accept many different types of Ext components including form fields—which we will be implementing later on in this article. The default xtype for each element in the items config is tbbutton. We can leave out the xtype config element if tbbutton is the type we want, but I like to include it just to help me keep track. The button Creating a button is fairly straightforward; the main config option is the text that is displayed on the button. We can also add an icon to be used alongside the text if we want to. Here is a stripped-down button: { xtype: 'tbbutton', text: 'Button'} Menu A menu is just a button with the menu config populated—it's that simple. The menu items work along the same principles as the buttons. They can have icons, classes, and handlers assigned to them. The menu items could also be grouped together to form a set of option buttons, but first let's create a standard menu. This is the config for a typical menu config: { xtype: 'tbbutton', text: 'Button', menu: [{ text: 'Better' },{ text: 'Good' },{ text: 'Best' }]} As we can see, once the menu array config is populated, the menu comes to life. To group these menu items together, we would need to set the group config and the boolean checked value for each item: menu: [{ text: 'Better', checked: true, group: 'quality'}, { text: 'Good', checked: false, group: 'quality'}, { text: 'Best', checked: false, group: 'quality'}] Split button The split button sounds like a complex component, but it's just like a button and a menu combined, with a slight twist. By using this type of button, you get to use the functionality of a button while adding the option to select an item from the attached menu. Clicking the left portion of the button that contains the text triggers the button action. However, clicking the right side of the button, which contains a small down arrow, triggers the menu. { xtype: 'tbsplit', text: 'Split Button', menu: [{ text: 'Item One' },{ text: 'Item Two' },{ text: 'Item Three' }]} Toolbar item alignment, dividers, and spacers By default, every toolbar aligns elements to the leftmost side. There is no alignment config for a toolbar, so if we want to align all of the toolbar buttons to the rightmost side, we need to add a fill as the first item in the toolbar. If we want to have items split up between both the left and right sides, we can also use a fill: { xtype: 'tbfill'} Pop this little guy in a tool-bar wherever you want to add space and he will push items on either side of the fill to the ends of the tool bar, as shown below: We also have elements that can add space or vertical dividers, like the one used between the Menu Button and the Split Button. The spacer adds a few pixels of empty space that can be used to space out buttons, or move elements away from the edge of the toolbar: { xtype: 'tbspacer'} A divider can be added in the same way: { xtype: 'tbseparator'} Shortcuts Ext has many shortcuts that can be used to make coding faster. Shortcuts are a character or two that can be used in place of a configuration object. For example, consider the standard toolbar filler configuration: { xtype: 'tbfill'} The shortcut for a toolbar filler is a hyphen and a greater than symbol: '->' Not all of these shortcuts are documented. So be adventurous, poke around the source code, and see what you can find. Here is a list of the commonly-used shortcuts:
Read more
  • 0
  • 0
  • 7376

article-image-apache-ofbiz-service-engine-part-2
Packt
20 Oct 2009
16 min read
Save for later

Apache OFBiz Service Engine: Part 2

Packt
20 Oct 2009
16 min read
Calling Services from Java Code So far, we have explored services invoked as events from the controller (example <event type="service" invoke="learningFirstService"/>). We now look at calling services explicitly from code. To invoke services from code, we use the dispatcher object, which is an object of type org.ofbiz.service.ServiceDispatcher. Since this is obtainable from the DispatchContext we can invoke services from other services. To demonstrate this we are going to create one simple service that calls another. In our services.xml file in ${component:learning}servicedef add two new service definitions: <service name="learningCallingServiceOne" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="callingServiceOne"> <description>First Service Called From The Controller</description> <attribute name="firstName" type="String" mode="IN" optional="false"/> <attribute name="lastName" type="String" mode="IN" optional="false"/> <attribute name="planetId" type="String" mode="IN" optional="false"/> <attribute name="fullName" type="String" mode="OUT" optional="true"/> </service> <service name="learningCallingServiceTwo" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="callingServiceTwo"> <description>Second Service Called From Service One</description> <attribute name="planetId" type="String" mode="IN" optional="false"/> </service> In this simple example it is going to be the job of learningCallingServiceOne to prepare the parameter map and pass in the planetId parameter to learningCallingServiceTwo. The second service will determine if the input is EARTH, and return an error if not. In the class org.ofbiz.learning.learning.LearningEvents, add the static method that is invoked by learningCallingServiceOne: public static Map callingServiceOne(DispatchContext dctx, Map context){ LocalDispatcher dispatcher = dctx.getDispatcher(); Map resultMap = null; String firstName = (String)context.get("firstName"); String lastName = (String)context.get("lastName"); String planetId = (String)context.get("planetId"); GenericValue userLogin = (GenericValue)context.get("userLogin"); Locale locale = (Locale)context.get("locale"); Map serviceTwoCtx = UtilMisc.toMap("planetId", planetId, "userLogin", userLogin, "locale", locale); try{ resultMap = dispatcher.runSync("learningCallingServiceTwo", serviceTwoCtx); }catch(GenericServiceException e){ Debug.logError(e, module); } resultMap.put("fullName", firstName + " " + lastName); return resultMap; } and also the method invoked by learningServiceTwo: public static Map callingServiceTwo(DispatchContext dctx, Map context){ String planetId = (String)context.get("planetId"); Map resultMap = null; if(planetId.equals("EARTH")){ resultMap = ServiceUtil.returnSuccess("This planet is Earth"); }else{ resultMap = ServiceUtil.returnError("This planet is NOT Earth"); } return resultMap; } To LearningScreens.xml add: <screen name="TestCallingServices"> <section> <actions><set field="formTarget" value="TestCallingServices"/></actions> <widgets> <include-screen name="TestFirstService"/> </widgets> </section></screen> Finally add the request-map to the controller.xml file: <request-map uri="TestCallingServices"> <security auth="false" https="false"/> <event type="service" invoke="learningCallingServiceOne"/> <response name="success" type="view" value="TestCallingServices"/> <response name="error" type="view" value="TestCallingServices"/> </request-map> and also the view-map: <view-map name="TestCallingServices" type="screen" page="component://learning/widget/learning/LearningScreens.xml#TestCallingServices"/> Stop, rebuild, and restart, then fire an OFBiz http request TestCallingServices to webapp learning. Do not be alarmed if straight away you see error messages informing us that the required parameters are missing. By sending this request we have effectively called our service with none of our compulsory parameters present. Enter your name and in the Planet Id, enter EARTH. You should see: Try entering MARS as the Planet Id. Notice how in the Java code for the static method callingServiceOne the line resultMap = dispatcher.runSync("learningCallingServiceTwo", serviceTwoCtx); is wrapped in a try/catch block. Similar to how the methods on the GenericDelegator object that accessed the database threw a GenericEntityException, methods on our dispatcher object throw a GenericServiceException which must be handled. There are three main ways of invoking a service: runSync—which runs a service synchronously and returns the result as a map. runSyncIgnore—which runs a service synchronously and ignores the result. Nothing is passed back. runAsync—which runs a service asynchronously. Again, nothing is passed back. The difference between synchronously and asynchronously run services is discussed in more detail in the section called Synchronous and Asynchronous Services. Implementing Interfaces Open up the services.xml file in ${component:learning}servicedef and take a look at the service definitions for both learningFirstService and learningCallingServiceOne. Do you notice that the <attribute> elements (parameters) are the same? To cut down on the duplication of XML code, services with similar parameters can implement an interface. As the first service element in this file enter the following: <service name="learningInterface" engine="interface"> <description>Interface to describe base parameters for Learning Services</description> <attribute name="firstName" type="String" mode="IN" optional="false"/> <attribute name="lastName" type="String" mode="IN" optional="false" /> <attribute name="planetId" type="String" mode="IN" optional="false"/> <attribute name="fullName" type="String" mode="OUT" optional="true"/></service> Notice that the engine attribute is set to interface. Replace all of the <attribute> elements in the learningFirstService and learningCallingServiceOne service definitions with: <implements service="learningInterface"/> So the service definition for learningServiceOne becomes: <service name="learningCallingServiceOne" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="callingServiceOne"> <description>First Service Called From The Controller</description> <implements service="learningInterface"/></service> Restart OFBiz and then fire an OFBiz http request TestCallingServices to webapp learning. Nothing should have changed—the services should run exactly as before, however our code is now somewhat tidier. Overriding Implemented Attributes It may be the case that the interface specifies an attribute as optional="false", however, our service does not need this parameter. We can simply override the interface and add the <attribute> element with whatever settings we wish. For example, if we wish to make the planetId optional in the above example, the <implements> element could remain, but a new <attribute> element would be added like this: <service name="learningCallingServiceOne" engine="java" location="org.ofbiz.learning.learning.LearningServices" invoke="callingServiceOne"> <description>First Service Called From The Controller</description> <implements service="learningInterface"/> <attribute name="planetId" type="String" mode="IN" optional="false"/></service> Synchronous and Asynchronous Services The service engine allows us to invoke services synchronously or asynchronously. A synchronous service will be invoked in the same thread, and the thread will "wait" for the invoked service to complete before continuing. The calling service can obtain information from the synchronously run service, meaning its OUT parameters are accessible. Asynchronous services run in a separate thread and the current thread will continue without waiting. The invoked service will effectively start to run in parallel to the service or event from which it was called. The current thread can therefore gain no information from a service that is run asynchronously. An error that occurs in an asynchronous service will not cause a failure or error in the service or event from which it is called. A good example of an asynchronously called service is the sendOrderConfirmation service that creates and sends an order confirmation email. Once a customer has placed an order, there is no need to wait while the mail service is called and the mail sent. The mail server may be down, or busy, which may result in an error that would otherwise stop our customer form placing the order. It is much more preferable to allow the customer to continue to the Order Confirmation page and have our business receive the valuable order. By calling this service asynchronously, there is no delay to the customer in the checkout process, and while we log and fix any errors with the mail server, we still take the order. Behind the scenes, an asynchronous service is actually added to the Job Scheduler. It is the Job Scheduler's task to invoke services that are waiting in the queue. Using the Job Scheduler Asynchronous services are added to the Job Scheduler automatically. However, we can see which services are waiting to run and which have already been invoked through the Webtools console. We can even schedule services to run once only or recur as often as we like. Open up the Webtools console at https://localhost:8443/webtools/control/main and take a look under the Service Engine Tools heading. Select Job List to view a full list of jobs. Jobs without a Start Date/Time have not started yet. Those with an End Date/Time have completed. The Run Time is the time they are scheduled to run. All of the outstanding jobs in this list were added to the JobSandbox Entity when the initial seed data load was performed, along with the RecurrenceRule (also an Entity) information specifying how often they should be run. They are all maintenance jobs that are performed "offline". The Pool these jobs are run from by default is set to pool. In an architecture where there may be multiple OFBiz instances connecting to the same database, this can be important. One OFBiz instance can be dedicated to performing certain jobs, and even though job schedulers may be running on each instance, this setting can be changed so we know only one of our instances will run this job. The Service Engine settings can be configured in frameworkserviceconfigserviceengine.xml. By changing both the send-to-pool attribute and the name attribute on the <run-from-pool element>, we can ensure that only jobs created on an OFBiz instance are run by this OFBiz instance. Click on the Schedule Job button and in the Service field enter learningCallingServiceOne, leave the Pool as pool and enter today's date/time by selecting the calendar icon and clicking on today's date. We will need to add 5 minutes onto this once it appears in the box. In the below example the Date appeared as 2008-06-18 14:11:24.265. This job is only going to be scheduled to run once, although we could specify any recurrence information we wish. Select Submit and notice that scheduler is already aware of the parameters that can (or must, in this case) be entered. This information has been taken from the service definition in our services.xml file. Press Submit to schedule the job and find the entry in the list. This list is ordered by Run Time so it may not be the first. Recurring maintenance jobs are imported in the seed data and are scheduled to run overnight. These will more than likely be above the job we have just scheduled since their run-time is further in the future. The entered parameters are converted to a map and then serialized to the database. They are then fed to the service at run time. Quickly Running a Service Using the Webtools console it is also possible to run a service synchronously. This is quicker than going through the scheduler should you need to test a service or debug through a service. Select the Run Service button from the menu and enter the same service name, submit then enter the same parameters again. This time the service is run straight away and the OUT parameters and messages are passed back to the screen: Naming a Service and the Service Reference Service names must be unique throughout the entire application. Because we do not need to specify a location when we invoke a service, if service names were duplicated we can not guarantee that the service we want to invoke is the one that is actually invoked. OFBiz comes complete with a full service reference, which is in fact a dictionary of services that we can use to check if a service exists with the name we are about to choose, or even if there is a service already written that we are about to duplicate. From https://localhost:8443/webtools/control/main select the Service Reference and select "l" for learning. Here we can see all of our learning services, what engine they use and what method they invoke. By selecting the service learningCallingServiceOne, we can obtain complete information about this service as was defined in the service definition file services.xml. It even includes information about the parameters that are passed in and out automatically. Careful selection of intuitive service names and use of the description tags in the service definition files are good practice since this allows other developers to reuse services that already exists, rather than duplicate work unnecessarily. Event Condition Actions (ECA) ECA refers to the structure of rules of a process. The Event is the trigger or the reason why the rule is being invoked. The condition is a check to see if we should continue and invoke the action, and the action is the final resulting change or modification. A real life example of an ECA could be "If you are leaving the house, check to see if it is raining. If so, fetch an umbrella". In this case the event is "leaving the house". The condition is "if it is raining" and the action is "fetch an umbrella". There are two types of ECA rules in OFBiz: Service Event Condition Actions (SECAs) and Entity Event Condition Actions (EECAs). Service Event Condition Actions (SECAs) For SECAs the trigger (Event) is a service being invoked. A condition could be if a parameter equalled something (conditions are optional), and the action is to invoke another service. SECAs are defined in the same directory as service definitions (servicedef). Inside files named secas.xml Take a look at the existing SECAs in applicationsorderservicedefsecas.xml and we can see a simple ECA: <eca service="changeOrderStatus" event="commit" run-on-error="false"> <condition field-name="statusId" operator="equals" value="ORDER_CANCELLED"/> <action service="releaseOrderPayments" mode="sync"/></eca> When the changeOrderStatus transaction is just about to be committed, a lookup is performed by the framework to see if there are any ECAs for this event. If there are, and the parameter statusId is ORDER_CANCELLED then the releaseOrderPayments service is run synchronously. Most commonly, SECAs are triggered on commit or return; however, it is possible for the event to be in any of the following stages in the service's lifecycle: auth—Before Authentication in-validate—Before IN parameter validation out-validate—Before OUT parameter validation invoke—Before service invocation commit—Just before the transaction is committed return—Before the service returns global-commit global-rollback The variables global-commit and i are a little bit different. If the service is part of a transaction, they will only run after a rollback or between the two phases (JTA implementation) of a commit. There are also two specific attributes whose values are false by default: run-on-failure run-on-error You can set them to true if you want the SECA to run in spite of a failure or error. A failure is the same thing as an error, except it doesn't represent a case where a rollback is required. It should be noted that parameters passed into the trigger service are available, if need be, to the action service. The trigger services OUT parameters are also available to the action service. Before using SECAs in a component, the component must be informed of the location of the ECA service-resources: <service-resource type="eca" loader="main" location="servicedef/secas.xml"/> This line must be added under the existing <service-resource> elements in the component's ofbiz-component.xml file. Entity Event Condition Actions (EECAs) For EECAs, the event is an operation on an entity and the action is a service being invoked. EECAs are defined in the same directory as entity definitions (entitydef): inside files named eecas.xml. They are used when it may not necessarily be a service that has initiated an operation on the entity, or you may wish that no matter what service operates on this entity, a certain course of action to be taken. Open the eecas.xml file in the applicationsproductentitydef directory and take a look at the first <eca> element: <eca entity="Product" operation="create-store" event="return"> <condition field-name="autoCreateKeywords" operator="not-equals" value="N"/> <action service="indexProductKeywords" mode="sync" value-attr="productInstance"/></eca> This ECA ensures that once any creation or update operation on a Product record has been committed, so long as the autoCreateKeywords field of this record is not N, then the indexProductKeywords service will be automatically invoked synchronously. The operation can be any of the following self-explanatory operations: create store remove find create-store (create or store/update) create-remove store-remove create-store-remove any The return event is by far the most commonly used event in an EECA. But there are also validate, run, cache-check, cache-put, and cache-clear events. There is also the run-on-error attribute. Before using EECAs in a component, the component must be informed of the location of the eca entity-resource: <entity-resource type="eca" loader="main" location="entitydef/eecas.xml"/> must be added under the existing <entity-resource> elements in the component's ofbiz-component.xml file. ECAs can often catch people out! Since there is no apparent flow from the trigger to the service in the code they can be difficult to debug. When debugging always keep an eye on the logs. When an ECA is triggered, an entry is placed into the logs to inform us of the trigger and the action. Summary This brings us to the end of our investigation into the OFBiz Service Engine. We have discovered how useful the Service Oriented Architecture in OFBiz can be and we have learnt how the use of some of the built in Service Engine tools, like the Service Reference, can help us when we are creating new services. In this article we have looked at: Calling services from code (using dispatcher). IN/OUT parameter mismatch when calling services Sending feedback; standard return codes success, error and fail. Implementing Service Interfaces Synchronous and asynchronous services Using the Service Engine tools ECAs: Event Condition Actions
Read more
  • 0
  • 0
  • 3087
Modal Close icon
Modal Close icon