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
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-real-content-php5-cms-part-1
Packt
27 Oct 2009
14 min read
Save for later

Real Content in PHP5 CMS: Part 1

Packt
27 Oct 2009
14 min read
The problem There are some common features in providing website content, but also many differences. Applications easily become complex as they tackle real world problems, and there has been much real innovation in web systems. So the areas to look at in this article are: Major areas for content development A review of minor yet important areas How a simple text manager is built An outline of a complex content delivery extension Discussion and considerations Now, we will work through the major areas of website content, devoting a section to each one. A round up of some less important aspects of content completes the discussion, leaving us ready to move on to details of implementation. Articles, blogs, magazines, and FAQ The most basic requirement is for text and pictures, and the simplest scheme needs little more than the standard database and a WYSIWYG editor. An extension that works at this level is illustrated later in the article. It is pretty much essential to have an ability to create items of this kind in an unpublished state so that they can be revised until ready for use. The state is then changed to published. Almost immediately, a further requirement arises to specify a range of publication dates, so that material aimed at a specific event can be automatically published at the appropriate time. Likewise, it is desirable to have an automatic mechanism for removing information that is no longer current, for example because it refers to a coming event in terms that will be irrelevant once the event has passed. A website that carries plainly obsolete articles is unlikely to be popular! There are many ways to organize textual material. One is to place it into some kind of tree structure, rather akin to the classification schemes used in libraries. Ideally, such a scheme has no particular constraints on the depth of the tree structure. A concern with this approach is that it can quickly lead to a conflict between two alternative uses—classification according to subject and classification according to reader permissions. An option that can be used in conjunction with a tree structure is to use some form of tagging. This introduces much greater flexibility in some respects, as it is easy to apply multiple tags to a single item of content, which can therefore be classified in a wide variety of ways, and can appear under multiple headings. A blog is an example of a system that might work best with a combination of a classification tree and a tagging scheme. Where there are several people creating blogs, the different authors fit well with a tree structure, since there is no question of an item belonging to more than one author. On the other hand, items are often tagged according to their subject matter, and several tags may be applicable to an individual article. If authors create more than one blog and there are questions about which visitors are able to see which blog, then careful thought needs to be given as to whether the split of blogs is best handled by the classification tree or by tagging. Using a tree achieves rigid separation, and is easily amenable to imposing access controls. But if the same item appears in more than one blog, then tagging works better as the item is ideally stored only once but has multiple tags. Blogs also frequently provide for comments, discussed in the next section. A magazine is typically a collection of articles. For a simple case, it might be adequate for the articles of the magazine to be equated to website pages, but a more sophisticated magazine would want to avoid restrictions of that kind. The basic unit of content would still need to be an individual article, but website pages then require some kind of template to build a page from multiple items. One popular application for quite simple content is the compilation of frequently asked questions (FAQ's). Advanced implementations might be described more grandly as knowledge bases. Again, both a classification tree and tagging can be relevant, but a useful FAQ (and especially one that wants to be a knowledge base) also needs effective search facilities so that information can be easily found. In all of these cases, added complexity arises if facilities like versioning are needed. Another similar issue is the need for workflow and differing roles, such as authors and editors. Mention of roles suggests a RBAC mechanism. It seems unlikely that one single model will ever meet every requirement in areas such as versioning and workflow. Version control can become extremely complex, and usually requires the allocation of roles that involve access rights and functional capabilities. Workflow is much the same. In both cases, though, simple and rigid schemes are liable to create problems. For example, the same person is quite likely to be an author in some situations, and an editor or publisher in others. A flexible and an efficient RBAC system is a pre-requisite for handling these problems, but as discussed earlier, the technical provision of RBAC is only a start. Applying it to particular systems and creating an appropriate user interface is a considerable challenge. Comments and reviews One of the successful innovations brought about by widespread use of the Web has been feedback through comments and reviews. Amazon is only one of many sites that now include reviews by customers of the products on sale. It could be said that this is a form of social networking, as the more sophisticated sites maintain profiles of reviewers and encourage them to achieve their own identity. Regular readers in particular areas of interest can get to know reviewers and form an opinion on the reliability of their views. There are two main problems with implementing comments and reviews. One is the question of how to generalize the facility, so as to avoid implementing it repeatedly in different applications. The other is how to deal with the ever present threat of spam. From the point of view of a developer, handling comments raises much the same issues regardless of what may be the subject of the comments. So blogs, selections of products, image galleries, and so on are all capable of having comments added to their items using similar mechanisms. This suggests a structure something like the scheme where the coarse grained structure is the component, but its display is achieved through the use of a template and a number of modules. Comments can thus be generated by a module that knows relatively little about the application, only enough to keep its comments separate from those for other applications and to relate a set of comments to a particular item, whether it is a blog item, product, gallery image, or whatever. That deals with the display of existing comments, which still leaves a requirement for a general interface that allows new comments to be added. The comment facility can easily enough handle the acceptance of a new comment, although it may need help if the page that accepts comments is to also show the object to which the comment applies. The comment facility also needs to know where to hand control once a new comment has been completed. Some moderately tricky detailed design is involved in providing an implementation of the full scheme. The other big problem with any facility that permits visitors to a site to enter information for display is that it attracts spammers. Usually, they arrive not in person but in the form of automated bots that can become very sophisticated. There are bots that know how to obtain an account, and log in to a range of systems. There are even bots that can handle CAPTCHAs (those messed up images out of which you are supposed to decipher letters or numbers). Some of the bots can handle CAPTCHAs better than some humans, which makes for accessibility problems. Fortunately, much link spamming is for the purpose of promoting websites, and so the spammer has to give away some information in the form of the link to the site being promoted. A reasonably effective defense against this kind of spamming is a collaborative scheme for blacklisting sites. Even that is not totally effective, as spammers find ways to create new sites quickly and cheaply, so that the threat is constantly changing. As with most forms of attack, there is unlikely to be any conclusion to this battle. Forums Forums are a very popular Web feature, providing a structured means for public or private discussion. Developing a forum is a major undertaking, and most people will prefer to choose from existing software products. Forum software usually provides for visitors to contribute messages, either starting a new topic or replying to an existing one. There is often a hierarchical structure to the messages so that a number of different areas of interest can be covered in a convenient way. Advanced systems include sophisticated user management, including support for a variety of different groups, which provides a means to decide who has access to which topics. Unwanted messages are a constant threat, and most active forums need moderators to weed them out. Development of a new forum will clearly need a number of the framework features discussed earlier. Robust user control is essential, and if different users are granted different access rights, a good system of RBAC is a requirement. A forum is highly amenable to the use of cache, since pages are likely to be constructed out of a number of database records, but the records are updated relatively infrequently. To be responsive, the cache needs to have a degree of intelligence so that pages with new contributions are refreshed quickly. Mail services are likely to be employed so that subscribers can receive notification of new contributions to topics in which they have registered an interest. Another approach is to seek a degree of integration between off the shelf forum software and the CMS. The most popular area for integration is user login. Obviously it is necessary to obtain some information about the way in which the forum software is implemented. Provided that can be found, then it is a relatively simple matter to integrate with a CMS that has been built with plentiful plug in triggers around the area of user authentication. From the point of view of visual integration, the amount of screen space needed by a forum is such that it is often difficult to build it within the framework of a typical CMS. Often a better approach is to build a custom theme for the forum that includes links back to the main site, so as to avoid completely losing continuity of navigation. Galleries, repositories, and streaming Although they have come from different requirements, galleries, and file repositories have a lot in common. Both start out simple and rapidly become complex. The general idea of a gallery is to build a collection of images, typically organized into categories and accessible via small versions of the images (thumbnails). File repositories have long been popular since the days of bulletin boards, where collections of files (often programs) were made available for download. Ideally the organization into categories (or folders or containers) is flexible with no particular limit on the depth to which subcategories can go. Some basic requirements relate to security. It is obviously essential to avoid hosting files that could contain malicious PHP code. This includes avoiding uploads of image files that contain PHP code embedded within actual image data. Simple checks can be fooled by this technique, but a block on the .php extension prevents the code being interpreted. Another potentially major security issue is bandwidth theft. If files or images are too easily accessed, then other sites may choose to use them without acknowledgment, transferring the bandwidth costs to the site hosting the material. As applications broaden, access control becomes an issue. Files are to be made available only to a restricted group, and uploads may be restricted more tightly again. There may be administrator oversight, with uploads needing approval. Once again, we are seeing a demand for an effective access control system, preferably role-based. In fact demands on systems of this kind can easily become very sophisticated, such as allowing users to have personal upload areas over which they have complete control to determine who is able to gain access. An RBAC system that is technically capable of handling this can be built relatively easily, although creating a good user interface is a challenge. Whether the system is a gallery or file repository, the use of thumbnail images is increasingly prevalent. File uploads may, therefore, be accompanied by one or more image files that are used to enhance the display of the files available. Information about the system is likely to be needed, such as which are the most recent additions to the collection, which items are most popular, who has accessed what, and who has uploaded what. Information of this kind can also contribute to security by providing an audit trail of what has been happening to the system. Streaming of files is a demand now often placed on a file repository, as the files can be audio or video files made available for immediate access. Streaming is simply a mode of file processing whereby the information is delivered to the user at a speed adequate for consumption in real time. Clearly video tends to place greater demands on the system than audio. The problems are both hardware and software related, although with steadily improving technology it is increasingly feasible to overcome both. E-commerce and payments Everyone is aware of the huge growth of commercial transactions on the Web. The kind of transaction involved can vary widely across simple fixed price retail sales, auctions of various kinds, and reverse auctions for procurement. For retail transactions immediate settlement is usually required, whereas larger scale business to business transactions are usually handled through relatively traditional invoicing methods. Even those are tending to be altered towards paperless billing and payment schemes that cut transaction costs to a minimum. Systems for e-commerce vary enormously in their sophistication from simple requests for payment using a PayPal button to highly sophisticated Web operations such as Amazon and eBay. Open source PHP software exists to cover a significant part of this spectrum, some of it in the form of extensions to CMS frameworks. PayPal has achieved a very high profile, especially with smaller operators, by offering easy access for merchants combined with technology that is relatively simple to implement. This includes the ability to complete a transaction with online confirmation in a way that is suitable for the sale of electronically deliverable goods such as software. Clearly, robust authentication of users is essential for e-commerce. For all but the simplest transactions, some kind of shopping cart is highly desirable. These requirements imply a need for good session handling, preferably taking effect as soon as a visitor arrives at a site. Nearly every shopping site will allow a visitor to accumulate items in a shopping cart prior to any kind of login. There is a plethora of payment systems, some of them suitable mainly for large volume uses, but others that can be applied on a small scale. A particular CMS framework might adopt some standard payment mechanisms that are then integral to the CMS and can be used whenever needed. Security is obviously paramount, as loss of data is both financially damaging and extremely bad for the site's reputation. E-commerce sites also often use a number of the features described in other sections here. A popular addition is the ability for customers to review the items they have purchased. This kind of facility may lead to further requirements to distinguish categories of users so as to give incentives to people who regularly write reviews.
Read more
  • 0
  • 0
  • 1689

article-image-developing-web-applications-using-javaserver-faces-part-1
Packt
27 Oct 2009
6 min read
Save for later

Developing Web Applications using JavaServer Faces: Part 1

Packt
27 Oct 2009
6 min read
Although a lot of applications have been written using these APIs, most modern Java applications are written using some kind of web application framework. As of Java EE 5, the standard framework for building web applications is Java Server Faces (JSF). Introduction to JavaServer Faces Before JSF was developed, Java web applications were typically developed using non-standard web application frameworks such as Apache Struts, Tapestry, Spring Web MVC, or many others. These frameworks are built on top of the Servlet and JSP standards, and automate a lot of functionality that needs to be manually coded when using these APIs directly. Having a wide variety of web application frameworks available (at the time of writing, Wikipedia lists 35 Java web application frameworks, and this list is far from extensive!), often resulted in "analysis paralysis", that is, developers often spend an inordinate amount of time evaluating frameworks for their applications. The introduction of JSF to the Java EE 5 specification resulted in having a standard web application framework available in any Java EE 5 compliant application server. We don't mean to imply that other web application frameworks are obsolete or that they shouldn't be used at all, however, a lot of organizations consider JSF the "safe" choice since it is part of the standard and should be well supported for the foreseeable future. Additionally, NetBeans offers excellent JSF support, making JSF a very attractive choice. Strictly speaking, JSF is not a web application framework as such, but a component framework. In theory, JSF can be used to write applications that are not web-based, however, in practice JSF is almost always used for this purpose. In addition to being the standard Java EE 5 component framework, one benefit of JSF is that it was designed with graphical tools in mind, making it easy for tools and IDEs such as NetBeans to take advantage of the JSF component model with drag-and-drop support for components. NetBeans provides a Visual Web JSF Designer that allow us to visually create JSF applications. Developing Our first JSF Application From an application developer's point of view, a JSF application consists of a series of JSP pages containing custom JSF tags, one or more JSF managed beans, and a configuration file named faces-config.xml. The faces-config.xml file declares the managed beans in the application, as well as the navigation rules to follow when navigating from one JSF page to another. Creating a New JSF Project To create a new JSF project, we need to go to File | New Project, select the Java Web project category, and Web Application as the project type. After clicking Next, we need to enter a Project Name, and optionally change other information for our project, although NetBeans provides sensible defaults. On the next page in the wizard, we can select the Server, Java EE Version, and Context Path of our application. In our example, we will simply pick the default values. On the next page of the new project wizard, we can select what frameworks our web application will use. Unsurprisingly, for JSF applications we need to select the JavaServer Faces framework. The Visual Web JavaServer Faces framework allows us to quickly build web pages by dragging-and-dropping components from the NetBeans palette into our pages. Although it certainly allows us to develop applications a lot quicker than manually coding, it hides a lot of the "ins" and "outs" of JSF. Having a background in standard JSF development will help us understand what the NetBeans Visual Web functionality does behind the scenes. When clicking Finish, the wizard generates a skeleton JSF project for us, consisting of a single JSP file called welcomeJSF.jsp, and a few configuration files: web.xml, faces-config.xml and, if we are using the default bundled GlassFish server, the GlassFish specific sun-web.xml file is generated as well. web.xml is the standard configuration file needed for all Java web applications. faces-config.xml is a JSF-specific configuration file used to declare JSF-managed beans and navigation rules. sun-web.xml is a GlassFish-specific configuration file that allows us to override the application's default context root, add security role mappings, and perform several other configuration tasks. The generated JSP looks like this: <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%> <%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%-- This file is an entry point for JavaServer Faces application. --%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <f:view> <h1> <h:outputText value="JavaServer Faces"/> </h1> </f:view> </body> </html> As we can see, a JSF enabled JSP file is a standard JSP file using a couple of JSF-specific tag libraries. The first tag library, declared in our JSP by the following line: <%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%> is the core JSF tag library, this library includes a number of tags that are independent of the rendering mechanism of the JSF application (recall that JSF can be used for applications other than web applications). By convention, the prefix f (for faces) is used for this tag library. The second tag library in the generated JSP, declared by the following line: <%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%> is the JSF HTML tag library. This tag library includes a number of tags that are used to implement HTML specific functionality, such as creating HTML forms and input fields. By convention, the prefix h (for HTML) is used for this tag library. The first JSF tag we see in the generated JSP file is the <f:view> tag. When writing a Java web application using JSF, all JSF custom tags must be enclosed inside an <f:view> tag. In addition to JSF-specific tags, this tag can contain standard HTML tags, as well as tags from other tag libraries, such as the JSTL tags. The next JSF-specific tag we see in the above JSP is <h:outputText>. This tag simply displays the value of its value attribute in the rendered page. The application generated by the new project wizard is a simple, but complete, JSF web application. We can see it in action by right-clicking on our project in the project window and selecting Run. At this point the application server is started (if it wasn't already running), the application is deployed and the default system browser opens, displaying our application's welcome page.
Read more
  • 0
  • 0
  • 2614

article-image-overview-cherrypy-web-application-server-part1
Packt
27 Oct 2009
6 min read
Save for later

Overview of CherryPy - A Web Application Server (Part1)

Packt
27 Oct 2009
6 min read
Vocabulary In order to avoid misunderstandings, we need to define a few key words that will be used. Keyword Definition Web server A web server is the interface dealing with the HTTP protocol. Its goal is to transform incoming HTTP requests into entities that are then passed to the application server and also transform information from the application server back into HTTP responses. Application An application is a piece of software that takes a unit of information, applies business logic to it, and returns a processed unit of information. Application server An application server is the component hosting one or more applications. Web application server A web application server is simply the aggregation of a web server and an application server into a single component. CherryPy is a web application server. Basic Example To illustrate the CherryPy library we will go through a very basic web application allowing a user to leave a note on the main page through an HTML form. The notes will be stacked and be rendered in a reverse order of their creation date. We will use a session object to store the name of the author of the note. Each note will have a URI attached to itself, of the form /note/id. Create a blank file named note.py and copy the following source code. #!/usr/bin/python# -*- coding: utf-8 -*# Python standard library importsimport os.pathimport time################################################################The unique module to be imported to use cherrypy###############################################################import cherrypy# CherryPy needs an absolute path when dealing with static data_curdir = os.path.join(os.getcwd(), os.path.dirname(__file__))################################################################ We will keep our notes into a global list# Please not that it is hazardous to use a simple list here# since we will run the application in a multi-threaded environment# which will not protect the access to this list# In a more realistic application we would need either to use a# thread safe object or to manually protect from concurrent access# to this list###############################################################_notes = []################################################################ A few HTML templates###############################################################_header = """<html><head><title>Random notes</<title><link rel="stylesheet" type="text/css" href="/style.css"></link></head><body><div class="container">"""_footer = """</div></body></html>"""_note_form = """<div class="form"><form method="post" action="post" class="form"><input type="text" value="Your note here..." name="text"size="60"></input><input type="submit" value="Add"></input></form></div>"""_author_form = """<div class="form"><form method="post" action="set"><input type="text" name="name"></input><input type="submit" value="Switch"></input></form></div>"""_note_view = """<br /><div>%s<div class="info">%s - %s <a href="/note/%d">(%d)</a></div></div>"""################################################################ Our only domain object (sometimes referred as to a Model)###############################################################class Note(object):def __init__(self, author, note):self.id = Noneself.author = authorself.note = noteself.timestamp = time.gmtime(time.time())def __str__(self):return self.note################################################################ The main entry point of the Note application###############################################################class NoteApp:"""The base application which will be hosted by CherryPy"""# Here we tell CherryPy we will enable the session# from this level of the tree of published objects# as well as its sub-levels_cp_config = { 'tools.sessions.on': True }def _render_note(self, note):"""Helper to render a note into HTML"""return _note_view % (note, note.author,time.strftime("%a, %d %b %Y %H:%M:%S",note.timestamp),note.id, note.id)@cherrypy.exposedef index(self):# Retrieve the author stored in the current session# None if not definedauthor = cherrypy.session.get('author', None)page = [_header]if author:page.append("""<div><span>Hello %s, please leave us a note.<a href="author">Switch identity</a>.</span></div>"""%(author,))page.append(_note_form)else:page.append("""<div><a href="author">Set youridentity</a></span></div>""")notes = _notes[:]notes.reverse()for note in notes:page.append(self._render_note(note))page.append(_footer)# Returns to the CherryPy server the page to renderreturn page@cherrypy.exposedef note(self, id):# Retrieve the note attached to the given idtry:note = _notes[int(id)]except:# If the ID was not valid, let's tell the# client we did not find itraise cherrypy.NotFoundreturn [_header, self._render_note(note), _footer]@cherrypy.exposedef post(self, text):author = cherrypy.session.get('author', None)# Here if the author was not in the session# we redirect the client to the author formif not author:raise cherrypy.HTTPRedirect('/author')note = Note(author, text)_notes.append(note)note.id = _notes.index(note)raise cherrypy.HTTPRedirect('/')class Author(object):@cherrypy.exposedef index(self):return [_header, _author_form, _footer]@cherrypy.exposedef set(self, name):cherrypy.session['author'] = namereturn [_header, """Hi %s. You can now leave <a href="/" title="Home">notes</a>.""" % (name,), _footer]if __name__ == '__main__':# Define the global configuration settings of CherryPyglobal_conf = {'global': { 'engine.autoreload.on': False,'server.socket_host': 'localhost','server.socket_port': 8080,}}application_conf = {'/style.css': {'tools.staticfile.on': True,'tools.staticfile.filename': os.path.join(_curdir,'style.css'),}}# Update the global CherryPy configurationcherrypy.config.update(global_conf)# Create an instance of the applicationnote_app = NoteApp()# attach an instance of the Author class to the main applicationnote_app.author = Author()# mount the application on the '/' base pathcherrypy.tree.mount(note_app, '/', config = application_conf)# Start the CherryPy HTTP servercherrypy.server.quickstart()# Start the CherryPy enginecherrypy.engine.start() Following is the CSS which should be saved in a file named style.css and stored in the same directory as note.py. html, body {background-color: #DEDEDE;padding: 0px;marging: 0px;height: 100%;}.container {border-color: #A1A1A1;border-style: solid;border-width: 1px;background-color: #FFF;margin: 10px 150px 10px 150px;height: 100%;}a:link {text-decoration: none;color: #A1A1A1;}a:visited {text-decoration: none;color: #A1A1A1;}a:hover {text-decoration: underline;}input {border: 1px solid #A1A1A1;}.form {margin: 5px 5px 5px 5px;}.info {font-size: 70%;color: #A1A1A1;} In the rest of this article we will refer to the application to explain CherryPy's design.
Read more
  • 0
  • 0
  • 3751

article-image-real-content-php5-cms-part-3
Packt
27 Oct 2009
8 min read
Save for later

Real Content in PHP5 CMS: Part 3

Packt
27 Oct 2009
8 min read
Administering text items—viewer Generating the XHTML is handled in a separate class, thus implementing the principles of the MVC pattern. The viewer class constructor establishes strings for translation in a way that will allow them to be picked up by gettext, as well as invoking the constructor in the parent class basicAdminHTML, which will provide useful methods and also transfer information such as the page navigation object from the controller object passed as a parameter: class listTextHTML extends basicAdminHTML { public function __construct ($controller) { parent::__construct($controller); $lang_strings = array(T_('Simple Text'),T_('Title'), T_('Byline'),T_('Version'), T_('Publishing'),T_('Published'), T_('Start date'),T_('End date'), T_('Article text'),T_('Metadata'), T_('Keys'),T_('Description'), T_('Hits'),T_('ID')); $this->translations = array_combine( $lang_strings, $lang_strings); } The actual display of a list of text items is then quite simple, involving the creation of a heading first, followed by a loop through the text items, and then some final XHTML including hidden fields that allow for effective navigation. Note that the parent class will have set up $this->optionurl and $this->optionline to help in the construction of links within the component and a hidden variable to identify the component respectively. public function view ($rows) { $mainhtml = $this->listview($rows); echo <<<ALL_HTML $mainhtml <div> <input type="hidden" name="task" value="" /> $this->optionline <input type="hidden" name="boxchecked" value="0" /> <input type="hidden" name="hidemainmenu" value="0" /> </div>ALL_HTML; } The view method does very little, relying on the listview method for most of the work, and only adding hidden fields needed to ensure that navigation and the toolbar will work correctly. Note that the parent class helps us by setting $this->optionline with a hidden input field for the critical option variable needed to ensure the correct component is invoked when the form is submitted. Actual XHTML form tags are created by the CMS framework so that every administrator page is a form. The reason for splitting the page creation in this way will become apparent later, when we look at menu creation. So, moving on to the listview method, we find quite a lot of simple code, which is mainly just a definition of the page in XHTML. The second and third parameters will be set differently from their default values when we come to menu creation. public function listview ($rows, $showlinks=true, $subhead='') { $rowcount = count($rows); $html = <<<ADMIN_HEADER {$this->header($subhead)} <table class="adminlist" width="100%"> <thead> <tr> <th width="3%" class="title"> <input type="checkbox" name="toggle" value="" onclick="checkAll($rowcount);" /> </th> <th> {$this->T_('ID')} </th> <th width="50%" class="title"> {$this->T_('Title')} </th> <th> {$this->T_('Byline')} </th> <th> {$this->T_('Hits')} </th> <th align="left"> {$this->T_('Published')} </th> </tr> </thead> <tbody>ADMIN_HEADER; $i = $k = 0; foreach ($rows as $i=>$row) { if ($showlinks) $title = <<<LINK_TITLE <a href="{$this->optionurl}&amp;task=edit&amp; id=$row->id">$row->title</a>LINK_TITLE; else $title = $row->title; $html .= <<<END_OF_BODY_HTML <tr class="row$k"> <td> {$this->html('idBox', $i, $row->id)} </td> <td align="center"> $row->id </td> <td> $title </td> <td> $row->byline </td> <td align="center"> $row->hits </td> <td align="center"> {$this->html('publishedProcessing', $row, $i )} </td> </tr>END_OF_BODY_HTML; $i++; $k = 1 - $k; } if (0 == $rowcount) $html .= <<<NO_ITEMS_HTML <tr><td colspan="6" class="center"> {$this->T_('No items')} </td></tr>NO_ITEMS_HTML; $html .= <<<END_OF_FINAL_HTML </tbody> </table> {$this->pageNav->getListFooter()}END_OF_FINAL_HTML; return $html; } When it comes to adding a new item or editing an existing one, no looping is required, and the WYSIWYG editor is activated to provide a helpful interface for the administrator who is editing a text item. Note that the use of PHP heredoc allows the XHTML to be written out quite plainly, with the PHP insertions unobtrusive but effective. Actual text for translation is shown in its correct place (in the base language) by using the T_ method that is inherited from aliroBasicHTML via basicAdminHTML. public function edit ($text) { $subhead = $text->id ? 'ID='.$text->id : T_('New'); $editor = aliroEditor::getInstance(); echo <<<EDIT_HTML {$this->header($subhead)} <div id="simpletext1"> <div> <label for="title">{$this->T_('Title')}</label><br /> <input type="text" name="title" id="title" size="80" value="$text->title" /> </div> <div> <label for="byline">{$this->T_('Byline')}</label><br /> <input type="text" name="byline" id="byline" size="80" value="$text->byline" /> </div> <div> <label for="version">{$this->T_('Version')}</label><br /> <input type="text" name="version" id="version" size="80" value="$text->version" /> </div> <div> <label for="article">{$this->T_('Article text')}</label><br /> {$editor->editorAreaText( 'article', $text->article, 'article', 500, 200, 80, 15 )} </div> </div> <div id="simpletext2"> <fieldset> <legend>{$this->T_('Publishing')}</legend> <div> <label for="published">{$this->T_('Published')}</label><br /> <input type="checkbox" name="published" id="published" value="1" {$this->checkedIfTrue($text->published)} /> </div> <div> <label for="publishstart">{$this->T_('Start date')}</label><br /> <input type="text" name="publish_start" id="publishstart" size="20" value="$text->publish_start" /> </div> <div> <label for="publishend">{$this->T_('End date')}</label><br /> <input type="text" name="publish_end" id="publishend" size="20" value="$text->publish_end" /> </div> </fieldset> <fieldset> <legend>{$this->T_('Metadata')}</legend> <div> <label for="metakey">{$this->T_('Keys')}</label><br /> <textarea name="metakey" id="metakey" rows="4" cols="40">$text->metakey</textarea> </div> <div> <label for="metadesc">{$this->T_('Description')}</label><br /> <textarea name="metadesc" id="metadesc" rows="4" cols="40">$text->metadesc</textarea> </div> </fieldset> <input type="hidden" name="task" value="" /> $this->optionline </div> <div id="simpletext3"> <input type="hidden" name="id" value="$text->id" /> <input type="hidden" name="boxchecked" value="0" /> <input type="hidden" name="hidemainmenu" value="0" /> </div>EDIT_HTML; } Finally, there is a common method to deal with the creation of the heading. It uses the addCSS method provided by the parent class to link to a small amount of CSS that is held in a separate file. Although the list of text items defined in the XHTML above is perfectly legitimate as a table, since it really is a tabular structure, the heading would be better built out of other XHTML elements. The only reason for using a table here is that it is one of the features retained from earlier systems for the sake of backwards compatibility: private function header ($subhead='') { $this->addCSS(_ALIRO_ADMIN_DIR.'/components /com_text/admin.text.css'); if ($subhead) $subhead = "<small>[$subhead]</small>"; return <<<HEAD_HTML <table class="adminheading"> <tr> <th class="user"> {$this->T_('Simple Text')} $subhead </th> </tr> </table>HEAD_HTML; } }
Read more
  • 0
  • 0
  • 2309

article-image-creating-shopping-cart-using-zend-framework-part-1
Packt
27 Oct 2009
13 min read
Save for later

Creating a Shopping Cart using Zend Framework: Part 1

Packt
27 Oct 2009
13 min read
Our next task in creating the storefront is to create the shopping cart. This will allow users to select the products they wish to purchase. Users will be able to select, edit, and delete items from their shopping cart. Lets get started. Creating the Cart Model and Resources We will start by creating our model and model resources. The Cart Model differs from our previous model in the fact that it will use the session to store its data instead of the database. Cart Model The Cart Model will store the products that they wish to purchase. Therefore, the Cart Model will contain Cart Items that will be stored in the session. Let's create this class now. application/modules/storefront/models/Cart.php class Storefront_Model_Cart extends SF_Model_Abstract implements SeekableIterator, Countable, ArrayAccess { protected $_items = array(); protected $_subTotal = 0; protected $_total = 0; protected $_shipping = 0; protected $_sessionNamespace; public function init() { $this->loadSession(); } public function addItem( Storefront_Resource_Product_Item_Interface $product,$qty) { if (0 > $qty) { return false; } if (0 == $qty) { $this->removeItem($product); return false; } $item = new Storefront_Resource_Cart_Item( $product, $qty ); $this->_items[$item->productId] = $item; $this->persist(); return $item; } public function removeItem($product) { if (is_int($product)) { unset($this->_items[$product]); } if ($product instanceof Storefront_Resource_Product_Item_Interface) { unset($this->_items[$product->productId]); } $this->persist(); } public function setSessionNs(Zend_Session_Namespace $ns) { $this->_sessionNamespace = $ns; } public function getSessionNs() { if (null === $this->_sessionNamespace) { $this->setSessionNs(new Zend_Session_Namespace(__CLASS__)); } return $this->_sessionNamespace; } public function persist() { $this->getSessionNs()->items = $this->_items; $this->getSessionNs()->shipping = $this->getShippingCost(); } public function loadSession() { if (isset($this->getSessionNs()->items)) { $this->_items = $this->getSessionNs()->items; } if (isset($this->getSessionNs()->shipping)) { $this->setShippingCost($this->getSessionNs()->shipping); } } public function CalculateTotals() { $sub = 0; foreach ($this as $item) { $sub = $sub + $item->getLineCost(); } $this->_subTotal = $sub; $this->_total = $this->_subTotal + (float) $this->_shipping; } public function setShippingCost($cost) { $this->_shipping = $cost; $this->CalculateTotals(); $this->persist(); } public function getShippingCost() { $this->CalculateTotals(); return $this->_shipping; } public function getSubTotal() { $this->CalculateTotals(); return $this->_subTotal; } public function getTotal() { $this->CalculateTotals(); return $this->_total; } /*...*/ } We can see that the Cart Model class is fairly weighty and in fact, we have not included the full class here. The reason we have slightly truncated the class is that we are implementing the SeekableIterator, Countable, and ArrayAccess interfaces. These interfaces are defined by PHP's SPL Library and we use them to provide a better way to interact with the cart data. For the complete code, copy the methods below getTotal() from the example files for this article. We will look at what each method does shortly in the Cart Model implementation section, but first, let's look at what functionality the SPL interfaces allow us to add. Cart Model interfaces The SeekableIterator interface allows us to access our cart data in these ways: // iterate over the cartforeach($cart as $item) {}// seek an item at a position$cart->seek(1);// standard iterator access$cart->rewind();$cart->next();$cart->current(); The Countable interface allows us to count the items in our cart: count($cart); The ArrayAccess interface allows us to access our cart like an array: $cart[0]; Obviously, the interfaces provide no concrete implementation for the functionality, so we have to provide it on our own. The methods not listed in the previous code listing are: offsetExists($key) offsetGet($key) offsetSet($key, $value) offsetUnset($key) current() key() next() rewind() valid() seek($index) count() We will not cover the actual implementation of these interfaces, as they are standard to PHP. However, you will need to copy all these methods from the example files to get the Cart Model working. Documentation for the SPL library can be found athttp://www.php.net/~helly/php/ext/spl/     Cart Model implementation Going back to our code listing, let's now look at how the Cart Model is implemented. Let's start by looking at the properties and methods of the class. The Cart Model has the following class properties: $_items:An array of cart items $_subTotal: Monetary total of cart items $_total: Monetary total of cart items plus shipping $_shipping: The shipping cost $_sessionNamespace: The session store The Cart Model has the following methods: init(): Called during construct and loads the session data addItem(Storefront_Resource_Product_Item_Interface $product, $qty): Adds or updates items in the cart removeItem($product): Removes a cart item setSessionNs(Zend_Session_Namespace $ns): Sets the session instance to use for storage getSessionNs(): Gets the current session instance persist(): Saves the cart data to the session loadSession(): Loads the stored session values calculateTotals(): Calculates the cart totals setShippingCost($cost): Sets the shipping cost getShippingCost(): Gets the shipping cost getSubTotal(): Gets the total cost for items in the cart (not including the shipping) getTotal(): Gets the subtotal plus the shipping cost When we instantiate a new Cart Model instance, the init() method is called. This is defined in the SF_Model_Abstract class and is called by the __construct() method. This enables us to easily extend the class's instantiation process without having to override the constructor. The init() method simply calls the loadSession() method. This method populates the model with the cart items and shipping information stored in the session. The Cart Model uses Zend_Session_Namespace to store this data, which provides an easy-to-use interface to the $_SESSION variable. If we look at the loadSession() method, we see that it tests whether the items and shipping properties are set in the session namespace. If they are, then we set these values on the Cart Model. To get the session namespace, we use the getSessionNs() method. This method checks if the $_sessionNs property is set and returns it. Otherwise it will lazy load a new Zend_Session_Namespace instance for us. When using Zend_Session_ Namespace, we must provide a string to its constructor that defines the name of the namespace to store our data in. This will then create a clean place to add variables to, without worrying about variable name clashes. For the Cart Model, the default namespace will be Storefront_Model_Cart. The Zend_Session_Namespace component provides a range of functionality that we can use to control the session. For example, we can set the expiration time as follows: $ns = new Zend_Session_Namespace('test');$ns->setExpirationSeconds(60, 'items');$ns->setExpirationHops(10);$ns->setExpirationSeconds(120); This code would set the item's property expiration to 60 seconds and the namespaces expiration to 10 hops (requests) or 120 seconds, whichever is reached first. The useful thing about this is that the expiration is not global. Therefore, we can have specialized expiration per session namespace. There is a full list of Zend_Session_Namespace functionalities in the reference manual. Testing with Zend_Session and Zend_Session_NamespaceTesting with the session components can be fairly diffi cult. For the Cart Model, we use the setSessionNs() method to allow us to inject a mock object for testing, which you can see in the Cart Model unit tests. There are plans to rewrite the session components to make testing easier in the future, so keep an eye out for those updates. To add an item to the cart, we use the addItem() method. This method accepts two parameters,$product and $qty. The $product parameter must be an instance of the Storefront_Resource_Product_Item class, and the $qty parameter must be an integer that defines the quantity that the customer wants to order. If the addItem() method receives a valid $qty, then it will create a new Storefront_Resource_Cart_Item and add it to the $_items array using the productId as the array key. We then call the persist() method. This method simply stores all the relevant cart data in the session namespace for us. You will notice that we are not using a Model Resource in the Cart Model and instead we are directly instantiating a Model Resource Item. This is because the Model Resources represent store items and the Cart Model is already doing this for us so it is not needed. To remove an item, we use the removeItem() method. This accepts a single parameter $product which can be either an integer or a Storefront_Resource_Product_Item instance. The matching cart item will be removed from the $_items array and the data will be saved to the session. Also, addItem() will call removeItem() if the quantity is set to zero. The other methods in the Cart Model are used to calculate the monetary totals for the cart and to set the shipping. We will not cover these in detail here as they are fairly simple mathematical calculations. Cart Model Resources Now that we have our Model created, let's create the Resource Interface and concrete Resource class for our Model to use. application/modules/storefront/models/resources/Cart/Item/Interface.php interface Storefront_Resource_Cart_Item_Interface { public function getLineCost(); } The Cart Resource Item has a very simple interface that has one method, getLineCost(). This method is used when calculating the cart totals in the Cart Model. application/modules/storefront/models/resources/Cart/Item.php class Storefront_Resource_Cart_Item implements Storefront_Resource_Cart_Item_Interface { public $productId; public $name; public $price; public $taxable; public $discountPercent; public $qty; public function __construct(Storefront_Resource_Product_Item_ Interface $product, $qty) { $this->productId = (int) $product->productId; $this->name = $product->name; $this->price = (float) $product->getPrice(false,false); $this->taxable = $product->taxable; $this->discountPercent = (int) $product->discountPercent; $this->qty = (int) $qty; } public function getLineCost() { $price = $this->price; if (0 !== $this->discountPercent) { $discounted = ($price*$this->discountPercent)/100; $price = round($price - $discounted, 2); } if ('Yes' === $this->taxable) { $taxService = new Storefront_Service_Taxation(); $price = $taxService->addTax($price); } return $price * $this->qty; } } The concrete Cart Resource Item has two methods __construct() and getLineCost(). The constructor accepts two parameters $product and $qty that must be a Storefront_Resource_Product_Item_Interface instance and integer respectively. This method will then simply copy the values from the product instance and store them in the matching public properties. We do this because we do not want to simply store the product instance because it has all the database connection data contained within. This object will be serialized and stored in the session. The getLineCost() method simply calculates the cost of the product adding tax and discounts and then multiplies it by the given quantity. Shipping Model We also need to create a Shipping Model so that the user can select what type of shipping they would like. This Model will simply act as a data store for some predefined shipping values. application/modules/storefront/models/Shipping.php class Storefront_Model_Shipping extends SF_Model_Abstract { protected $_shippingData = array( 'Standard' => 1.99, 'Special' => 5.99, ); public function getShippingOptions() { return $this->_shippingData; } } The shipping Model is very simple and only contains the shipping options and a single method to retrieve them. In a normal application, shipping would usually be stored in the database and most likely have its own set of business rules. For the Storefront, we are not creating a complete ordering process so we do not need these complications. Creating the Cart Controller With our Model and Model Resources created, we can now start wiring the application layer together. The Cart will have a single Controller, CartController that will be used to add, view, and update cart items stored in the Cart Model. application/modules/storefront/controllers/CartController.php class Storefront_CartController extends Zend_Controller_Action { protected $_cartModel; protected $_catalogModel; public function init() { $this->_cartModel = new Storefront_Model_Cart(); $this->_catalogModel = new Storefront_Model_Catalog(); } public function addAction() { $product = $this->_catalogModel->getProductById( $this->_getParam('productId') ); if(null === $product) { throw new SF_Exception('Product could not be added to cart as it does not exist' ); } $this->_cartModel->addItem( $product, $this->_getParam('qty') ); $return = rtrim( $this->getRequest()->getBaseUrl(), '/' ) . $this->_getParam('returnto'); $redirector = $this->getHelper('redirector'); return $redirector->gotoUrl($return); } public function viewAction() { $this->view->cartModel = $this->_cartModel; } public function updateAction() { foreach($this->_getParam('quantity') as $id => $value) { $product = $this->_catalogModel->getProductById($id); if (null !== $product) { $this->_cartModel->addItem($product, $value); } } $this->_cartModel->setShippingCost( $this->_getParam('shipping') ); return $this->_helper->redirector('view'); } } The Cart Controller has three actions that provide a way to: add: add cart items view: view the cart contents update: update cart items The addAction() first tries to find the product to be added to the cart. This is done by searching for the product by its productId field, which is passed either in the URL or by post using the Catalog Model. If the product is not found, then we throw an SF_Exception stating so. Next, we add the product to the cart using the addItem() method. When adding the product, we also pass in the qty. The qty can again be either in the URL or post. Once the product has been successfully added to the cart, we then need to redirect back to the page where the product was added. As we can have multiple locations, we send a returnto variable with the add request. This will contain the URL to redirect back to, once the item has been added to the cart. To stop people from being able to redirect away from the storefront, we prepend the baseurl to the redirect string. To perform the actual redirect, we use the redirector Action Helper's gotoUrl() method. This will create an HTTP redirect for us. The viewAction() simply assigns the Cart Model to the cartModel View property. Most of the cart viewing functionality has been pushed to the Cart View Helper and Forms, which we will create shortly. The updateAction() is used to update the Cart Items already stored in the cart. The first part of this updates the quantities. The quantities will be posted to the Action as an array in the quantity parameter. The array will contain the productId as the array key, and the quantity as the value. Therefore, we iterate over the array fi nding the product by its ID and adding it to the cart. The addItem() method will then update the quantity for us if the item exists and remove any with a zero quantity. Once we have updated the cart quantities, we set the shipping and redirect back to the viewAction. >> Continue Reading Creating a Shopping Cart using Zend Framework: Part 2
Read more
  • 0
  • 0
  • 5671

article-image-jboss-tools-palette
Packt
26 Oct 2009
4 min read
Save for later

JBoss Tools Palette

Packt
26 Oct 2009
4 min read
By default, JBoss Tools Palette is available in the Web Development perspective that can be displayed from the Window menu by selecting the Open Perspective | Other option. In the following screenshot, you can see the default look of this palette: Let's dissect this palette to see how it makes our life easier! JBoss Tools Palette Toolbar Note that on the top right corner of the palette, we have a toolbar made of three buttons (as shown in the following screenshot). They are (from left to right): Palette Editor Show/Hide Import Each of these buttons accomplishes different tasks for offering a high level of flexibility and customizability. Next, we will focus our attention on each one of these buttons. Palette Editor Clicking on the Palette Editor icon will display the Palette Editor window (as shown in the following screenshot), which contains groups and subgroups of tags that are currently supported. Also, from this window you can create new groups, subgroups, icons, and of course, tags—as you will see in a few moments. As you can see, this window contains two panels: one for listing groups of tag libraries (left side) and another that displays details about the selected tag and allows us to modify the default values (extreme right). Modifying a tag is a very simple operation that can be done like this: Select from the left panel the tag that you want to modify (for example, the <div> tag from the HTML | Block subgroup, as shown in the previous screenshot). In the right panel, click on the row from the value column that corresponds to the property that you want to modify (the name column). Make the desirable modification(s) and click the OK button for confirming it (them). Creating a set of icons The Icons node from the left panel allows you to create sets of icons and import new icons for your tags. To start, you have to right-click on this node and select the Create | Create Set option from the contextual menu (as shown in the following screenshot). This action will open the Add Icon Set window where you have to specify a name for this new set. Once you're done with the naming, click on the Finish button (as shown in the following screenshot). For example, we have created a set named eHTMLi: Importing an icon You can import a new icon in any set of icons by right-clicking on the corresponding set and selecting the Create | Import Icon option from the contextual menu (as shown in the following screenshot): This action will open the Add Icon window, where you have to specify a name and a path for your icon, and then click on the Finish button (as shown in the following screenshot). Note that the image of the icon should be in GIF format. Creating a group of tag libraries As you can see, the JBoss Tools Palette has a consistent default set of groups of tag libraries, like HTML, JSF, JSTL, Struts, XHTML, etc. If these groups are insufficient, then you can create new ones by right-clicking on the Palette node and selecting the Create | Create Group option from the contextual menu (as shown in the following screenshot). This action will open the Create Group window, where you have to specify a name for the new group, and then click on Finish. For example, we have created a group named mygroup: Note that you can delete (only groups created by the user) or edit groups (any group) by selecting the Delete or Edit options from the contextual menu that appears when you right-click on the chosen group. Creating a tag library Now that we have created a group, it's time to create a library (or a subgroup). To do this, you have to right-click on the new group and select the Create Group option from the contextual menu (as shown in the following screenshot). This action will open the Add Palette Group window, where you have to specify a name and an icon for this library, and then click on the Finish button (as shown in the following screenshot). As an example, we have created a library named eHTML with an icon that we had imported in the Importing an icon section discussed earlier in this article: Note that you can delete a tag library (only tag libraries created by the user) by selecting the Delete option from the contextual menu that appears when you right-click on the chosen library.
Read more
  • 0
  • 0
  • 1669
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 €18.99/month. Cancel anytime
article-image-new-soa-capabilities-biztalk-server-2009-wcf-sql-server-adapter
Packt
26 Oct 2009
3 min read
Save for later

New SOA Capabilities in BizTalk Server 2009: WCF SQL Server Adapter

Packt
26 Oct 2009
3 min read
Do not go where the path may lead; go instead where there is no path and leave a trail.-Ralph Waldo Emerson Many of the patterns and capabilities shown in this article are compatible with the last few versions of the BizTalk Server product. So what's new in BizTalk Server 2009?` BizTalk Server 2009 is the sixth formal release of the BizTalk Server product. This upcoming release has a heavy focus on platform modernization through new support for Windows Server 2008, Visual Studio.NET 2008, SQL Server 2008, and the .NET Framework 3.5. This will surely help developers who have already moved to these platforms in their day-to-day activities but have been forced to maintain separate environments solely for BizTalk development efforts. Lets get started. What is the WCF SQL Adapter? The BizTalk Adapter Pack 2.0 now contains five system and data adapters including SAP, Siebel, Oracle databases, Oracle applications, and SQL Server. What are these adapters and how are they different than the adapters available for previous version of BizTalk? Up until recently, BizTalk adapters were built using a commonly defined BizTalk Adapter Framework. This framework prescribed interfaces and APIs for adapter developers in order to elicit a common look and feel for the users of the adapters. Moving forward, adapter developers are encouraged by Microsoft to use the new WCF LOB Adapter SDK. As you can guess from the name, this new adapter framework, which can be considered an evolution of the BizTalk Adapter Framework, is based on WCF technologies. All of the adapters in the BizTalk Adapter Pack 2.0 are built upon the WCF LOB Adapter SDK. What this means is that all of the adapters are built as reusable, metadata-rich components that are surfaced to users as WCF bindings. So much like you have a wsHttp or netTcp binding, now you have a sqlBinding or sapBinding. As you would expect from a WCF binding, there is a rich set of configuration attributes for these adapters and they are no longer tightly coupled to BizTalk itself. Microsoft has made connection a commodity, and no longer do organizations have to spend tens of thousands of dollars to connect to line of business systems like SAP through expensive, BizTalk-only adapters. This latest version of the BizTalk Adapter Pack now includes a SQL Server adapter, which replaces the legacy BizTalk-only SQL Server adapter. What do we get from this SQL Server adapter that makes it so much better than the old one? Feature Classic SQL Adapter WCF SQL Adapter Execute create-read-update-delete statements on tables and views; execute stored procedures and generic T-SQL statements Partial (send operations only support stored procedures and updategrams) Yes Database polling via FOR XML Yes Yes Database polling via  traditional tabular results No Yes Proactive database push via SQL Query Notification No Yes Expansive adapter configuration which impacts connection management and transaction behavior No Yes Support for composite transactions which allow aggregation of operations across tables or procedures into a single atomic transaction No Yes Rich metadata browsing and retrieval for finding and selecting database operations No Yes Support for the latest data types (e.g. XML) and SQL Server 2008 platform No Yes Reusable outside of BizTalk applications by WCF or basic HTTP clients No Yes Adapter extension and configuration through out of the box WCF components or custom WCF behaviors No Yes Dynamic WSDL generation which always reflects current state of the system instead of fixed contract which always requires explicit updates No Yes
Read more
  • 0
  • 0
  • 4874

article-image-building-your-first-application-papervision3d-part-2
Packt
26 Oct 2009
10 min read
Save for later

Building your First Application with Papervision3D: Part 2

Packt
26 Oct 2009
10 min read
This article covers: Basics of a 3D composition in Papervision3D Building your first application Basics of a 3D scene in Papervision3D Before we're ready to program some code for Papervision3D, we need to know a little bit more about 3D in Papervision3D. The following section is meant to give you a better understanding of the code that you will write. Each of these concepts relates directly to classes that are used by Papervision3D. All the object types that will be described are active elements in a 3D scene. Let's have a visualized look at all these objects: Scene The scene is the entire composition of 3D objects in a 3D space. Think of it as your stage in Flash with three axes—x, y, and z. Each object that you want to be visible should be added to the scene. If you don't add objects to the scene, they will not appear on your screen. Camera You can think of this as a real camera, which is somewhere in 3D space recording activity inside the scene. The camera defines the point of view from which you are viewing the scene. Because a camera in 3D is not a visible object, it is not part of our scene and you don't need to add it. Like a real camera you can, for example, zoom and focus. Cameras in 3D space can usually do more than real cameras. For example, in 3D you can, exclude objects to be rendered, when they are too close or too far away from the camera. The camera is able to ignore objects that are not in a certain, defined range. This is done for performance reasons. Objects that are too far away, or even behind the camera, don't need to be recorded, saving a lot of calculation for objects that are in a position where the camera simply can't see them. Viewport A viewport is a container sprite on your stage, and shows the output of what the camera sees. In the illustrative object overview, this has been compared with the lens of the camera. The lens is our window onto the 3D scene. We can make this window small and see just a small part of the scene, or make it big and see a lot. This works exactly as a real window in a wall—making it bigger will not affect how the world outside looks, but will have an effect on how much we can see from this world. The following illustration contains the visualization of a relatively big viewport on the left, along with a relatively small and wide viewport on the right. The thick dark outlines represent the viewports. In the right image, you can clearly see how the window to the 3D world works and how changing its size will not stretch the view of the 3D object in the scene. It only affects how much we see of it. 3D Objects A shape in 3D space is called a 3D object, or DisplayObject3D in Papervision3D. You can think of 3D objects as more advanced display objects just like sprites and movie clips. The difference is that a DisplayObject3D has a third axis, so we can place it anywhere in 3D space and rotate over each of the three axes. Material A material is the texture that is printed on an object. When an object doesn't have a material applied, it will be invisible. There are a variety of materials available for you to use. For example, a very simple material is a color; a more advanced example of a material could be a live streaming video. Render engine A render engine is like a rolling camera. As long as you trigger the render engine, it will output information of the scene recorded by the camera to the viewport. When you stop triggering the render engine, your viewport will not show any new image from the scene and shows the last rendered image. Rendering is actually the most intensive task for your computer, as it needs to recalculate each object that is placed inside your scene and output this to the viewport. Left-handed Cartesian coordinate system Flash, as well as Papervision3D, make use of the Cartesian coordinate system. In Flash, a regular visual object can be positioned on the stage by entering an x and y value. The object will be positioned according to these values and relative to the upper left corner of the stage. A higher x value moves the object to the right, whereas a higher y value moves it downward. The coordinate system in Papervision3D works essentially the same, except for the following two differences: Flash uses Cartesian coordinates on two axes, whereas Papervision3D makes use of them on three axes The y-axis in Flash is inversed compared to the y-axis in Papervision3D In Papervision3D, we want to position objects not only on the x and y axes, but also on an extra axis, in order to position objects in depth. This third axis is called the z-axis. In Flash, objects are positioned relative to the upper left corner, which is the 0, 0 coordinate. This is called the center point, or the origin. Predictably, the position of the origin in 3D space is located at 0, 0, 0. The three axes and the origin point are illustrated by the following image: The plus and minus signs illustrate whether the coordinate values are increasing or decreasing in the direction away from the origin. Notice that the y-axis is inverted compared to 2D coordinates in Flash. When you want to position an object lower on your screen in Flash, you need to give it a higher y position. This is how 2D coordinates on a computer screen work. The above figure shows the y-axis as according to the coordinate system as it is used by Papervision3D. Creating a basic class for Papervision3D In the previous sections you've learned what a basic scene is made of, and how you can create your own classes. Now that we have gone through all this theory, it's now time that we get our hands dirty by writing some code. Start your favorite authoring tool. The first application we'll build is a 3D scene containing a sphere that is rotating over its y-axis. A sphere is basically a "3D ball" and is built into Papervision3D as one of the default primitives. The basic document class First, have a look at the document class that defines the basic structure for the rotating sphere application. package { import flash.display.Sprite; import org.papervision3d.cameras.Camera3D; import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.render.BasicRenderEngine; import org.papervision3d.scenes.Scene3D; import org.papervision3d.view.Viewport3D; public class FirstApplication extends Sprite { private var scene:Scene3D; private var viewport:Viewport3D; private var camera:Camera3D; private var renderEngine:BasicRenderEngine; private var sphere:Sphere; public function FirstApplication() { scene = new Scene3D(); camera = new Camera3D(); sphere = new Sphere(); scene.addChild(sphere); viewport = new Viewport3D(); addChild(viewport); renderEngine = new BasicRenderEngine(); renderEngine.renderScene(scene,camera,viewport); } }} Let's have a look at this in detail. While we do that, you can create a new project in Flash, Flex Builder, or Flash Builder with a document class called FirstApplication. If you're using Flex Builder or Flash Builder, don't forget to configure the path to the Papervision3D source. We know that we need to have a scene, a camera, a viewport, a 3D object with a material, and a render engine, in order to create a rendered output on the screen. Remember that the document class needs to extend Sprite. To make all these available inside the class, we need to import them first. import flash.display.Sprite;import org.papervision3d.cameras.Camera3D;import org.papervision3d.objects.primitives.Sphere;import org.papervision3d.render.BasicRenderEngine;import org.papervision3d.scenes.Scene3D;import org.papervision3d.view.Viewport3D; Now that the imports are set, we define the properties of the class. private var scene:Scene3D;private var viewport:Viewport3D;private var camera:Camera3D;private var renderEngine:BasicRenderEngine;private var sphere:Sphere; We only define the properties and their class types here, without assigning any value. We'll do that inside the constructor. Let's first create the constructor. public function FirstApplication(){} We start by creating a scene inside the constructor. A scene is needed as the holder for our 3D objects. It's very easy to create one. scene = new Scene3D(); All you have to do is create an instance of the Scene3D class, which doesn't take any parameters. Next, we add a Camera3D, which is just as easy as the creation of a new Scene. camera = new Camera3D(); A camera can take parameters when you create a new instance; however, the default values will do for now. The scene and camera are useless as long as there are no 3D objects in the scene to film. For this example a sphere will be used, which is one of the built-in 3D objects. sphere = new Sphere(); A camera, as well as a sphere, takes parameters when you instantiate it. However, when you do not pass any parameters, a default sphere will be created. Now that we have created our sphere, we need to add it to the scene, otherwise it will not be seen by the camera. This works in exactly the same way as adding regular display objects to the display list in Flash, by using the addChild() method. scene.addChild(sphere); That looks familiar, right? Now that we have a scene, a camera, and a sphere, we need to set up the window to the 3D scene, so we can see what is going on in there. We need to define our viewport and add it to the stage to make it visible. viewport = new Viewport3D();addChild(viewport); While creating a new viewport, you can pass optional parameters to it, but the default parameters are again fine for now. We are now just one step away from publishing our application. First we need to get our camera rolling. This is done by defining the render engine, which will render the current view of the camera to the viewport. renderEngine = new BasicRenderEngine();renderEngine.renderScene(scene,camera,viewport); Now that the render engine is defined and an instruction to render the scene is added, we are ready to publish this project. This should result in the following image of triangles that together form something like a circle: Case sensitivityPay attention to upper cases and lower cases in the examples. Not following these conventions might result in an error. A good example of this is the definition and instantiation of a sphere as we did in our FirstApplication.var sphere:Sphere = new Sphere();Here we see that we have defined a class property called sphere (lowercase) of a Sphere (uppercase) type, containing an instance of Sphere (uppercase). Giving a variable/property the same name as the defined object type will often cause problems. The result of these few lines of code may not look very impressive yet, but in fact this is the beginning of something that will soon become exciting and could never be accomplished this easy by regular Flash use. When you have managed to compile this application that shows the triangles, you've made it through the hardest part of this example. Let's continue building your first application and see how we can add the illusion of 3D to our object, which still looks very 2D.
Read more
  • 0
  • 0
  • 2094

article-image-graphical-report-design-ireport-part-1
Packt
26 Oct 2009
7 min read
Save for later

Graphical Report Design with iReport: Part 1

Packt
26 Oct 2009
7 min read
In 2008, iReport was rewritten to take advantage of the NetBeans platform. It is freely available both as a standalone product and as a plugin to the NetBeans IDE. In this article, we will be covering the standalone version of iReport; however, the material is also applicable to the iReport NetBeans plugin. By the end of this article, you will be able to: Obtain and set up iReport Quickly create database reports by taking advantage of iReport's Report Wizard Design reports graphically with iReport Obtaining iReport iReport can be downloaded from its home page at http://jasperforge.org/projects/ireport by clicking on the Download iReport image slightly above the center of the page. Once we click on the image, we are directed to an intermediate page where we can either log in with our JasperForge account or go straight to the download page. Either logging in or clicking on the No Thanks, Download Now button takes us to the iReport download page. The standalone iReport product is in the first row of the table on the page. To download it, we simply click on the Download link in the last column. Other downloads on the page are for older versions of JasperReports, iReport NetBeans plugin, and other JasperSoft products. iReport can be downloaded as a DMG file for Macintosh computers, as a Windows installer for Windows PCs, as a source file, as a ZIP file, or as a gzipped TAR file. To install iReport, simply follow the usual application installation method for your platform. If you chose to download the ZIP or gzipped TAR file, simply extract it into any directory. A subdirectory called something like iReport-nb-3.5.1 will be created. (The exact name will depend on the version of iReport that was downloaded.) Inside this directory, you will find a bin subdirectory containing an executable shell script called ireport and a couple of Windows executables, ireport.exe and ireport_w.exe. On Windows systems, either EXE file will start iReport. The difference between the two Windows executables is that theireport.exe will display a command-line window when iReport is executed, and ireport_w.exe won't. Both versions provide exactly the same functionality. On Unix and Unix-like systems, such as Linux and Mac OS, iReport can be started by executing the ireport shell script. The following screenshot illustrates how iReport looks when it is opened for the first time: Setting up iReport iReport can help us quickly generate database reports. To do so, we need to provide it with the JDBC driver and connection information for our database. iReport comes bundled with JDBC drivers for several open source relational database systems, such as MySQL, PostgreSQL, HSQLDB, and others. If we want to connect to a different database, we need to add the JDBC driver to iReport's CLASSPATH. This can be done by clicking on Tools | Options and then selecting the Classpath tab. To add the JDBC driver to the CLASSPATH, click on the Add JAR button, and then navigate to the location of the JAR file containing the JDBC driver. Select the JAR file and click on the OK button at the bottom of the window. We won't actually add a JDBC driver, as we are using MySQL for our examples, which is one of the RDBMS systems supported out of the box by iReport. The information just provided is for the benefit of readers using an RDBMS system that is not supported out of the box. Before we can create reports that use an RDBMS as a datasource, we need to create a database connection. In order to do so, we need to click on the Report Datasources icon in the toolbar: After doing so, the Connections / Datasources configuration window should pop up. To add the connection, we need to click on the New button, select Database JDBC connection, and then click on the Next> button. We then need to select the appropriate JDBC driver, fill in the connection information, and click on the Save button. Before saving the database connection properties, it is a good idea to click on theTest button to make sure we can connect to the database. If we can, we should see a pop-up window like the following: After verifying that we can successfully connect to the database, we are ready to create some database reports. Creating a database report in record time iReport contains a wizard that allows us to quickly generate database reports (very useful if the boss asks for a report 15 minutes before the quitting time on a Friday!). The wizard allows us to use one of the predefined templates that are included with iReport. The included report templates are divided into two groups: templates laid out in a "columnar" manner and templates laid out in a "tabular" manner. Columnar templates generate reports that are laid out in columns, and tabular templates generate reports that are laid out like a table. In this section, we will create a report displaying all the aircraft with a horsepower of 1000 or more. To quickly create a database report, we need to go to File | New | Report Wizard. We should then enter an appropriate name and location for our report and click on Next>. Next, we need to select the datasource or database connection to use for our report. For our example, we will use the JDBC connection we configured in the previous section. We can then enter the database query we will use to create the report. Alternatively, we can use the iReport query designer to design the query. For individuals with SQL experience, in many cases it is easier to come up with the database query in a separate database client tool and then paste it in the Query text area than using the query designer. The complete query for the report is: selecta.tail_num,a.aircraft_serial,am.model as aircraft_model,ae.model as engine_modelfrom aircraft a, aircraft_models am, aircraft_engines aewhere a.aircraft_model_code = am.aircraft_model_codeand a.aircraft_engine_code = ae.aircraft_engine_codeand ae.horsepower >= 1000 The following window shows a list of all the columns selected in the query, allowing us to select which ones we would like to use as report fields: In this case, we want the data for all columns in the query to be displayed in the report. Therefore, we select all columns by clicking on the second button. We then select how we want to group the data and click on Next>. This creates a report group. In this example, we will not group the report data. The screenshot illustrates how the drop-down box contains the report fields selected in the previous step. We then select the report layout (Columnar or Tabular). In this example, we will use the Tabular Layout. After selecting the layout, we click on Next> to be presented with the last step. We then click on Finish to generate the report's JRXML template. While the template is automatically saved when it is created, the report generated by the Preview button is not automatically saved. We can then preview our report by clicking on Preview. That's it! We have created a report by simply entering a query and selecting a few options from a wizard.  
Read more
  • 0
  • 0
  • 3108

article-image-storing-planning-data-ibm-cognos-d-cube-part-2
Packt
26 Oct 2009
6 min read
Save for later

Storing Planning Data in IBM Cognos: D-Cube (Part 2)

Packt
26 Oct 2009
6 min read
Exporting data from the D-Cube You can export data from the D-Cube into an ASCII file or to the clipboard. The export function gives you the ability to format how you want to export the data. You can set the delimiter, insert headers, and arrange the order of the dimensions. You can also suppress zero values in calculated data so that the export function will not include records that have zero or null data. To export from a D-Cube: Open the D-Cube. Click on D-Cube|Export. The Export function displays four tabs: Export Header/Footer Zeros Show Det/Tot Export Observe the following: Under the Export to option, select whether you want to export to a file or to the clipboard. If you are exporting to a file, enter the path and name of the file that you want to export the data to. Alternatively, you can click on the Browse button to save the file. Click the Select button to open the item selection box, and then select the dimension items containing the data you want to export. If you have a saved selection containing the data that you want to export, then you can load that selection into the dimension selection box. Groups Select how you want the dimensions to be displayed as columns: Single Column: Export each dimension as a single column. Multiple Column: Select one dimension whose items you want displayed as separate columns, and set the rest of the dimensions as single columns. The last dimension marked as [data] under the Dimension Order box contains the items that will used as multiple columns (see the following example): Single vs. multiple columns The following table illustrates a single column file with each dimension laid out as a separate column:       The following table illustrates a multiple column file. In this example, the items in the Month dimension are displayed as separate columns.       Format In the Format section, select the following: Separator: Set the delimiter to be used in the export file. Select Comma, Tab, Semicolon, or Aligned Columns. Column Headings Normal: This is the default setting. If you export in multiple columns, this option will include columns headers on each page but not for the rows and page dimensions. If you export in single columns, this no column headers will be included. At Top: This option includes the D-List names and column headers at the top of first page only. Above Each Page: This option includes the D-List names and column headers at the top of each page of the export. None: This option does not include column headers at all. Mode Append: Add the data to any previously-exported data in the same file. Overwrite: Overwrite any previously-exported data in the same file. Data formats: Apply Regional Settings: Select this checkbox to use the regional settings in your operating system as the format for the export. Pipes as Spaces: Select this checkbox to replace any pipe symbols (|) with spaces. Plain Number Format: Select this option to remove any numeric formats that you applied in the D-List. The values are exported in as many decimal places as is necessary in is basic format. All commas, currency signs, and percentages will be removed. Negative values enclosed in parenthesis will be prefixed with a minus sign. Non-numeric formats (Text, Date, and D-List) will be retained. Text Qualifier: Choose whether you want the data exported with a single quote or double quote text qualifier. Dimension Order: Determine the order of the dimensions that will be exported as columns. Move the dimensions up or down using the arrows, or click the Dimension Order button to arrange the dimensions according to their order in the D-Cube. Header/Footer This option lets you enter a title and/or footer to the export file. Enter the title or footnote by typing directly into the text box. Zeros This option suppresses any record with zero values. This option is independent of the zero suppression in force when you are viewing the D-Cube. You can suppress zeros in rows or columns by highlighting the dimension labeled R or C respectively. You can deselect a selected dimension by pressing Ctrl and clicking on the highlighted item. To suppress zeros in pages, select Suppress Zero Pages. If you want to suppress zeros in all of the dimensions, highlight all of the dimensions and then select Suppress Zero Pages. Show Det/Tot This option lets you choose whether you want to export only detail items or calculated items by highlighting the dimensions containing the detail or subtotal items, as appropriate. There are separate selection boxes for detail and total items. Breakback Breakback is a powerful feature in IBM Cognos Planning. With Breakback, you can enter data into calculated cells and change the variables that make up the formula according to rules that you specify. Breakback is commonly used to propagate changes to a total across its detail items, in proportion to the value of the detail items. Suppose you have five products, showing a total of 1500 units:   Product Current Product A 100 Product B 200 Product C 300 Product D 400 Product E 500 TOTAL 1500 With Breakback, if you enter 3000 in the total, the detail products will change as follows:   Product With Breakback Product A 200 Product B 400 Product C 600 Product D 800 Product E 1000 TOTAL 3000 Breakback distributes the changes in the TOTAL to Products A to E in proportion to their original share of the total. Breakback works on addition, subtraction, multiplication, and division. It can handle multiple calculations across multiple dimensions and hierarchies. Breakback on hierarchies You can apply Breakback on a grand total consisting of multiple subtotals across various hierarchical levels. In a simple hierarchy where you have only one subtotal, Breakback distributes the value across its children proportionately. In a multi-level hierarchy, Breakback cascades the changes one level at a time down through the hierarchy. If you enter a value into a total, Breakback will distribute the value proportionately to the subtotals immediately below the total, then to the subtotal the next level down, and so on.
Read more
  • 0
  • 0
  • 2370
article-image-trunks-freepbx-25
Packt
26 Oct 2009
5 min read
Save for later

Trunks in FreePBX 2.5

Packt
26 Oct 2009
5 min read
A trunk in the simplest of terms is a pathway into or out of a telephone system. A trunk connects a PBX to outside resources, such as PSTN telephone lines, or additional PBX systems to perform inter-system transfers. Trunks can be physical, such as a PRI or PSTN line, or they can be virtual by routing calls to another endpoint using Internet Protocol (IP) links. Trunk types FreePBX allows the creation of six different types of trunks as follows: Zap IAX2 SIP ENUM DUNDi Custom Zap, IAX2, and SIP trunks utilize the technologies of their namesake. These trunks have the same highlights and pitfalls that extensions and devices using the same technology do. Zap trunks require physical hardware cards for incoming lines to plug into. SIP trunks are the most widely adopted and compatible, but have difficulties traversing firewalls. IAX2 trunks are able to traverse most firewalls easily, but are limited to adoption mainly on Asterisk-based systems. In terms of VoIP, ENUM(E.164 NUmber Mapping) is a method for unifying E.164 (the international telecommunication numbering plan) with VoIP routing. The ENUM system can be considered very similar to the way that the Internet DNS system works. In the DNS system, when a domain name is looked up an IP address is returned. The IP address allows a PC to traverse the Internet and find the server that belongs to that IP address. The ENUM system provides VoIP routes back when queried for a phone number. The route that is returned is usually a SIP or IAX2 route. An ENUM trunk allows FreePBX to send the dialed phone number to the publice164.orgENUM server. If the called party has listed their phone number in the e164.org directory, a VoIP route will be returned and the call will be connected using that route. A VoIP route contains the VoIP protocol, the server name or IP address, the port, and the extension to use in order to contact the dialed phone number. For example, a SIP route for dialing the number 555-555-1234 might appear as SIP:1234@pbx.example.com:5060. This is advantageous in several ways. It is important to note that indirect routes to another telephony system are often costly. Calling a PSTN telephone number typically requires that call to route through a third-party provider's phone lines and switching equipment (a service they will happily charge for). If a number is listed in the ENUM directory, the returned route will bridge the call directly to the called party (or their provider), bypassing the cost of routing through a third party. ENUM also benefits the called party, allowing them to redirect inbound calls to wherever they would like. Service disruptions that would otherwise render a particular phone number useless can be bypassed by directing the phone number to a different VoIP route in the ENUM system. More information on ENUM can be found at the following web sites: The ENUM home page The e164.org home page: The Internet Engineering Task Force ENUM charter DUNDi (Distributed Universal Number Discovery) is a routing protocol technology similar to ENUM. In order to query another Asterisk system using DUNDi, that system must be "peered" with your own Asterisk system. Peering requires generating and exchanging key files with the other peer. DUNDi is a decentralized way of accomplishing ENUM-style lookups. By peering with one system you are effectively peering with any other system that your peer is connected to. If system A peers with system B, and system B peers with system C, then system C will be able to see the routes provided by system A. In peer-topeer fashion, system B will simply pass the request along to system A, even though system C has no direct connection to system A. DUNDi is not limited to E.164 numbering schemes like ENUM and it allows a PBX to advertise individual extensions, or route patterns, instead of whole phone numbers. Therefore, it is a good candidate for distributed office setups, where a central PBX can be peered with several satellite PBX systems. The extensions on each system will be able to call one another directly without having to statically set up routes on each individual PBX. More information on DUNDi can be found at the following web sites: DUNDi home page Example DUNDi SIP configuration Example DUNDi IAX2 configuration Custom trunks work in the same fashion as custom extensions do. Any valid Asterisk Dial command can be used as a custom trunk by FreePBX. Custom trunks typically use additional VoIP protocols such as H.323 and MGCP. Setting up a new trunk Setting up a trunk in FreePBX is very similar to setting up an extension. All of the trunks share eight common setup fields, followed by fields that are specific to the technology that trunk will be using. In order to begin setting up a trunk, click on Trunks in the left side navigation menu as shown in the following screenshot: From the Add a Trunk screen, click on the name of the technology that the trunk will be using (for example, if a SIP trunk will be used, click on Add SIP Trunk) as shown in the following screenshot:
Read more
  • 0
  • 0
  • 8319

article-image-adding-interactive-course-material-moodle-19-part-2
Packt
26 Oct 2009
1 min read
Save for later

Adding Interactive Course Material in Moodle 1.9: Part 2

Packt
26 Oct 2009
1 min read
Adding the First Question Page Immediately after you save your lesson settings, Moodle presents you with the following page: At this point, it is time to create the first question page or import question pages from another system. Let's take a look at each of your options. Importing Questions If you choose to Import questions, you can import questions created by Moodle and other online learning systems. Some of the formats that you can import are: GIFT and Moodle XML These are Moodle's proprietary formats. GIFT is text only, and XML can include graphics and special characters. Aiken This format is for multiple choice questions. Missing Word This format is for missing word multiple choice questions. Blackboard If you're converting from Blackboard to Moodle, you can export questions from Blackboard and import them into Moodle. WebCT This format supports multiple choice questions, and short answers questions from WebCT. Course Test Manager If you're converting from Course Test Manager to Moodle, you can export questions from Course Test Manager, and import them into Moodle. Embedded Answers (Cloze) This format is a multiple question, multiple-choice question with embedded answers.  
Read more
  • 0
  • 0
  • 1574

article-image-article-personalize-your-pbx-using-freepbx-features
Packt
26 Oct 2009
4 min read
Save for later

Personalize Your Own PBX Using FreePBX Features

Packt
26 Oct 2009
4 min read
Let's get started. CallerID Lookup Sources Caller ID lookup sources supplement the caller ID name information that is sent by most telephone companies. A caller ID lookup source contains a list of phone numbers matched with names. When FreePBX receives a call, it can query a lookup source with the number of the caller. If the caller is on the lookup source's list, a name is returned that will be sent along with the call wherever the call gets routed to. The name will be visible on a phone's caller ID display (if the phone supports caller ID), and is also visible in the FreePBX call detail records. In order to set up a caller ID lookup source, click on the CallerID Lookup Sources link under the Inbound Call Control section of the navigation menu on the left side of the FreePBX interface as shown in the following screenshot: The Add Source screen has three common configuration options: Source Description Source type Cache results Source Description is used to identify this lookup source when it is being selected as a caller ID lookup source during the configuration of an inbound route. Source type is used to select the method that this source will use to obtain caller ID name information. FreePBX allows a lookup source to use one of the following methods: ENUM: FreePBX will use whichever ENUM servers are configured in /etc/asterisk/enum.conf to return caller ID name information. By default, this file contains the e164.arpa and e164.org zones for lookups. All ENUM servers in the enum.conf file will be queried. HTTP: FreePBX will query a web service for caller ID name information using the HTTP protocol. A lookup source that uses HTTP to query for information can use services such as Google Phonebook or online versions of the white/yellow pages to return caller ID names. When HTTP is selected as the source type, six additional options will appear for configuration. These options are discussed in the HTTP source type section. MySQL: FreePBX will connect to a MySQL database to query for caller ID name information. Usually, this will be a database belonging to a Customer Relationship Management (CRM) software package in which all customer information is stored. When MySQL is selected as the Source type, five additional options will appear for configuration. These options are discussed later in the MySQL source type section. SugarCRM: As of FreePBX version 2.5.1, this option is not yet implemented. In the future, this Source type option will allow FreePBX to connect to the database used by the SugarCRM software package to query for caller ID name information. If the Cache results checkbox is selected, then when a lookup source returns results they will be cached in the local AstDB database for quicker retrieval the next time the same number is looked up. Note that values cached in the AstDB will persist past a restart of Asterisk and a reboot of the PBX. Once a caller ID name has been cached, FreePBX will always return that name even if the name in the lookup source changes. Caching must be disabled for a new caller ID name to be returned from the lookup source. Once all configuration options have been filled out, click on the Submit Changes button followed by the orange-colored Apply Configuration Changes bar to make the new lookup source available to inbound routes. Now that we have an available lookup source, we can configure an inbound route to use this source to set caller ID information. Click on the Inbound Routes link under the Inbound Call Control section of the navigation menu on the left side of the FreePBX interface as shown in the following screenshot: Click the name of the inbound route that will use the new lookup source in the menu on the right side of the page (in this example, DID 5551234567) as shown in the following screenshot: Scroll down the page to the CID Lookup Source section. Select the name of the new lookup source from the Source drop-down menu: Click on the Submit button at the bottom of the page, followed by the orange-colored Apply Configuration Changes bar at the top of the page. Calls that are routing using this inbound route will now query our new lookup source for caller ID name information.
Read more
  • 0
  • 0
  • 4580
article-image-graphical-report-design-ireport-part-2
Packt
26 Oct 2009
4 min read
Save for later

Graphical Report Design with iReport: Part 2

Packt
26 Oct 2009
4 min read
By the end of this article, you should be able to: Add multiple columns to a report Group report data Add images and charts to a report Creating more elaborate reports In this section, we will modify the simple report we created in the previous article to illustrate how to add images, charts, and multiple columns to a report. We will also see how to group report data. We will perform all of these tasks graphically with iReport. Adding images to a report Adding static images to a report is very simple with iReport. Just drag the Image component from the Palette to the band where it will be rendered in the report. When we drop the image component into the appropriate band, a window pops up asking us to specify the location of the image file to display. After we select the image, we can drag it to its exact location where it will be rendered. As we can see, adding images to a report using iReport couldn't be any simpler. Adding multiple columns to a report The report we've been creating so far in this article (continued from the first part of this article, Graphical Report Design with iReport: Part 1, for database details, refer to Database for our reports section of Creating Dynamic Reports from Databases) contains over 11,000 records. It spans over 300 pages. As we can see, there is a lot of space between the text fields. Perhaps it would be a good idea to place the text fields closer together and add an additional column. This would cut the number of pages in the report by half. To change the number of columns in the report, we simply need to select the root report node in the Report Inspector window at the top left and then modify its Columns property in the Properties window at the bottom right. When we modify the Columns property, iReport automatically modifies the Column Width property to an appropriate value. We are free, of course, to modify this value if it doesn't meet our needs. As our report now contains more than one column, it makes sense to re-add the Column Header band we deleted earlier. This can be done by right-clicking on the band in the Report Inspector window and selecting Add Band. Next, we need to move the static text in the page header to the Column Header band. To move any element from one band to another, all we need to do is drag it to the appropriate band in the Report Inspector window. Next, we need to resize and reposition the text fields in the Detail band and the static text elements in the Column Header band so that they fit in the new, narrower width of the columns. Also, resize the Column Header band to avoid having too much whitespace between the elements of the Column Header and Detail bands. Our report now looks like this: We can see the resulting report by clicking on Preview. Grouping report data Suppose we are asked to modify our report so that data is divided by the state where the aircraft is registered. This is a perfect situation to apply report groups. Report groups allow us to divide report data when a report expression changes. To define a report group, we need to right-click on the root report node in the Report Inspector window, and then select Add Report Group. Then, enter the Group name and indicate whether we want to group by a field or by a report expression. In our case, we want to group the data by state field. After clicking on Next>, we need to indicate whether we want to add a group header and/or footer to our report. For aesthetic purposes, we move the static text fields in the Column Header band to the Group Header band, remove the column and page header bands, and add additional information to the Group Header band. After making all of these changes, our report preview will look like this: We can preview the report by clicking Preview.
Read more
  • 0
  • 0
  • 2215

article-image-pentaho-reporting-building-interactive-reports-html
Packt
26 Oct 2009
1 min read
Save for later

Pentaho Reporting: Building Interactive Reports in HTML

Packt
26 Oct 2009
1 min read
Interactive HTML report properties All reporting elements share a common set of HTML-related properties that may be used to create a dynamic report. Below is a list of properties and their uses: HTML Properties class This property sets the class attribute of the current HTML entity to the specified value. name This property sets the name attribute of the current HTML entity to the specified value. title This property sets the title attribute of the current HTML entity to the specified value. xml-id This property allows the naming of the current HTML entity, setting the id attribute, making it possible to reference in outside scripts. append-body This property allows the placement of raw HTML within the body of the HTML document, prior to the rendering of the current element. append-body-footer This property allows the placement of raw HTML within the body of the HTML document, after the rendering of the current element. append-header Defined only at the master report level, this property allows the inclusion of raw HTML within the header of the HTML document generated. This location is traditionally used to load additional CSS files, as well as external JavaScript files.
Read more
  • 0
  • 0
  • 3033
Modal Close icon
Modal Close icon