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
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - CMS & E-Commerce

830 Articles
article-image-guide-understanding-core-data-ios
Packt
21 Apr 2011
13 min read
Save for later

A Guide to Understanding Core Data iOS

Packt
21 Apr 2011
13 min read
Core Data iOS Essentials A fast-paced, example-driven guide guide to data-drive iPhone, iPad, and iPod Touch applications        Core Data Core Data is Apple's persistence framework, which is used to persist—store our application's data in a persistent store, which may be memory or a flat file database. It helps us represent our data model in terms of an object graph, establish relationships among objects, and it can also store object graphs on the disk. It also allows us to use the entities of our data model in the form of objects, that is, it maps our data into a form that can be easily stored in a database, such as SQLite, or into a flat file. Also, the Core Data reduces a lot of coding. On using Xcode's templates for Core Data applications, we automatically get the boilerplate code that does several complex tasks such as generating XML files, binary files, SQLite files automatically for us without writing a single code, allowing us to focus on the business logic of our application. Besides this, Core Data also provides several features that are required in data manipulation, which includes filtering data, querying data, sorting data, establishing relationships with other data, and persisting data in different repositories. Core Data features The Core Data framework provides lots of features that include the following: Supports migrating and versioning: It means we can modify our data model, that is, entities of the application, whenever desired. The Core Data will replace the older persistent store with the revised data model. Supports Key-Value Coding (KVC): It is used to store and retrieve data from the managed objects. Core Data provides the methods required for setting and retrieving attribute values from the managed object, respectively. We will be using this feature in our application to display the information of customers and the products sold to them through the table view. Tracks the modifications: Core Data keeps track of the modifications performed on managed objects thus allowing us to undo any changes if required. We will be using this feature in our application while modifying the information of a customer or product to know what the earlier value was and what the new value entered for it is. Supports lazy loading: It's a situation that arises when all the property values of a managed object are not loaded from the data store and the property values are accessed by the application. In such situations, faulting occurs and the data is retrieved from the store automatically. Efficient database retrievals: Core Data queries are optimized for this, though the execution of query is dependent on the data store. Multi-threading: Core Data supports multi-threading in an application, that is, more than one thread can be executed in parallel to increase performance. Even some tasks can be performed in the background using a separate thread. Inverse relationship: Core Data maintains an inverse relationship for consistency. If we add an object to a relationship, Core Data will automatically take care of adding the correct object to the inverse relationship. Also, if we remove an object from a relationship, Core Data will automatically remove it from the inverse relationship. In our application, we will be using an inverse relationship between the Customer and Product entities, so that if a customer is deleted, the information of all the products purchased by him/her should also be automatically deleted. External data repositories: Core Data supports storing objects in external data repositories in different formats. Data Model Core Data describes the data in terms of a data model. A data model is used to define the structure of the data in terms of entities, properties, and their relationships. Entities Because Core Data maintains data in terms of objects, an entity is an individual data object to represent complete information of the person, item, object, and so on. For example, customer is an entity, which represents information of customers, such as name, address, e-mail ID, contact number, products purchased, date of purchase, and so on. Similarly, the product is an entity, which represents the information of a product, such as name of the product, price, weight, and so on. An entity consists of properties that are a combination of attributes and relationships. An entity in Xcode's Data Model Editor may appear as shown in the following screenshot: Properties Properties of an entity give detailed information about it, such as what are its attributes and how it is related to other entities. A property of an entity refers to its attributes and relationships. Attributes are scalar values and relationships are pointers to or collections of other entities at the object level. A property is represented by a name and a type. Attributes Attributes are the variables within an object (entity). In fact, a collection of attributes makes an entity. In database language, they are known as columns of the table. For example, the customer's entity may consist of attributes such as name, address, contact number, items purchased, and so on. Similarly, the attributes in the products table may be item code, item name, quantity, and so on. While creating attributes of an entity, we have to specify its name and its data type to declare the kind of information (whether integer, float, string, and so on) that will be stored in the attribute. Also, we can define the constraints on the information that can be stored in the column. For example, we can specify the maximum, minimum value (range) that can be stored in that attribute, or whether the attribute can or cannot store certain special symbols, and so on. Also, we can specify the default value of an attribute. Relationships Besides attributes, an entity may also contain relationships (which define how an entity is related to other entities). The attributes and relationships of an entity are collectively known as properties. The relationships are of many types (To-One, To-Many, and Many-to-Many) and play a major role in defining connection among the entities and what will be the impact of insertion or deletion of a row in one entity on the connected entities. Examples of relationship types: The relationship from a child entity to a parent entity is a To-One relationship as a child can have only one parent The relationship from a customer to a product entity is a To-Many relationship as a customer can purchase several products The relationship from an employee to a project entity is of Many-to-Many type as several employees can work on one project and an employee can work on several projects simultaneously To define a many-to-many relationship in Core Data, we have to use two To-many relationships. The first To-many relationship is set from the first entity to the second entity. The second To-many relationship is set from the second entity to the first entity. In Xcode's Data Model Editor, the relationship from Customer to Product—a To-Many relationship—is represented by a line that appears pointing from the Customer entity to the Product entity with two arrows, (designating a One-to-Many relationship) as shown in the subsequent screenshot, whereas the To-One relationship is represented by a line with a single arrow: When defining relationships in Core Data we may use inverse relationships, though it's optional. Inverse relationship In Core Data, every relationship can have an inverse relationship. Like, if there is a relationship from Customer to Product, there will be a relationship from Product to Customer too. A relationship does not need to be the same kind as its inverse; for example, a To-One relationship can have an inverse relationship of type To-Many. Although relationships are not required to have an inverse, Apple generally recommends that you always create and specify the inverse, (even if you won't need) as it helps Core Data to ensure data integrity. For example, consider a situation when a Customer entity has a relationship of the To-Many type to a Product entity and some information of a customer is changed or a row of a customer is deleted. Then it will be easier for Core Data to ensure consistency; that is, by inverse relationship, Core Data can automatically find the products related to the deleted customer and hence, delete them too. Before we go further, let us have a quick look at the architecture that is used in iPhone application development: MVC. Model View Controller (MVC) iPhone application development uses MVC architecture where M stands for Model, V stands for View, and C for Controller. Model represents the backend data—data model View represents the user interface elements through which the user looks at the contents displayed by the application and can interact with them Controller represents the application logic that decides the type of view to be displayed on the basis of actions taken by the user Core Data organizes the data model in terms of objects that are easy to handle and manipulate. The finalized objects are stored on a persistent storage. The usual way of representing data models is through classes that contains variables and accessor methods. We don't have to create classes by hand, (for our data models) as Core Data framework provides a special Data Model Design tool (also known as Data Model Editor) for quickly creating an entity relationship model. The terms that we will be frequently using from now onwards are Managed Object Model, Managed Objects, and Managed Object Context. Let us see what these terms mean: Managed Object Model: The data model created by the Data Model Design tool (Data Model Editor) is also known as Managed Object Model. Managed Objects: Managed objects are instances of the NSManagedObject class (or its subclass) that represent instances of an entity that are maintained (managed) by the Core Data framework. In a managed object model, an entity is defined by an entity name and the name of the class that is used at runtime to represent it. The NSManagedObject class implements all of the functionality required by a managed object. A managed object is associated with an entity description (an instance of NSEntityDescription) that describes the object; for example, the name of the entity, its attributes, relationships, and so on. In other words, an NSEntityDescription object may consist of NSAttributeDescription and NSRelationshipDescription objects that represent the properties of the entity. At runtime, the managed object is associated with a managed object context. Managed Object Context: The objects when fetched from the persistent storage are placed in managed object context. It performs validations and keeps track of the changes made to the object's attributes so that undo and redo operations can be applied to it, if required. In a given context, a managed object provides a representation of a record in a persistent store. Depending on a situation, there may be multiple contexts—each containing a separate managed object representing that record. All managed objects are registered with managed object context. For an application, we need the information represented by the Managed Object (instance of an entity) to be stored on the disk (persistent store) via managed object context. To understand the concepts of managed object context and its relation with data persistence, we need to understand the components of Core Data API, so let us go ahead and look at what Core Data API is all about. Core Data API The Core Data API, also called the stack, consists of three main components: NSPersistentStoreCoordinator NSManagedObjectModel NSManagedObjectContext The PersistentStoreCoordinator plays a major role in storing and retrieving managed objects from the Persistent Store via ManagedObjectContext. We can see in the following figure how the three are related: The Managed Object Model (an instance of NSManagedObjectModel class) is created from the data model of our application. If there is more than one data model in our application, the Managed Object Model is created by merging all of the data models found in the application bundle. The managed object (instance of the NSManagedObject class or its subclass) represents an instance of an entity that is maintained (managed) by the Core Data framework. A managed object is an instance of an Objective-C class, but it differs from other objects in three main ways: A managed object must be an instance of NSManagedObject or of a class that inherits from NSManagedObject The state of managed object is maintained by its managed object context A managed object has an associated entity description that describes the properties of the object For working with a managed object, it is loaded into memory. The managed object context maintains the state of the managed object after it is loaded in memory. The Managed Object Context tracks in-memory changes that have yet to be persisted to the data store. Any changes made to the state of an NSManagedObject do actually affect the state of the object in memory, not just the persistent representation of that object in the data store. When we want to commit the modifications made to the managed object, we save the managed object context to the persistent store. In order to deal with persistent store, the managed object context needs a reference to a PersistentStoreCoordinator. In other words, a pointer to the PersistentStoreCoordinator is required for creating a Managed Object Context. Remember, the PersistentStoreCoordinator is the essential middle layer in the stack that helps in storing and retrieving the managed object model from the persistent store. The managed object context is an object that plays a major role in the life cycle of managed objects. It handles all the aspects of managed object from faulting to validation including undo/redo. To modify managed objects, they are fetched from a persistent store through managed context. The modified managed objects are committed to the persistent store through context only. The managed objects represent data held in a persistent store. Faulting is considered to occur for an object whose property values have not yet been loaded from the external data store. To access the objects (entity) in managed object context, FetchRequest, an instance of NSFetchRequest class, is used. To define the entity to be retrieved via NSFetchRequest, we pass the appropriate NSEntityDescription to the NSFetchRequest. The result, that is, the set of entities retrieved from the managed object context (on the basis of FetchRequest) are managed by FetchedResultsController—an instance of NSFetchedResultsController. In fact, FetchRequest is passed to the FetchedResultsController along with a reference to the managed object context. Once the NSFetchedResultsController class has been initialized, we can perform a fetch operation to load the entities (stored in it) into memory. The managed object context keeps track of all the changes made to the managed object since the last time it was loaded in memory and hence helps in undoing any changes made to the managed object (if required).The Persistent Store Coordinator helps in avoiding redundancy if multiple calls are made by different classes on the same file at the same time, that is, the multiple calls are serialized by the NSPersistentStoreCoordinator class to avoid redundancy. Let us now get a detailed understanding of the terms used above.
Read more
  • 0
  • 0
  • 3743

article-image-opencart-themes-using-jcarousel-plugin
Packt
20 Apr 2011
6 min read
Save for later

OpenCart Themes: Using the jCarousel Plugin

Packt
20 Apr 2011
6 min read
  OpenCart 1.4 Template Design Cookbook Over 50 incredibly effective and quick recipes for building modern eye-catching OpenCart templates         Installing jQuery and jCarousel In this recipe, we will download jQuery and jCarousel and also install them into our store. By default, OpenCart comes with jQuery installed. Carousels have become a popular means to display products. There are many different types of carousels. But, we will use jCarousel for this recipe. You can use your favourite one. Getting started We need jQuery for our dynamic content throughout the site. jQuery is added by default with OpenCart. But here, we will also see how to download it and install it. We will download and install jQuery and jCarousel. First, we will go to the sites from where we can download them. If jQuery is not present in your site, you can download it from http://docs.jquery.com/Downloading_jquery. We will download the latest jQuery JavaScript file. How to do it First, we need to download the required files to use jCarousel. We need the jQuery JavaScript file and jCarousel JavaScript and css files. To check whether our site is jQuery-enabled or not, we can use web developer Firefox addons. Click on the information tab of Web Developer: It will display many sub-menus. Every sub-menu has its own importance. We select View JavaScript. Then, a new tab will open containing all the JavaScripts for the web page in it. You can contract or expand the links. If our store already has jQuery, then we can find it in this page. Otherwise, it won't be in this page or it will show a 404 error. Since our store is jQuery-enabled by default, we don't need to install jQuery. We have shown the installation of jQuery so that you can have full control of the process. There are several releases available to download. After downloading jQuery, we will place it under the catalogviewJavascriptjQuery folder. Now, we will download jCarousel. We can download it from http://sorgalla.com/projects/jCarousel/. Then, extract the compressed file. There will be many files in the extracted folder. Under the lib folder, we have an uncompressed and minified version of jCarousel. We create a folder named jCarousel under catalogviewiavascriptjquery. Then, in the jCarousel folder, create another folder named js. We will place any one of the two files under catalogviewjavascriptjqueryjcarouseljs. And bring the skins folder under the catalogviewjavascriptjqueryjcarousel. Displaying products using jCarousel We have installed jQuery and jCarousel in the previous recipe. Here, we will see how we can display products with jCarousel. In this recipe, we are going use jCarousel for the latest products, but you can use it for other modules as well. Getting started First, we will open the header.tpl file under catalogviewthemeshoptemplatecommon. If we don't have jQuery in our site, then we need to add it here. See the following code block: <script type="text/javascript" src="catalog/view/javascript/jquery/jquery-1.3.2.min.js"></script> How to do it We will follow the steps below for jCarousel addition to our store: First, we need to add the links for jCarousel JavaScript and css files to work with jCarousel. As we are using jCarousel for displaying the latest products, we place the links for those files in the latest_home.tpl under catalogviewthemeshoptemplatemodule. We add the following links: <script type="text/javascript" src="catalog/view/javascript/jquery/jcarousel/lib/jquery.jcarousel.js"></script> <link rel="stylesheet" type="text/css" href="catalog/view/javascript/jquery/jcarousel/skins/tango/skin.css" /> Now, we modify some HTML element structure to place the products in jCarousel. The current structure is table based. We will use <ul> <li> instead of the table structure. We remove the following tag: <table class="list"> //... </table> And write the following code, here by the three dots, we mean other inner codes: <ul id="latestcarousel" class="jCarousel-skin-tango"> //... </ul> Here latestcarousel ID is our carousel container ID. There are two skins available for jCarousel, one is tango and the other is ie7. Here, we are using tango. We also remove the tr tag: <tr> //... </tr> Now, remove the td tag and the following: <td style="width: 25%;"><?php if (isset($products[$j])) { ?> //... <?php } ?></td> And, we replace it with the following code: <li> //... </li> Now, we will initialize jCarousel. <script type="text/javascript"> jQuery(document).ready(function() { jQuery('#latestcarousel').jcarouseljcarousel(); }); </script> If we see our changes in the browser, then we will find it as: Here, we need to adjust the height and width of the carousel. To change the width of the carousel, open the skin.css file under catalogiewJavascriptjQueryjCarouselskins. We are going to change the following code: .jcarousel-skin-tango .jcarousel-container-horizontal { width: 245px; padding: 20px 40px; } To the following code: .jcarousel-skin-tango .jcarousel-container-horizontal { width: auto; padding: 20px 40px; } Again, if we are going to use jCarousel in some other places as well, it is not smart to change the skin.css. Instead we can override it in our theme-css for a specific region. For example, #content .middle .jcarousel-skin-tango .jcarousel-container-horizontal. Here, we have just shown you one instance of jCarousel usage. We changed the width to auto. So, in the browser, the carousel will be like this: There is style for both vertical and horizontal carousel in the stylesheet. As we are now using the horizontal carousel, we adjust the styles for horizontal only. The area showing the images of the products is smaller compared to the carousel width. So, we will adjust the width. We set the width to auto. .jcarousel-skin-tango .jcarousel-clip-horizontal { width: auto; height: 75px; } Now, the carousel is displaying products along the full width of the carousel. See the following image: Our height for the carousel is small. Let's change the height of it. We change the height to 200px: .jcarousel-skin-tango .jcarousel-clip-horizontal { width: auto; height: 200px; } This makes our carousel look like the following: To enlarge the height of the product image display area, we need to change the following code: .jcarousel-skin-tango .jcarousel-item { width: 75px; height: 200px; } We change the height to 200px. In the browser, now our carousel looks like this: We need to adjust the margin property for our product images. We change the margin-right property to 50px. .jcarousel-skin-tango .jcarousel-item-horizontal { margin-left: 0; margin-right: 50px; } This makes spacing between the product images. You need to refresh the browser to view the changes: We will set options for the carousel. There are several options. You can see the available options in this link: http://sorgalla.com/projects/jcarousel/. We used the following options and placed it in the latest_home.tpl, the page in which we are showing jCarousel: <script type="text/javascript"> jQuery(document).ready(function() { jQuery('#latestcarousel').jcarousel({ scroll: 1, visible: 3, auto: 3, rtl: true, wrap: 'circular' }); }); </script>  
Read more
  • 0
  • 0
  • 2055

article-image-opencart-themes-styling-effects-jquery-plugins
Packt
20 Apr 2011
5 min read
Save for later

OpenCart Themes: Styling Effects of jQuery Plugins

Packt
20 Apr 2011
5 min read
  OpenCart 1.4 Template Design Cookbook Over 50 incredibly effective and quick recipes for building modern eye-catching OpenCart templates         Read more about this book       (For more resources on Opencart, see here.) Customizing the cycle plugin In this recipe, we use the jQuery cycle plugin with our products. We first download the jQuery cycle plugin. Getting started We need jQuery enabled for jQuery cycle to work with our store shop. How to do it Go through the following steps to customize the jQuery cycle plugin: First, download the jQuery cycle JavaScript files from http://jquery.malsup.com/cycle/download.html. We extract the downloaded compressed file. We will use the jquery.cycle.min.js. We copy this file to catalogviewjavascriptjquery. We need to add jQuery and the jQuery cycle JavaScript file into our file. For this recipe, we will add this plugin for the latest products in the home section. So, we add the following code in latest_home.tpl as we are not using the jQuery cycle plugin throughout the site: <script type="text/Javascript" src="catalog/view/javascript/jquery/ jquery.cycle.min.js"></script> Then, we will modify the existing table-based structure to div-based. We remove the following code: <table class="list">//...</table> And in place of that we write the following: <div class="slideshow">//...</div> We also again remove the tr tag: <tr>//...</tr> And replace the td HTML tag with the following div tag: <td style="width: 25%;">//...</td> The required div tag is: <div class="slideshow-image-container">//...</div> We will initialize the jQuery cycle plugin with the following code: <script type="text/Javascript">$(document).ready(function() { $('.slideshow').cycle({ fx: 'fade' });});</script> Now, go to the browser and refresh to see the effect of our change: We center the product image. So, we add the following margin-left property to our image in the stylesheets.css file: .slideshow .slideshow-image-container {margin-left: 200px;} Then, the image container moves to the center of the latest product area. See the following image: We need to do some styling to our product images. We will have a thick border around our image. So, we add these styling attributes: .slideshow .slideshow-image-container { margin-left: 200px; border: 10px solid #ddd;} This creates a border around the product image like the following: The product image and the descriptions are all left aligned. So, we make it centered by adding the following style tag: .slideshow .slideshow-image-container { margin-left: 200px; text-align: center; padding: 10px; border:10px solid #ddd;} Now, our jQuery cycle looks like this: There's more... You can also see the Accordion jQuery plugin. It is also a very popular jQuery plugin. You can add and initialize it in almost the same way. You can read the documentation of the plugin at http://plugins.jquery.com/project/accordion. Modifying the side column with the cycle plugin We modified the latest product block in the center column with the jQuery cycle plugin. Now, if we want to show our products on the side columns with the jQuery cycle, then this recipe will guide us to our destination. Getting started We need jQuery enabled for jQuery cycle to work with our store shop. How to do it Go through the following steps to customize the jQuery cycle plugin: To use the plugin, first, we need to add the required file links to the latest.tpl file as we are using the jQuery cycle for latest products. We add the following line in our latest.tpl file: <script type="text/Javascript" src="catalog/view/javascript/jquery/jquery.cycle.all.min.js"></script> Then, like our previous recipes, we will remove the table-based style and instead, use div-based styles: <table cellpadding="2" cellspacing="0" style="width: 100%;">//...<tr>//...</tr>//..</table> And, we write the following tag in place of the table element: <div class="slideshow">//...</div> We also li tag with a div element. See the following code: //remove this tags<li>//...</li>//replace with the following element<div class="slideshow-image-container">//...</div> Now, we initialize the cycle plugin with the code below: <script type="text/Javascript">$(document).ready(function() { $('.slideshow').cycle({ fx: 'fade' });});</script> If we go to the browser, then we can see the following changes: We will add some styling to the above display. The products are displaying on the left side of the side column. To make it centered, we add margin to the style: .slideshow .slideshow-image-container { margin-left: 60px; } Our right column changes like this: We add a border to our image. We do the following styling addition: .slideshow .slideshow-image-container { margin-left: 60px; border: 5px solid #ddd;} When we go to the browser, we find the following state of our right side bar: We need to add some padding and make our text aligned to the center. So, we also add the following styles: .slideshow .slideshow-image-container { margin-left: 60px; border: 5px solid #ddd; padding:5px; text-align: center;} We refresh our browser and see our changes in action: There is more You can also add this plugin on the left side of our OpenCart store. Just change the position of the module from the module section of the admin panel.  
Read more
  • 0
  • 0
  • 1654
Visually different images

article-image-creating-media-galleries-aspnet-4-social-networking
Packt
19 Apr 2011
11 min read
Save for later

Creating media galleries with ASP.NET 4 social networking

Packt
19 Apr 2011
11 min read
In order to create the file management software for our website, we need to consider topics such as a single or multi-file upload, file system management, and image manipulation in the case of photos. In addition to this we will cover creation of pages for displaying the user's photo albums, their friends' photo albums, as well as a few data management pages. What's the problem? Apart from the standard infrastructure issues that we have to consider when building a system such as this, one of the core issues in any web-based file management system is file upload. As we all know, most server side technologies allow only one file to be uploaded at a time and ASP.NET is no different. And while we could easily buy a third-party plug-in to handle multiple files at once, we decided to provide for options to upload the files either via Silverlight or via Flash. Once we get our file upload process working we are only one-third of the way there! As we are going to be mostly concerned with uploading images, we need to consider that we will need to provide some image manipulation. With each file that is uploaded to our system we need to create a handful of different sizes of each image to be used in various scenarios across our site. To start with, we will create thumbnail, small, medium, large, and original size photos. Now while creating different size files is technically working with the file storage system, we wanted to take an extra breath with regards to the file storage concepts. We can choose to store the files on the file system or in a database. For avatars it made sense to store each with the profile data whereas for image galleries it makes more sense to store the file on the file system. While storing files to the file system we need to be very cautious as to how the file structure is defined and where and how the individual files are stored. In our case we will use system-generated GUIDs as our file names with extensions to define the different sizes that we are storing. We will dig into this more as we start to understand the details of this system. Once we have uploaded the files to the server and they are ready for our use across the system, we will take up the concept of user files versus system files. If we build the system with some forethought regarding this topic we can have a very generic file management system that can be extended for future use. We will build a personal system in this article. But as you will see with some flags in just the right places, we could just as easily build a system file manager or a group file manager. Design Let's take a look at the design for this feature. Files For our site, as we are not storing our files in the database, we need to take a closer look at what actually needs to be managed in the database so as to keep track of what is going on in the file system. In addition to standard file metadata, we need to keep a close eye on where the file actually lives—specifically which file system folder (directory on the hard drive) the file will reside in. We also need to be able to maintain which accounts own which files, or in the case of system files, which files can be viewed by anyone. Folders You may be wondering why we have a separate section regarding folders when we just touched upon the fact that we will be managing which file system folder we will be storing files in. In this section we are going to discuss folder management from a site perspective rather than a file system perspective—user folders or virtual folders if you desire. Very similar to file storage, we will be storing various metadata about each folder. We will also have to keep track of who owns which folder, who can see which folder, or in the case of system folders whether everyone can see that folder. And of course as each folder is a virtual container for a file, we will have to maintain the relationship between folders and files. File upload The file upload process will be handled by a Silverlight/Flash client. While this is not really an article about either Silverlight or Flash, we will show you how simple it is to create this Flash client, that is really just providing a way to store many files that need to be uploaded, and then uploading them one at a time in a way that the server can handle each file. For the Silverlight option, we are using code from Codeplex—http://silverlightfileupld.codeplex.com/. File system management Managing the file system may seem like a non-issue to begin with. However, keep in mind that for a community site to be successful we will need at least 10,000 or so unique users. Given that sharing photos and other files is such a popular feature of most of today's community sites, this could easily translate into a lot of uploaded files. While you could technically store a large number of files in one directory on your web server, you will find that over time your application becomes more and more sluggish. You might also run into files being uploaded with the same name using this approach. Also, you may find that you will have storage issues and need to split off some of your files to another disk or another server. Many of these issues are easily handled if we think about and address them up front. In our case we will use a unique file name for each uploaded file. We will store each file in subdirectories that are also uniquely named based on the year and month in which the file was uploaded. If you find that you have a high volume of files being uploaded each day, you may want to store your files in a folder with the year and month in the name of the folder and then in another subdirectory for each day of that month. In addition to a good naming convention on the file system, we will store the root directory for each file in the database. Initially you may only have one root for your photos, one for videos, and so on. But storing it now will allow you to have multiple roots for your file storage—one root location per file. This gives you a lot of extensibility points over time meaning that you could easily relocate entire sections of your file gallery to a separate disk or even a separate server. Data management screens Once we have all of the infrastructure in place we will need to discuss all the data management screens that will be needed—everything from the UI for uploading files to the screens for managing file metadata, to screens for creating new albums. Then we will need to tie into the rest of the framework and allow users to view their friends' uploaded file albums. The solution Let's take a look at our solution. Implementing the database First let's take a look at the tables required for these features (see the following screenshot). Files The most important thing to consider storing while in the database is of course our primary interest files. As with most other conversations regarding a physical binary file we always have to consider if we want to store the file in the database or on the file system. In this case we think it makes sense to store the file (and in the case of a photo, its various generated sizes) on the file system. This means that we will only be storing metadata about each file in our database. The most important field here to discuss is the FileSystemName. As you can see this is a GUID value. We will be renaming uploaded files to GUIDs in addition to the original extension. This allows us to ensure that all the files in any given folder are uniquely named. This removes the need for us to have to worry about overwriting other files. Then we see the FileSystemFolderID. This is a reference to the FileSystemFolders table, that lets us know the root folder location where the file is stored. Next on our list of items to discuss is the IsPublicResource flag. By its name it is quite clear that this flag will set a file as public or private and can therefore be seen by all or by its owner (AccountID). We then come to a field that may be somewhat confusing: DefaultFolderID. This has nothing to do with the file system folders. This is a user created folder. When files are uploaded initially they are put in a virtual folder. That initial virtual folder becomes the file's permanent home. This doesn't mean that it is the file's only home. As you will see later we have the concept that files can live in many virtual folders by way of subscription to the other folders. File system folders As mentioned previously, the FileSystemFolders table is responsible for letting us know where our file's root directory is. This allows us to expand our system down the road to have multiple roots, that could live on the same server but different disks, or on totally different servers. The fields in the table are Key, Path (URL), and a Timestamp. File types The FileTypes table will help us to keep track of what sort of files we are storing and working with. This is a simple lookup table that tells us the extension of a given file. Folders Folders are virtual in this case. They provide us with a way to specify a container of files. In our case we will be containing photos, in which case folders will act as photo albums. The only field worth explaining here is the flag IsPublicResource, which allows us to specify whether a folder and its resources are public or private, that is, viewable by all or viewable only by the owner. Folder types The FolderTypes table allows us a way to specify the type of folder. Currently this will simply be Name, photos, movies, and so on. However, down the road you may want to specify an icon for each folder type in which case this is the place where you would want to assign that specification. Account folders In the AccountFolders table we are able to specify additional ownership of a folder. So in the case that a folder is a public resource and external resources can own folders, we simply create the new ownership relationship here. This is not permanent ownership. It is still specified with the Folders table's AccountID. This is a temporary ownership across many Accounts. As you can see in the previous screenshot we have the owner (AccountID) and the folder that is to be owned (FolderID). Account files Similar to the AccountFolders table, the AccountFiles table allows someone to subscribe to a specific file. This could be used for the purposes of Favorites or similar concepts. The makeup of this table is identical to AccountFolders. You have the owner and the file being owned. Folder files The FolderFiles table allows an Account to not only subscribe to a file, similar to the Favorites concept, but it also allows a user to take one of my files and put it into one of their folders as though the file itself belonged to them. As you can see in the previous screenshot this is primarily a table that holds the keys to the other tables. We have the FolderID, FileID, and AccountID for each file. This clearly specifies who is taking ownership of what and where they want it to be placed. Creating the relationships Once all the tables are created we can then create all the relationships. For this set of tables we have relationships between the following tables: Files and FileSystemFolders Files and FileTypes Files and Folders Files and Accounts Folders and Accounts Folders and FolderTypes AccountFolders and Accounts AccountFolders and Folders AccountFiles and Accounts AccountFiles and Files FolderFiles and Accounts FolderFiles and Folders FolderFiles and Files
Read more
  • 0
  • 0
  • 1902

article-image-making-ajax-calls-using-jquery
Packt
19 Apr 2011
7 min read
Save for later

Making AJAX Calls using jQuery

Packt
19 Apr 2011
7 min read
AJAX (Asynchronous JavaScript and XML), a term coined by Jesse James Garrett of Adaptive Path, stands for a combination of different technologies that help to communicate seamlessly with the server without the need for a page refresh. AJAX applications involve the following technologies: JavaScript for running the core AJAX engine XmlHttpRequest object to communicate with the server Web presentation using XHTML and CSS or XSLT DOM to work with the HTML structure XML and JSON for data interchange The XmlHttpRequest object is used for posting HTTP/HTTPS requests to the server. Most modern browsers have a built-in XmlHttpRequest object. JSON (JavaScript Object Notation) is a lightweight data interchange format and is increasingly used in AJAX applications today. It is basically a collection of name/value pairs. In classic web applications, the client submits data to the server for processing and the server sends back refreshed content to the client. This causes a visible page refresh and the web user must wait for a page reload before further interaction with the web application. AJAX, however, eliminates the need for an explicit page refresh by communicating with the server behind the scenes. It uses the power of XmlHttpRequest object to post a request to the server. Thus, the backend communication with the server is transparent to the end user. In addition, using AJAX, only the data that is required to be updated can be selectively refreshed on the page. The previous figure is the traditional model for web applications (left) compared to the AJAX model (right). The previous figure shows the basic difference between traditional and AJAX-enabled applications. In traditional web applications, the client sends requests directly to the server and waits to receive the corresponding response. In AJAX-based applications, however, this is replaced by a JavaScript call to the AJAX engine instead, which sends the request asynchronously to the server. As a result, web users' interaction with the application is not interrupted and users can continue to work with the application. The jQuery library provides many methods for working with AJAX. In this article, we will explore the use of the following methods: $.ajax(settings): This is a generic low level function that helps to create any type of AJAX request. There are a number of configuration settings that can be applied using this function to customize an AJAX call. It helps to set the type of HTTP request (GET/ POST), the URL, parameters, datatype, as well as the callback functions to execute successful/unsuccessful invocation of the AJAX call. $.ajaxSetup(options): This method helps to define default settings for making AJAX calls on the page. The setup is done one time and all the subsequent AJAX calls on the page are made using the default settings. Getting started Let's start by creating a new ASP.NET website in Visual Studio and name it Chapter6. Save the jQuery library in a script folder js in the project. To enable jQuery on any web form, drag-and-drop the library to add the following to the page: <script src="js/jquery-1.4.1.js" type="text/javascript"></script> Now let's move on to the recipes where we will see how jQuery can be used to make AJAX calls to ASP.NET code-behind. Basically, in this article, we will explore three possible approaches of communicating with the server: Using page methods Using web services Using HTTP Handlers So, let's get started. Setting up AJAX with ASP.NET using jQuery In this recipe, we will set up our ASP.NET web page to execute an AJAX call. We will also see how to set the default AJAX properties. Getting ready Create an HTML file Content.html in the project and add the following contents: <html > <head> <title>Content Page</title> <link href="css/content.css" rel="stylesheet" type="text/css" /> </head> <body> <p> <table cellpadding="3" cellspacing="3" id="box-table-a"> <tr><td>Title</td><td>Author</td><td>Genre</td></tr> <tr><td>Alchemist</td><td>Paulo Coelho</td><td>Fiction</td></tr> <tr><td>Heart of Darkness</td><td>Joseph Conrad</td><td>Classic</ td></tr> <tr><td>David Copperfield</td><td>Charles Dickens</ td><td>Classic</td></tr> <tr><td>Have a Little Faith</td><td>Mitch Albom</td><td>Fiction</ td></tr> </table> </p> </body> </html> Add a new web form Recipe1.aspx to the current project. Add a button control to the web form to trigger the AJAX request. <asp:Button ID="btnSubmit" runat="server" Text="Click Here" /> Thus, the ASPX markup of the web form is as follows: <form id="form1" runat="server"> <div align="center"> <fieldset style="width:400px;height:200px;"> <div id="contentArea"> <asp:Button ID="btnSubmit" runat="server" Text="Click Here" /> </div> </fieldset> </div> </form> On page load, the form will appear as shown in the following screenshot: When the button is clicked, we will retrieve the contents of the HTML file using AJAX and display it on the page. How to do it… In the document.ready() function of the jQuery script block, call the ajaxSetup() method to set the default properties of all AJAX calls on the page: $.ajaxSetup({ Turn off the cache so that the contents are not cached by the browser: cache: false, Set the data type of the response. In this case, since we are going to load the contents from the HTML file, the dataType is HTML: dataType: "html", Define the callback function if the AJAX request fails. The callback function takes in three parameters: the XMLHttpRequest object, the error status, and an exception object: error: function(xhr, status, error) { alert('An error occurred: ' + error); }, Define the global timeout in milliseconds: timeout: 30000, Set the type of HTTP request (GET/POST): type: "GET", Define the callback function to be called before the AJAX request is initiated. This function can be used to modify the Xml HttpRequest object: beforeSend: function() { console.log('In Ajax beforeSend function'); }, Define the function to be called when the AJAX request is completed: complete: function() { console.log('In Ajax complete function'); } }); Now, having set the default properties in the previous code block, we will now invoke the actual AJAX call on clicking the button control on the form. Attach a handler for the click event of the button control: $("#btnSubmit").click(function(e) { Prevent default form submission: e.preventDefault(); Initiate the AJAX call using the .ajax() method: $.ajax({ Specify the URL to send the request to. In this case, we're sending the request to the HTML file: url: "Content.htm", Define the callback function for successful execution of the AJAX call: success: function(data) { The HTML response from the server is received in the data parameter in the preceding callback function. Clear the contents of the containing div area to remove the button control and append the received HTML response: $("#contentArea").html("").append(data); } }); }); Thus, the complete jQuery solution is as follows: <script language="javascript" type="text/javascript"> $(document).ready(function() { $.ajaxSetup({ cache: false, dataType: "html", error: function(xhr, status, error) { alert('An error occurred: ' + error); }, timeout: 30000, type: "GET", beforeSend: function() { console.log('In Ajax beforeSend function'); }, complete: function() { console.log('In Ajax complete function'); } }); $("#btnSubmit").click(function(e) { e.preventDefault(); $.ajax({ url: "Content.htm", success: function(data) { $("#contentArea").html("").append(data); } }); }); }); </script> How it works… Run the web form. Click on the button to initiate the AJAX request. You will see that the page content is updated without any visible page refresh as follows:
Read more
  • 0
  • 0
  • 3246

article-image-linux-shell-script-tips-and-tricks
Packt
15 Apr 2011
7 min read
Save for later

Linux Shell Script: Tips and Tricks

Packt
15 Apr 2011
7 min read
  Linux Shell Scripting Cookbook Solve real-world shell scripting problems with over 110 simple but incredibly effective recipes  In this article, we took a look at some tips and tricks on working with Linux shell script.    Successful and unsuccessful command Tip: When a command returns after error, it returns a non-zero exit status. The command returns zero when it terminates after successful completion. Return status can be read from special variable $? (run echo $? immediately after the command execution statement to print the exit status). Fork bomb :(){ :|:& };: Tip: This recursive function is a function that calls itself. It infinitely spawns processes and ends up in a denial of service attack. & is postfixed with the function call to bring the subprocess into the background. This is a dangerous code as it forks processes and, therefore, it is called a fork bomb. You may find it difficult to interpret the above code. See Wikipedia page http://en.wikipedia.org/wiki/Fork_bomb for more details and interpretation of the fork bomb. It can be prevented by restricting the maximum number of processes that can be spawned from the config file /etc/security/limits.conf. Specify -maxdepth and –mindepth as the third argument Tip: -maxdepth and –mindepth should be specified as the third argument to the find. If they are specified as the fourth or further arguments, it may affect the efficiency of the find as it has to do unnecessary checks (for example, if –maxdepth is specified as the fourth argument and –type as the third argument, the find command first finds out all the files having the specified –type and then finds all of the matched files having the specified depth. However, if the depth were specified as the third argument and –type as the fourth, find could collect all the files having at most the specified depth and then check for the file type, which is the most efficient way of searching. -exec with multiple commands Tip: We cannot use multiple commands along with the –exec parameter. It accepts only a single command, but we can use a trick. Write multiple commands in a shell script (for example, commands.sh) and use it with –exec as follows: -exec ./commands.sh {} ; -n option for numeric sort Tip: Always be careful about the -n option for numeric sort. The sort command treats alphabetical sort and numeric sort differently. Hence, in order to specify numeric sort the –n option should be provided. The ## operator Tip: The ## operator is more preferred over the # operator to extract an extension from a filename since the filename may contain multiple '.' characters. Since ## makes greedy match, it always extract extensions only. Recursively search many files Tip: To recursively search for a text over many directories of descendants use: $ grep "text" . -R -n This is one of the most frequently used commands by developers. It is used to find the file of source code in which a certain text exists. Placing variable assignments Tip: Usually, we place initial variable assignments, such as var=0; and statements to print the file header in the BEGIN block. In the END{} block, we place statements such as printing results and so on. -d argument Tip: The -d argument should always be given in quotes. If quotes are not used, & is interpreted by the shell to indicate this should be a background process. Excluding a set of files from archiving Tip: It is possible to exclude a set of files from archiving by specifying patterns. Use --exclude [PATTERN] for excluding files matched by wildcard patterns. For example, to exclude all .txt files from archiving use: $ tar -cf arch.tar * --exclude "*.txt" Note that the pattern should be enclosed in double quotes. Using cpio command for absolute paths Tip: By using cpio, we can also archive using files as absolute paths. /usr/somedir is an absolute path as it contains the full path starting from root (/). A relative path will not start with / but it starts the path from the current directory. For example, test/file means that there is a directory test and the file is inside the test directory. While extracting, cpio extracts to the absolute path itself. But incase of tar it removes the / in the absolute path and converts it as relative path. PATH format Tip: For the PATH format, if we use / at the end of the source, rsync will copy contents of that end directory specified in the source_path to the destination. If / not at the end of the source, rsync will copy that end directory itself to the destination. / at the end of destination_path Tip: If / is at the end of destination_path, rsync will copy the source to the destination directory. If / is not used at the end of the destination path, rsync will create a folder, named similar to the source directory, at the end of the destination path and copy the source into that directory. wait command Tip: The wait command enables a script to be terminated only after all its child process or background processes terminate or complete. First argument of the sftp command Tip: -oPort should be the first argument of the sftp command. Running du DIRECTORY Tip: Running du DIRECTORY will output a similar result, but it will show only the size consumed by subdirectories. However, they do not show the disk usage for each of the files. For printing the disk usage by files, -a is mandatory. du DIRECTORY commands traversal Tip: du can be restricted to traverse only a single file system by using the –x argument. Suppose du DIRECTORY is run, it will traverse through every possible subdirectory of DIRECTORY recursively. A subdirectory in the directory hierarchy may be a mount point (for example, /mnt/sda1 is a subdirectory of /mnt and it is a mount point for the device /dev/sda1). du will traverse that mount point and calculate the sum of disk usage for that device filesystem also. In order to prevent du from traversing and to calculate from other mount points or filesystems, use the -x flag along with other du options. du –x / will exclude all mount points in /mnt/ for disk usage calculation. Use an absolute path for the executable Tip: An executable binary of the time command is available at /usr/bin/time as well as a shell built-in named time exists. When we run time, it calls the shell built-in by default. The shell built-in time has limited options. Hence, we should use an absolute path for the executable (/usr/bin/time) for performing additional functionalities. -x argument Tip: The -x argument along with -a specifies to remove the TTY restriction imparted, by default, by ps. Usually, using ps without arguments prints processes that are attached to terminal only. Parameters for -o Tip: Parameters for -o are delimited by using the comma (,) operator. It should be noted that there is no space in between the comma operator and next parameter. Mostly, the -o option is combined with the -e (every) option (-oe) since it should list every process running in the system. However, when certain filters are used along with –o, such as those used for listing the processes owned by specified users, -e is not used along with –o. Usage of -e with a filter will nullify the filter and it will show all process entries. pgrep command Tip: pgrep requires only a portion of the command name as its input argument to extract a Bash command, for example, pgrep ash or pgrep bas will also work. But ps requires you to type the exact command. apropos Tip: Sometimes we need to search if some command related to a word exists. Then we can search the manpages for strings in the command. For this we can use: apropos COMMAND   In this article, we took a look at some tips and tricks on working with Linux shell script.Further resources on this subject: Linux Email [Book] Installing VirtualBox on Linux [Article] Linux Shell Script: Logging Tasks [Article] Linux Shell Script: Monitoring Activities [Article] Compression Formats in Linux Shell Script [Article] Making a Complete yet Small Linux Distribution [Article]
Read more
  • 0
  • 0
  • 3438
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 $15.99/month. Cancel anytime
article-image-joomla-16-faqs
Packt
14 Apr 2011
9 min read
Save for later

Joomla! 1.6 FAQs

Packt
14 Apr 2011
9 min read
  Joomla! 1.6 First Look A concise guide to everything that's new in Joomla! 1.6.         Read more about this book       (For more resources on Joomla!, see here.) Question: What are the server requirements for installing Joomla! 1.6 on a web hosting account? Answer: The following system requirements have remained the same since the 1.5 release: Apache 1.3.x or higher. Apache is the web server software that processes the PHP instructions for how to pull in contents from the database and display a web page. XML and Zlib support. Your host's PHP installation should support XML and Zlib functionality. But the PHP and MySQL requirements have changed. To enable you to run a Joomla! 1.6 powered website, your web hosting account should support: PHP 5.2 or higher. PHP is the scripting language that Joomla! is written in. MySQL 5.0.4 or higher. The MySQL database is where Joomla! stores its data (the contents of your site).   Question: What are the changes for templates in Joomla! 1.6? Answer: Templates created for version 1.5 can't be used in Joomla! 1.6. The new release uses clean, semantic HTML code, without using tables for layout purposes. This is good news, as template developers are no longer required to add so-called template overrides in order to achieve a semantic design. However, it is one of the reasons that developers will have to upgrade their existing code to move a 1.5 template to version 1.6. Joomla! 1.6 also introduces some other nice template features, such as the ability to use ‘subtemplates’ (called Template Styles in Joomla!). This new feature allows you to easily create individual styling for parts of your site.   Question: What’s new about categorizing content in Joomla! 1.6? Answer: The main thing that a content management system should help you in doing is of course to publish content and to manage existing content with minimal effort. Joomla! 1.6 allows you to organize content exactly as you want. Up to Joomla! 1.5, you could only classify your content in three levels: sections would contain categories, and categories would hold articles. Although this didn't pose problems for most sites, it was nevertheless a strange restriction. That's why Joomla! 1.6 introduces a more flexible system of classification. Categories can now hold an unlimited number of subcategories. This means that you can have a hierarchy. A category can hold as many subcategories as you need. This concept is called "unlimited nested categories". In most cases you won't need more than two or three subcategories, but if you do, there's nothing to stop you. You can check the content category hierarchy in the Category Manager. Child categories are displayed indented, with small gray lines indicating the sublevel: The above screenshot shows the nested categories contained in the sample data that comes with Joomla! 1.6. As you can see, all article content is stored in subcategories of the main category Sample Data-Articles.   Question: What's the difference between Root user, Super Administrator, Super User, Admin? Answer: When you install Joomla!, there's always one root user, allowed to do anything in the administration area. In Joomla! 1.5, this root user was called Super Administrator. In Joomla! 1.6, this name has been changed to Super User. Another point to note is that the root user is always a Super User—but there can be more Super Users who aren't root users. The root user is a unique Super User who can assign new users to the Super User group. But there's always just one root user created when installing Joomla! Only this root user can change another Super User's details. (You can always identify the root user in the User Manager by his fixed ID number, which in Joomla! 1.6 is always 42).   Question: What's the use of the new User Permissions tab? Answer: When browsing the Global Configuration screen, you'll notice that there's a new tab called Permissions. It's where you set all site-wide user permissions. In Joomla! 1.6, you have much more control over user permissions. You can create new user groups and set permissions on different levels- not just site-wide, as was previously the case in Joomla! 1.5.   Question: What are the changes in the article editor? Answer: Creating or editing an article in Joomla! 1.6 will seem very familiar to 1.5 users. Go to Content | Article Manager | New or Edit to display the article editor screen: (Move the mouse over the image to enlarge.) On closer inspection, you'll notice some items have been renamed or rearranged: In the New Article section, you can set the article to be Featured. This is just another word for what was previously called 'Front Page' or 'Show on Front Page'. In the Article Options, references to sections have gone. The Show Category option allows you to show the Category Title of the current category. The Show Parent option allows you to also show the parent category title among the article details. In the Article Options, references to sections have gone. The Show Category option allows you to show the Category Title of the current category. The Show Parent option allows you to also show the parent category title among the article details. In the New Article section, there's a Permissions button that jumps to the separate Article Permissions section at the bottom of the screen. As you can see, the new user permissions options are available on many levels in the Joomla! 1.6 interface. Here you can set user permissions to delete or edit the current article.   Question: What's the Options button In the Menu Manager: Menus screen about? Answer: In the Menu Manager: Menus screen, there's a new button called Options: Clicking on it will open a pop up screen allowing you set all default User Permissions for all menus.   Question: What's new about the Access Control Levels system? Answer:In Joomla! 1.5, a fixed set of user groups was available, ranging from "Public" users (anyone with access to the frontend of the site) to "Super Administrators", allowed to log in to the backend and do anything. The ACL system in Joomla! 1.6 is much more flexible: Instead of fixed user groups with fixed sets of permissions, you can create as many groups as you want and grant the people in those groups any combination of permissions. ACL enables you to control anything users can do on the site: log in, create, edit, delete, publish, unpublish, trash, archive, manage, or administer things. Users are no longer limited to only one group: a user can belong to different groups at the same time. This allows you to give particular users both the set of permissions for one group and another group without having to create a third, combined set of permissions from the ground up. Permissions no longer apply to the whole site as they did in Joomla! 1.5. You can now set permissions for specific parts of the site. Permissions apply to either the whole site, or to specific components, categories, or items (such as a single article).   Question: How can we set access levels for users? Answer: By default, three Viewing Access Levels are available: Public, Registered, and Special. Go to Users | User Manager and click on the Viewing Access Levels tab to see these levels: This is what the three default Viewing Access Levels mean: Public means that there are no special viewing permissions involved. It's the set of permissions for the Public user group, who are only allowed access to the public site. Registered is the set of permissions for Registered Users. These by default are allowed to log in to the site to view the site parts that are set to the Registered access level. Special is the set of viewing permissions for all users that can log in to the backend (Manager, Administrator, Super User)   Question: How can I customize the logo on the site? Answer: You can customize the logo just by changing the Template Style settings. Let's find out how this works: Navigate to Extensions | Template Manager. Click on the Styles tab and then click on the link Beez2 - Default. The Template Manager: Edit Style screen is displayed. In the Advanced Options panel, locate the Logo option and click on Select. A pop-up screen appears. In the Upload files section, click on Browse to select a logo file from your computer. For best results, use a PNG file with a transparent background applied, with a maximum height of about 65 pixels. Select the image file and click on Start Upload. The message Upload Complete is displayed: Click on the logo image to select it and then click on Insert in the top right corner. In the Edit Style screen, click on Save and then click on View Site. The new logo image is displayed and replaces the Joomla! logo: To further customize the logo and header area, enter a short description of your site in the Advanced Options | Site Description box. This will replace the site tag line, just below the logo.   Question: What is the Redirect Manager? Answer: A new addition in 1.6 is the Redirect Manager, which you can find in the Components menu. This application can be quite useful, especially if you're migrating a 1.5 site to 1.6. When changing to a new site, many URLs from your old site are bound to change. This can result in lots of broken links from other sites that still point to the old URLs. The Redirect Manager helps you to direct visitors who come to your site through outdated links. In the Redirect Manager, just enter the old links and tell Joomla! what new pages it should show instead:   Question: What are the new module features in Joomla! 1.6? Answer: In Joomla! 1.6, using modules is more flexible: You can schedule the time during which a module should display. In previous versions of Joomla!, you could set a start date and an end date for publishing articles. Now this is also possible for modules. Modules are always assigned to one or more menu items. However, when editing a menu in Joomla! 1.5, there was no way to find out or change which modules were assigned to that menu item. You had to leave the menu item edit screen, navigate to the particular module's settings in the Module Manager, and check the module's menu assignment there. In Joomla! 1.6, you can set what modules are assigned to a menu link directly when you're editing a menu link.   Summary In this article we covered some of the most frequently asked questions on Joomla! 1.6. Further resources on this subject: Installing and Configuring Joomla! 1.5 [Article] Search Engine Optimization in Joomla! [Article] Joomla! 1.6: Organizing and Managing Content [Article] Joomla! 1.6: Managing Site Users with Access Control [Article] Mastering Joomla! 1.5 Extension and Framework Development Second Edition [Book]
Read more
  • 0
  • 0
  • 1337

article-image-visualizing-productions-ahead-time-celtx
Packt
12 Apr 2011
13 min read
Save for later

Visualizing Productions Ahead of Time with Celtx

Packt
12 Apr 2011
13 min read
Celtx: Open Source Screenwriting Beginner's Guide Write and market Hollywood-perfect movie scripts the free way!      If you just write scripts, you won't need the features in this article. However, Indie (independent) producers, folks actually making movies, putting together audio visual shows, or creating documentaries will find these tools of immense value and here we look at visualizing all this good stuff (pun, as ever, intended). Sketching Celtx's Sketch Tool allows us to easily visualize ideas and shot setups by adding our drawings of them to projects. Sketches can be separate items in the Project Library (or in folders within the library) or added to a project's Storyboard (more on that in the next section of this article). The Sketch Tool comes with pre-loaded icons for people, cameras, and lights, which we can drag and drop into our sketches, making them look more polished. The icons are SVG images (Scalable Vector Graphics), which allow us to make them as large as we like without losing any quality in the image. The http://celtx.com site makes additional icons available (Art Packs) at low costs (example: $2.99 for 23 icons). Also provided in the Sketch tool are tools for drawing lines, arrows, shapes, and for adding text labels. Just to avoid confusion, let me tell you that there is nothing like pens or erasers or other free drawing features. We'll use various drag-and-drop icons and any of us, artistic talent or not, can turn out very professional-looking storyboards in no time at all. Celtx Projects are containers which hold items such as scripts, index cards, reports, schedules, storyboards, prop lists, and more including sketches. Time for action - starting a new sketch We have two ways of creating a new Sketch, which are as follows: First, open a project (new or already in progress) and look in the Project Library in the upper-left quadrant of the Celtx screen. Sketch is included by default, as shown in the following screenshot: The following steps show the second method for creating a new sketch: Click on File at the very upper-left of the Celtx main window On the drop-down menu, choose Add Item... Click on Sketch and then click on OK, as shown in the following screenshot: What just happened? The new Sketch is added to the Project Library window. If one was already there (likely since it is by default), you now have two with the same name. No problem; simply right-click on one of them, choose Rename, and change its name. We can also delete or duplicate a Sketch this way. To open the main Sketch Tool window from anywhere in a Celtx project, double-click on the name of the Sketch in the Project Library. In the case of a new Sketch created through the Add Item dialog box, as shown in the preceding section, it will already be open and ready for use. That is, the main window covering most of the center of the Celtx screen is where we sketch. Double-clicking on Screenplay or any other item in the Project Library window navigates us to that item and away from our Sketch. It is saved automatically. The following screenshot shows how the Sketch Tool looks when opened: Sketch Tool toolbar Along the top of the middle window (the Sketch Tool window), we have a toolbar. In the preceding screenshot, most of these tools are grayed out. They become fully visible when conditions are met for their use. Let's take a tour. The following screenshot shows the sketch toolbar in its entirety: Now, let's explore these tools individually and see what they do. In addition to the tool bar (shown in the preceding screenshot), I'll include an image of each individual tool as well: Select tool: The first tool from the left is for selecting items in the sketch. There's nothing to select yet, so let's click on the second tool from the left. The select tool is shown in the following screenshot: The diagonal line: It is the second tool from the left and it draws a line. Move the cursor (now a cross) to the point where the line begins, hold down the left mouse button, and drag out the line, releasing the mouse button at its ending point. The diagonal line is shown in the following screenshot: Line tool: Click on the first tool above. The mouse cursor becomes a hollow arrow on a PC but remains a black arrow on the Mac. Select the line we drew by clicking on it (a little hard for a line) or holding down the left mouse button and drawing a box all the way around the line (easier). When the mouse button is released, we know the line is selected because it has a dotted blue line around it and two small gray circles or "handles" at either end. Once the item is selected, just hold down the left mouse button and it can be moved anywhere in the Sketch Tool window.Select either of the handles by moving the cursor arrow over it and pressing the left mouse button. We can now move that end of the line all over the place and it stays wherever the button is released; it's the same for the other end of the line. While the line is selected, just hit the Delete key to erase it. This also works in the same way for all the other elements. Arrow Tool: The third tool from the left (the diagonal arrow) works exactly like the line tool, except there's an arrowhead on one end. It's a useful drawing tool for pointing to something in our diagrams or using as a spear if it's that kind of movie, eh? The arrow tool is shown in the following screenshot: Box and Circle Tools: The fourth tool (the box) draws a box or rectangle and the fifth (the circle) a circle or oval. Clicking on the select tool (the first tool on the left) and using its cursor to click inside of a square or circle selects it. There are two little gray circles which allow us to manipulate the figure just as we did with the line above. The box tool is shown in the following screenshot: And the circle tool is shown in the following screenshot: Text Tool: Suppose we want to label a line, arrow, box, or circle, we can use the sixth tool, that is, the little letter "A", which is shown in the following screenshot: Draw a box and click on the A. The mouse cursor is now an "I-beam". Click in the box. A mini-dialog box appears, as shown in the following screenshot: This Edit Text box allows the selection of the font, size, bold, italic, and provides a place to type in the label, such as the stirring This is a box. Click on OK and the label is in the box, as shown in the following screenshot: If we need to edit an existing label, click on the select tool, double-click on the text, the Edit Text mini-dialog box comes up, and you can edit the text. Keeping the labeled box as an example, we're ready to visit the next two tools, namely, the empty circle and his brother the solid circle, both of which are grayed out at the moment. Let's wake them up. Stroke and Fill Tools: Click on the select tool and then click inside the box. These two tools turn blue and allow us access to them. These are shown in the following screenshot: The empty circle controls the color of the stroke (that's the outline of the item, such as our box) and the solid circle, the fill (the inside color of the item). Note that there is a small arrow on the right side of each circle. Click on the one next to the solid (fill) circle. A color selection box drops down; choose a color by clicking on it. The box now has that color inside it as a fill, as shown in the following screenshot: If you want to change the stroke and/or fill colors, just click on the stroke or fill tool to drop-down the selection box again. Moving on, add another box (or circle, whatever) and move it. Use the select tool, hold down the Shift key, click on the new box, and move it over the original box. Layer Tools: Okay, we now have one item on top of another. Sometimes that's inconvenient in a scene diagram and we need to reverse the order (move one or more items up a layer or more). With the top box selected, look at the toolbar. The next four icons to the right of the stroke and fill circles are now "lit up" (no longer grayed out). The layer tools are shown in the following screenshot: These are, in the order, lower to bottom, lower, raise, and raise to top. In other words, the selected box would be lowered to the bottom-most layer, lowered one layer, raised one layer, or jumped all the way to the top-most layer. Group and Ungroup: Now, to save a few million electrons, let's use the same two boxes again. Select the one on top, hold down the Shift key, and both boxes are now selected. We can move them together, for example. However, note that the next icon to the right is now no longer gray (it's now two blue boxes, one over the other and four smaller black ones). This is the group tool, which is shown in the following screenshot: Clicking on it groups or bonds the selected items together. This, of course, lights up the next icon on the toolbar, the (wait for it) ungroup tool, which restores independence to grouped items. Undo and Redo Tools: The next two toolbar icons, the curved arrows, are undo and redo tools. They reverse an action to the previous state or restore an item to its next state (if there is one, that is, "undo" and "redo"). These tools are shown in the following screenshot: Cut, Copy, and Paste Tools: The last three tools on the Sketch Tool window toolbar are the cut, copy, and paste tools, as shown in the following screenshot: Cutting removes an item but retains it on the clipboard, copying leaves the item and also puts a copy of it on the clipboard, while paste puts the item from the clipboard back into the sketch. Now, we come to the fun part, icons! As in "yes, icon do a professional-looking sketch." (Sorry, couldn't resist.) Icons for a professional look Celtx provides icons, giving our sketches a polished professional look (neat, artistic, follows industry entertainment conventions) while requiring little or no artistic ability. The Palettes windows, found on the right side of the main Sketch Tool window, list available icons. The default installation of Celtx includes a very limited number of icons, one camera, two kinds of lights, and a top-down view of a man and a woman. Celtx, of course, is open source software and thus free (a price I can afford). However, one of the ways in which its sponsoring developer, a Canadian company, Greyfirst Corp. in St. John's, Newfoundland, makes money is by selling add-ons to the program, one type being additional icons in the form of Art Packs. In the following screenshot, if we click on the + Get Art Packs link, a webpage opens where one can order Art Packs and other add-ons at quite reasonable prices: Now, to use an icon in a sketch, let's start with the camera. Open a new sketch by doubleclicking on Sketch in the Project Library window or Add Item from the main File menu. In the Palettes window, move the mouse cursor over Camera and hold down the left mouse button while dragging the camera icon into the main Sketch Tool window. It looks like the following screenshot: Manipulating icons: When any icon is dragged into the main window of the Sketch Tool (and anytime that icon is selected by clicking on it with the select tool cursor described earlier) it has a dotted circle around it (as shown in the preceding screenshot) and two small solid circles (violet on top, olive below). Clicking on the violet circle and holding down the left mouse button while dragging allows rotation of the icon. Releasing the button stops rotation and leaves the icon in that orientation. Clicking on the olive circle (the lower one) and holding down the left mouse button and dragging allow resizing the icon, either larger or smaller. As these icons, like the lines, arrows, boxes, and circles we discussed earlier in this article are also SVG (Scalable Vector Graphics), we can have them as large as desired with no pixilation or other distortion. Using the Sketch Tool toolbar and the supplied icons, we can rapidly and easily draw professional looking diagrams like the scene shown in the following screenshot, which shows two lights, the camera, the talent, arrows showing their movement in the scene, and the props: Again, additional icons may be purchased from the http://celtx.com website. For example, the following screenshot shows the twenty-three icons available in Art Pack 1: Saving a finished Sketch Now is a good time for us to take a moment and discuss the limitations of the Sketch Tool. This feature provides a fast way of whipping up a scene diagram from inside a Celtx project. It does not replace an outside drawing program nor give us the functionality of something like Adobe Illustrator, but it is quite powerful and very handy. By the way, we can use external media files in Celtx and we'll do just that in both of the remaining sections of this article. Another limitation concerns saving sketches. There's no way of exporting the sketch as an external image such as .jpg or .bmp. In fact, even saving within the Celtx project is automated. Do the following to see what I mean: In a Celtx project, double-click on Sketch in the Project Library to start a sketch. Draw something. Double-click on Screenplay. Then double-click on Sketch. The drawing is still there. Save the Celtx project, exit, and open it again. Double-click on Sketch. Drawing's still there! We can even use Add Item from the File menu (a shortcut is the little plus symbol beneath the Project Library title) and add another Sketch (same name) to the Project Library and even draw a new sketch in it. Of course, having different drawings with the same name is hardly utilitarian, so here's how we really save a sketch.
Read more
  • 0
  • 0
  • 2794

article-image-joomla-16-organizing-and-managing-content
Packt
08 Apr 2011
10 min read
Save for later

Joomla! 1.6: Organizing and Managing Content

Packt
08 Apr 2011
10 min read
  Joomla! 1.6 First Look A concise guide to everything that's new in Joomla! 1.6. Anyone who's used to working with the previous versions of Joomla! knows the old section—category—article drill. Articles had to be part of a category and categories had to be part of a section. There were no workarounds for this rigid three-level content organization scheme. Sometimes, this required Joomla! users to adapt their content to the system's limitations (or extend Joomla!'s functionality by using more powerful content management extensions, so-called Content Construction Kits or CCKs). In Joomla! 1.6, the rigid old system has finally been replaced. Sections have gone; there are now only categories, and any category can hold as many levels of subcategories as you need. In the backend, instead of both a Section Manager and a Category Manager, you'll now find only a Category Manager. You can forget the concept of sections altogether; in Joomla!! 1.6 there's no need for them anymore, as they're no longer needed as 'containers' to hold categories. Improvement #1: categories can now be one level deep Sometimes, you'll want to organize articles in just one category. Let's say you want to add a few articles about your organization: who you are, where to reach you, and so on. You don't need any subcategories. You'd need a structure like this: In Joomla! 1.5, this simple setup of a "sectionless" category holding articles wasn't possible. You'd have to organize content in sections and categories—which implied that any group of articles would be stored two levels deep, even if you didn't need this. The only alternative was not to organize content, using uncategorized articles. In Joomla! 1.6, you can put content in just one category if you want to. Just go to Content | Category Manager | Add New Category to create a new category. In the Parent drop down box, select No parent: As this category has "No parent", it becomes a top-level or "parent" category. It's as simple as that; now you can do something that wasn't possible in Joomla! 1.5, by assigning articles directly to this category. Improvement #2: creating multiple category levels Joomla!'s old section—category—article approach didn't allow you to create categories within categories ( "nested categories"). However, on content-rich sites, you might need more than two levels of content organization and use a few subcategories. Here's an example from a site featuring product reviews. It uses several levels to organize the main category of "reviews" in subcategories of product types, brands, and models: A great advantage of being able to create such a structure is that it allows for very specific searches (that is, within categories) and multiple ways of navigation. Another example is if you are creating a catalog that you want to be searchable with multiple filters such as manufacturer, price, general item type, or a specific product name. Creating a set of 'nested' categories Let's find out how you can quickly set up a few nested categories like the ones shown in the illustration above: Go to Content | Category Manager | Add New Category. In the Title field, enter Reviews. In the Parent field, make sure that the default option No parent is selected. The screen should look like this: Click on Save & New. A message appears to confirm your action: Category successfully saved. At the same time, all the fields in the Add New Category are emptied. To create a subcategory, enter the subcategory name Cameras in the Title field. In the Parent drop-down box, select Reviews: Click on Save & New to store the subcategory. Repeat the previous three steps to create more subcategories. For each new category, first enter a title, then select the appropriate parent category and save it by clicking on Save & New. When you're done with creating subcategories, click on Save & Close to view the results in the Category Manager. In the example below, the Cameras category is parent to a subcategory Compact Cameras. The Compact Cameras category is parent to a subcategory called Canon. If you've followed the above example, you'll find the following set of categories in the Category Manager. They are displayed as shown below: The Reviews name isn't indented, as it is a top-level category. Cameras, Compact Cameras, and Canon are displayed indented as they are subcategories. When you create articles, you can now assign them to the new categories. The same category hierarchy as you've just seen in the Category Manager is displayed in the Category drop-down box: Using nested categories in the sample data You've just set up a few categories and subcategories yourself. On a complex site, you can have a far more complex structure. Don't worry, I won't ask you to create dozens of nested categories right now—but it's a good idea to learn from the example set by the Joomla! Developers. Let's have a look at the categories and articles that come with Joomla! when it is installed with sample data. The way things are organized there will give you some idea of how you can deploy nested categories and get the most out of the new system. Exploring the sample data On the frontend, click on the Sample sites link in the This Site menu. On the Sample Sites page, a new menu appears. This menu gives access to both sample sites—Australian Parks and Fruit Shop: Have a look around at both example sites. They appear to be separate websites, but they're not. Here the Joomla! developers have cunningly deployed the possibilities of the new category system and have organized all content for the three sites (the main site and two example sites) within one big website. To find out how this is done, let's have a look at the categories in the backend: Go to Content | Category Manager to see how the sample content is organized. The screenshot below shows an overview: As you can see in the screenshot above, there's one top-level category, Sample Data-Articles. All other articles are contained in the subcategories of this main level category. Apart from the top level category, there are three main categories: The Joomla! category. It has three sublevels. The Park Site category. It has two sublevels. The Fruit Shop category. It has one sublevel. Finally, there's a group of articles that's not in any category; it's a bunch of leftovers all marked as Uncategorized. How can different categories look like different sites? As you click through the example sites, not only the content changes; the menu links to each main category (such as the Parks and Fruit Shop category) have specific templates assigned to them. This way, on the frontend, the look-and-feel of the different main article categories are totally different, whereas in the backend, they're just part of one big site. Applying templates to categories can give visitors the impression of exploring a separate set of websites. Although there's no limit to the number of levels in the category hierarchy, even in this rather complex set of sample site articles, categories don't go further than four levels deep. It is possible to make more subcategories, but keep in mind that this means that your content will be stored 'deeper' in the hierarchy, possibly making it more difficult for visitors (and search engines) to find it. One benefit of placing interrelated content under its own main level category is that you can easily unpublish, delete, or archive any content dealing with a specific subject by unpublishing, deleting, or archiving this main level category. That's why the Joomla! developers have chosen to use one top-level category for all sample data. By unpublishing the top level category (Sample Data-Articles), you can unpublish all of the example content in one go. New category settings: notes and metadata When entering or editing a new category, the New Category or Edit Category screen now offer you an area to type notes about the purpose of the category or related items, as well as a place to add keywords and a description (metadata). The Note field (found in the Basic Options section) can be useful to share some extra information about the category with other backend users. For example, you can enter a short explanation about this category ('subcategory of ...'): Adding category metadata In Joomla! 1.5, there was no way to separately enter metadata for category pages. Now, you can enter specific Meta Description and Meta Keywords in the Metadata Options section when creating or editing a category. Another new item in the Basic Options of a category is the Alternative Layout select box. Alternative layouts are an advanced new feature that enable you to select a customized layout for the current category, provided the selected template (or a third-party component) provides these extra layout options. A template can contain so-called template override files, allowing for customized layouts that replace Joomla!'s default views. Using the Alternative Layout select box, you can now select the template override you want to activate for this particular item. To find out more about this feature, have a look at the "Introduction to Alternative Layouts in Version 1.6" document on the Joomlacode site. You'll find it at http://downloads.joomlacode.org/trackeritem/5/8/6/58619/introtoaltlayoutsinversion1-6v2.pdf. Fresh ways to display category contents on the frontend Joomla! 1.6 provides several additional methods to display category contents. They replace the four classic layouts of Category List, Category Blog, Section List, and Section Blog. When creating a new menu link pointing to a category, you are now presented with a slightly different set of Menu Item Types: These are the category views are available: List All Categories is a new view, described below Category Blog was previously called Category Blog Layout Category List was previously called Category List Layout The Blog and List views are basically the same as they've always been. However, these display types now offer new settings that provide more control over the look and feel of the resulting pages. Along with the new List All Categories menu item type, there are also a few new module types that provide you with new ways to display links to categories and their article contents. Let's have a closer look at the new category views. New category view # 1: List All Categories The new category system rationalizes the organization of content, even in large or complex websites. One advantage of this is that you can more easily give visitors (and search engines!) access to all that well-structured content, just by adding one menu link to a main level category. This will allow visitors to easily drill down the different layers (the category levels) of the site structure. To achieve this, the new List All Categories menu link type allows you to display categories as well as their subcategory contents. You can see an example of this menu organization if you select the Site Map link on the This Site menu in the frontend of the sample Joomla! 1.6 content. As we've previously seen, the sample data that comes with Joomla! 1.6 is organized in a structured way. The Site Map link uses the List All Categories menu item type to show all levels in the category hierarchy.  
Read more
  • 0
  • 0
  • 1971

article-image-apache-wicket-displaying-data-using-datatable
Packt
01 Apr 2011
6 min read
Save for later

Apache Wicket: displaying data using DataTable

Packt
01 Apr 2011
6 min read
It's hard to find a web application that does not have a single table that presents the user with some data. Building these DataTables, although not very difficult, can be a daunting task because each of these tables must often support paging, sorting, filtering, and so on. Wicket ships with a very powerful component called the DataTable that makes implementing all these features simple and elegant. Because Wicket is component-oriented, once implemented, these features can be easily reused across multiple DataTable deployments. In this article, we will see how to implement the features mentioned previously using the DataTable and the infrastructure it provides. Sorting A common requirement, when displaying tabular data, is to allow users to sort it by clicking the table headers. Click a header once and the data is sorted on that column in ascending order; click it again, and the data is sorted in the descending order. In this recipe, we will see how to implement such a behavior when displaying data using a DataTable component. We will build a simple table that will look much like a phone book and will allow the sorting of data on the name and e-mail columns: Getting ready Begin by creating a page that will list contacts using the DataTable, but without sorting: Create Contact bean: Contact.java public class Contact implements Serializable { public String name, email, phone; // getters, setters, constructors2. Create the page that will list the contacts: HomePage.html <html> <body> <table wicket_id="contacts" class="contacts"></table> </body> </html> HomePage.java public class HomePage extends WebPage { private static List<Contact> contacts = Arrays.asList( new Contact("Homer Simpson", "[email protected]", "555-1211"), new Contact("Charles Burns", "[email protected]", "555-5322"), new Contact("Ned Flanders", "[email protected]", "555-9732")); public HomePage(final PageParameters parameters) { // sample code adds a DataTable and a data providert hat uses the contacts list created above } } How to do it... Enable sorting by letting DataTable columns know they can be sorted by using a constructor that takes the sort data parameter: HomePage.java List<IColumn<Contact>> columns = new ArrayList<IColumn<Contact>>(); columns.add(new PropertyColumn<Contact>(Model.of("Name"), "name","name")); columns.add(new PropertyColumn<Contact>(Model.of("Email"), "email", "email")); columns.add(new PropertyColumn<Contact>(Model.of("Phone"), "phone")); Implement sorting by modifying the data provider: private static class ContactsProvider extends SortableDataProvider<Contact> { public ContactsProvider() { setSort("name", true); } public Iterator<? extends Contact> iterator(int first, int count) { List<Contact> data = new ArrayList<Contact>(contacts); Collections.sort(data, new Comparator<Contact>() { public int compare(Contact o1, Contact o2) { int dir = getSort().isAscending() ? 1 : -1; if ("name".equals(getSort().getProperty())) { return dir * (o1.name.compareTo(o2.name)); } else { return dir * (o1.email.compareTo(o2.email)); } } }); return data.subList(first, Math.min(first + count, data.size())).iterator(); } public int size() { return contacts.size(); } public IModel<Contact> model(Contact object) { return Model.of(object); } } How it works... DataTable supports sorting out of the box. Any column with the IColumn#getSortProperty() method that returns a non-null value is treated as a sortable column and Wicket makes its header clickable. When a header of a sortable column is clicked Wicket will pass the value of IColumn#getSortProperty to the data provider which should use this value to sort the data. In order to know about the sorting information the data provider must implement the ISortableDataProvider interface; Wicket provides the default SortableDataProvider implementation which is commonly used to implement sort-capable data providers. DataTable will take care of details such as multiple clicks to the same column resulting in change of sorting direction, so on. Let's examine how to implement sorting in practice. In step 1 and 2, we have implemented a basic DataTable that cannot yet sort data. Even though the data provider we have implemented already extends a SortableDataProvider, it does not yet take advantage of any sort information that may be passed to it. We start building support for sorting by enabling it on the columns, in our case the name and the email columns: List<IColumn<Contact>> columns = new ArrayList<IColumn<Contact>>(); columns.add(new PropertyColumn<Contact>(Model.of("Name"), "name", "name")); columns.add(new PropertyColumn<Contact>(Model.of("Email"), "email", "email")); columns.add(new PropertyColumn<Contact>(Model.of("Phone"), "phone")); We enable sorting on the columns by using the three-argument constructor of the PropertyColumn, with the second argument being the "sort data". Whenever a DataTable column with sorting enabled is clicked, the data provider will be given the value of the "sort data". In the example, only the name and e-mail columns have sorting enabled with the sort data defined as a string with values "name" and "e-mail" respectively. Now, let's implement sorting by making our data provider implementation sort-aware. Since our data provider already extends a provider that implements ISortableDataProvider we only need to take advantage of the sort information: public Iterator<? extends Contact> iterator(int first, int count) { List<Contact> data = new ArrayList<Contact>(contacts); Collections.sort(data, new Comparator<Contact>() { public int compare(Contact o1, Contact o2) { int dir = getSort().isAscending() ? 1 : -1; if ("name".equals(getSort().getProperty())) { return dir * (o1.name.compareTo(o2.name)); } else { return dir * (o1.email.compareTo(o2.email)); } } }); return data.subList(first, Math.min(first + count, data.size())).iterator(); } First we copy the data into a new list which we can sort as needed and then we sort based on the sort data and direction provided. The value returned by getSort().getProperty() is the same sort data values we have defined previously when creating columns. The only remaining task is to define a default sort which will be used when the table is rendered before the user clicks any header of a sortable column. We do this in the constructor of our data provider: public ContactsProvider() { setSort("name", true); } There's more... DataTable gives us a lot out of the box; in this section we see how to add some usability enhancements. Adding sort direction indicators via CSS DataTable is nice enough to decorate sortable <th> elements with sort-related CSS classes out of the box. This makes it trivial to implement sort direction indicators as shown in the following screenshot: A possible CSS style definition can look like this: table tr th { background-position: right; background-repeat:no-repeat; } table tr th.wicket_orderDown { background-image: url(images/arrow_down.png); } table tr th.wicket_orderUp { background-image: url(images/arrow_up.png); } table tr th.wicket_orderNone { background-image: url(images/arrow_off.png);
Read more
  • 0
  • 1
  • 7714
article-image-opencart-layout-structure
Packt
29 Mar 2011
7 min read
Save for later

OpenCart: layout structure

Packt
29 Mar 2011
7 min read
In this article, we will see the default layout structure of OpenCart. We'll discuss the cascading stylesheet file from it and modify it according to our needs. First of all, we'll use the reset style properties to eliminate cross-browser problems. We will discuss every property here. We'll also see the corresponding effects on our site. Then, we'll do some basic styling for the site. For each change in style, we will see why we did that. Folder structure In our main OpenCart folder, we have the admin and catalog sections. These are two separate subsystems. As the name says, admin has the files and folders for administration operation. Catalog contains the store files and folders. Each admin and catalog section has a separate model, view, and controller. Under this admin and catalog folder, we will see the model, view, and controller folders. You will see different subfolders within those folders. So, let's discuss this MVC structure in the following paragraph. OpenCart is built with the MVC design pattern. So, it has model, view, and controller. A user requests the OpenCart controller to process the request. Then, the controller gets the data using the model and processes the fetched data to show the response with the view file. The following figure shows the above operation of MVC: For theme modification, we will focus only on the View folder of the catalog in this article. It has javascript and theme folders. We place our themes under the theme folder and the necessary JavaScript files in the JavaScript folder. Each theme has an image, stylesheet, and template folder. We will see how we can create a new theme later in this article. Theme file style As we stated earlier, OpenCart uses the MVC design pattern. So, the view files remain separated from the core code. These files are .tpl files. And, they are placed under catalogviewthemedefaulttemplate. These .tpl files are basically HTML files. They have PHP code within them to display the necessary data. OpenCart doesn't use the smarty template engine. Rather, it uses embedded PHP codes that are easy to use. We assign the PHP variables in the controller with necessary data. Then, we call the variable in the .tpl view file. We can also use the global class reference variable. In the controller, we will assign the value like this: $this->data['shop_name'] = 'store'; Here, we assigned store value to the shop_name variable. In the .tpl view file, we will display the value like this: <?php echo $shop_name; ?> Creating a new theme In this recipe, we will see the steps to create a new theme for OpenCart. There are some rules to create OpenCart themes. Getting started Let's get started with the steps to create a new theme with OpenCart. How to do it Following are the steps for creating a new theme for OpenCart: First of all, we need to create a new folder under catalogviewtheme. For example, we will name it shop for this project. Now, we need to copy some files from the default theme folder to our new theme folder. The files are the following: catalogviewthemedefaultstylesheet*.* catalogviewthemedefaultimage*.* catalogviewthemedefaulttemplatecommonheader.tpl We have to edit some values in the header.tpl file for our new theme. We will replace all default keywords with our new theme name shop. Actually, there are six places where we need to replace the new theme name. The lines are the following: <link rel="stylesheet" type="text/css" href="catalog/view/theme/shop/stylesheet/stylesheet.css" /> // other lines ... <link rel="stylesheet" type="text/css" href="catalog/view/theme/shop/stylesheet/ie6.css" /> //other lines ... <div class="div3"> <a href="<?php echo str_replace('&', '&amp;', $special); ?>" style="background-image: url('catalog/view/theme/shop/image/special.png');"> <?php echo $text_special; ?></a> <a onclick="bookmark(document.location, '<?php echo addslashes($title); ?>');" style="background-image: url('catalog/view/theme/shop/image/bookmark.png');"> <?php echo $text_bookmark; ?></a><a href="<?php echo str_replace('&', '&amp;', $contact); ?>" style="background-image: url('catalog/view/theme/shop/image/contact.png');"><?php echo $text_contact; ?></a><a href="<?php echo str_replace('&', '&amp;', $sitemap); ?>" style="background-image: url('catalog/view/theme/shop/image/sitemap.png');"><?php echo $text_sitemap; ?></a></div> //other lines ... And now, save it. Now, we will go to the admin area. First log in with our stored admin credentials. Go to System | Settings in the admin panel: We will go to the Store tab. We will change the theme from default to shop, our new theme from a select list. You can make changes on your theme's CSS file. Resetting layout styles Before beginning our theme styling work, we must first reset all the styles. This will help us with cross-browser problems. Getting started We need to modify the stylesheet.css file of our new theme first. We will go to catalogviewthemeshopstylesheet. And open up stylesheet.css in our favourite editor. How to do it Now, we will add reset styles to our stylesheet.css file. First, we need to change the browser's margin, padding, and border properties. We will set styles for several different HTML tags. We can add extra style properties into it: html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; outline: 0; font-size: 100%; vertical-align: baseline; background: transparent; } We will see the effect of our code in our store. The product images will come closer now. We adjust the line height of body tag. So, put the following code in the CSS file. body { line-height: 1; } This also squeezes the lines in the body element. The following image depicts this: By applying the above style, the line height of these tabs becomes shortened. We need to reset the style for ordered/unordered list elements. Hence, we use the following reset value: ol, ul { list-style: none; } It shows all the ul, ol tags without the default bullet properties. Now, we will reset the blockquote element styles. We will find the changes if we use blockquotes in our HTML code: blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } For all the elements, we are going to change the focus-styling attributes. We change the outline properties to 0. We set the styles like the following: :focus { outline: 0; } There could be some styling for insert and deletion in some browsers. So, we will use this styling for the purpose: ins { text-decoration: none; } del { text-decoration: line-through; } We will control the styling of our tables also. We set the border and spacing qualities like the following: table { border-collapse: collapse; border-spacing: 0; } We still need to set the attribute cell-spacing to 0. So, our reset styling becomes the following: html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; outline: 0; font-size: 100%; vertical-align: baseline; background: transparent; } body { line-height: 1; } ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } :focus { outline: 0; } ins { text-decoration: none; } del { text-decoration: line-through; } table { border-collapse: collapse; border-spacing: 0; } We can place it at the start of our site's style file stylesheet.css, or we can create a new file and put the content there also. To do that, just create a new CSS file within the catalogviewthemeshopstylesheet folder. For example, we can name the new style file as reset.css. If we use a new style file, then we need to add the style file in the controller.  
Read more
  • 0
  • 0
  • 3282

article-image-cakephp-authentication-setup-application
Packt
28 Mar 2011
11 min read
Save for later

CakePHP: authentication setup on an application

Packt
28 Mar 2011
11 min read
In this CakePHP tutorial, you'll learn how to set up a basic authentication system. Follow the recipes and you'll find all the code you need. Setting up a basic authentication system The first task to be completed when we are in the process of adding authentication to an application is to identify which controllers will need user access. Normally we would make every controller and action protected by default, and then we would specify which areas of our application allow public access. Getting ready We must have a users table that should contain, at least, two fields: username (to hold the username) and password (to hold a hash made out of the user's password). If you don't have a table for this purpose, you can use the following SQL statement to create it: CREATE TABLE `users`( `id` INT UNSIGNED AUTO_INCREMENT NOT NULL, `username` VARCHAR(255) NOT NULL, `password` CHAR(40) NOT NULL, PRIMARY KEY(`id`) ); How to do it... Create a file named users_controller.php and place it inside your app/controllers folder with the following contents: <?php class UsersController extends AppController { public function login() { } public function logout() { $this->redirect($this->Auth->logout()); } } ?> Create a file named login.ctp in your app/views/users folder (create the folder if you don't have one already), and add the following contents: <?php echo $this->Form->create(array('action'=>'login')); echo $this->Form->inputs(array( 'legend' => 'Login', 'username', 'password' )); echo $this->Form->end('Login'); ?> Create a file named app_controller.php in your app/ folder with the following contents: <?php class AppController extends Controller { public $components = array( 'Auth' => array( 'authorize' => 'controller' ), 'Session' ); public function isAuthorized() { return true; } } ?> Modify the UsersController, and add the following code before the login method: public function beforeFilter() { parent::beforeFilter(); $this->Auth->allow('add'); } public function add() { if (!empty($this->data)) { $this->User->create(); if ($this->User->save($this->data)) { $this->Session->setFlash('User created!'); $this->redirect(array('action'=>'login')); } else { $this->Session->setFlash('Please correct the errors'); } } } Create a file named add.ctp and place it in your app/views/users folder with the following contents: <?php echo $this->Form->create(); echo $this->Form->inputs(array( 'legend' => 'Signup', 'username', 'password' )); echo $this->Form->end('Submit'); ?> We now have a fully working authentication system. We can add new users by browsing to http://localhost/users/add, logging in by browsing to http://localhost/users/login, and finally logging out by browsing to http://localhost/users/logout. After creating a user, you should see the login form with a success message, as shown in the following screenshot: How it works... We start by creating two actions in the UsersController class: login(), to show and process submissions of the login form, and logout(), to handle users logging out. You may be surprised that the login() method has no logic whatsoever. To display the form, all we need to do is display the action's view. The form submission is taken care of by the Auth component, leaving us with no need to implement any controller logic. Therefore, the only implementation we need is to create a view for this action, which includes a simple form with two fields: username, and password. The inputs method of CakePHP's FormHelper is a shortcut designed to avoid multiple calls to the input method. By using it, we can create a full form with elements without the need to call FormHelper::input() several times. The logout() controller action simply calls the Auth component's logout() method. This method removes the logged-in user data from the session, and returns the address to which the user should be redirected after logging out, obtained from the previously configured logoutRedirect setting of the component (defaults to the application's home page if the setting was not configured.) Next, we add two components to the controller: Session, and Auth. The Session component is needed to create the messages (through the use of its setflash() method) that informs the user if a login attempt was unsuccessful, or if a user was created. The Auth component operates between your controller's actions and the incoming request by means of the beforeFilter callback method. It uses it's authorize setting to check what type of authentication scheme is to be used. Once the Auth component is added to a controller, all actions in that controller are not accessible unless there is a valid user logged in. This means that if we had any actions that should be public (such as the login() and add() actions in our controller), we would have to tell the Auth component about them. If one wishes to make some actions public, one can add the name of these actions to the allowedActions setting of the Auth component, or by calling its allow() method. We use the later approach to tell the Auth component that the add() action should be reachable without a logged-in user. The login() action is automatically added to the list of public actions by the Auth component. When the user attempts to reach an action that is not within the public actions, the Auth component checks the session to see if a user is already logged in. If a valid user is not found, it redirects the browser to the login action. If there is a user who is logged in, it uses the controller's isAuthorized method to check if the user has access. If its return value is true, it allows access, otherwise access is rejected. In our case, we implemented this method in AppController, our base controller class. If the attempted action requires a user who is logged in, the login() action is executed. After the user submits data using the login form, the component will first hash the password field, and then issue a find operation on the User model to find a valid account, using the posted username and password. If a valid record is found, it is saved to the session, marking the user as logged in. Hashing a password confirmation field When the Auth component is enabled on a controller and the user submits a form with a field named password (regardless if it is being rendered in the login form), the component will automatically hash the password field before executing the controller's action. The Auth component uses the salt defined in the configuration setting Security.salt (in your app/config/core.php file) to calculate the hash. Different salt values will produce different hashes even when using the same password. Therefore, make sure you change the salt on all your CakePHP applications, thus enhancing the security of your authentication system. This means that the action will never hold the plain password value, and this should be particularly noted when utilizing mechanisms to confirm password validations. When you are implementing such validation, make sure you hash the confirmation field using the proper method: if (!empty($this->data)) { $this->data['User']['confirm_password'] = $this->Auth- >password($this->data['User']['confirm_password']); // Continue with processing } Using and configuring the Auth component If there is something that defines the Auth component, it is its flexibility that accounts for different types of authentication modes, each of these modes serving different needs. In this recipe, you will learn how to modify the component's default behavior, and how to choose between the different authentications modes. Getting ready We should have a fully working authentication system, so follow the entire recipe Setting up a basic authentication system. We will also add support to have disabled user accounts. Add a field named active to your users table with the following SQL statement: ALTER TABLE `users` ADD COLUMN `active` TINYINT UNSIGNED NOT NULL default 1; How to do it... Modify the definition of the Auth component in your AppController class, so it looks like the following: public $components = array( 'Auth' => array( 'authorize' => 'controller', 'loginRedirect' => array( 'admin' => false, 'controller' => 'users', 'action' => 'dashboard' ), 'loginError' => 'Invalid account specified', 'authError' => 'You don't have the right permission' ), 'Session' ); Now while still editing your app/app_controller.php file, place the following code right below the components property declaration, at the beginning of the beforeFilter method in your AppController class: public function beforeFilter() { if ($this->Auth->getModel()->hasField('active')) {$this->Auth->userScope = array('active' => 1); } } Copy the default layout from cake/libs/view/layouts/default.ctp to your app/views/layouts directory, and make sure you place the following line in your layout where you wish to display authentication messages: <?php echo $this->Session->flash('auth'); ?> Edit your app/controllers/users_controller.php file and place the following method right below the logout() method: public function dashboard() { } Finally, create the view for this newly added action in a file named dashboard.ctp and place it in your app/views/users folder with the following contents: <p>Welcome!</p> If you now browse to http://localhost/users/login and enter the wrong credentials (wrong username and/or password), you should see the error message shown in the following screenshot: How it works... As the Auth component does its magic right before a controller action is executed, we either need to specify its settings in the beforeFilter callback, or pass them in an array when adding the component to the components property. A common place to do it is in the beforeFilter() method of the AppController class, as by doing so we can share the same authentication settings throughout all our controllers. This recipe changes some Auth settings, so that whenever a valid user logs in, they are automatically taken to a dashboard action in the UsersController (done via the loginRedirect setting.) It also adds some default error messages through the component's respective settings: loginError for when the given account is invalid, and authError for when there is a valid account, but the action is not authorized (which can be achieved by returning false from the isAuthorized() method implemented in AppController.) It also sets the component's userScope setting in AppController::beforeFilter(). This setting allows us to define which conditions the User find operation need to match to allow a user account to log in. By adding the userScope setting, we ensure that only user records that have the active field set to 1 are allowed access. Changing the default user model As you may have noticed, the role of the User model is crucial, not only to fetch the right user account, but also to check the permissions on some of the authentication schemes. By default, the Auth component will look for a User model, but you can change which model is to be used by setting the userModel property or the userModel key in the settings array. For example, if your user model is Account, you would add the following setting when adding the Auth component to your controller: 'userModel' => 'Account' Or equivalently, you would add the following to the beforeFilter method of your AppController class, in the block of code where you are setting up the component: $this->Auth->userModel = 'Account'; There's more... The $authorize property of the Auth component (or the authorize key in the Auth component settings array) defines which authentication scheme should be used. Possible values are: controller: It makes the component use the controller's isAuthorized method, which returns true to allow access, or false to reject it. This method is particularly useful when obtaining the logged-in user model: It is similar to controller; instead of using the controller to call the method, it looks for the isAuthorized method in the User model. First, it tries to map the controller's action to a CRUD operation (one of 'create', 'read', 'update', or 'delete'), and then calls the method with three arguments: the user record, the controller that is being accessed, and the CRUD operation (or actual controller action) that is to be executed. object: It is similar to model; instead of using the model to call the method, it looks for the isAuthorized method in a given class. In order to specify which class, set the AuthComponent::$object property to an instance of such a class. It calls the method with three arguments: the user record, the controller that is being accessed, and the action that is to be executed. actions: It uses the Acl component to check for access, which allows a much more grained access control. crud: It is similar to actions; the difference lies in the fact that it first tries to map the controller's action to a CRUD operation (one of 'create', 'read', 'update', or 'delete'.)
Read more
  • 0
  • 0
  • 3278

article-image-anatomy-wordpress-plugin
Packt
25 Mar 2011
7 min read
Save for later

Anatomy of a WordPress Plugin

Packt
25 Mar 2011
7 min read
  WordPress 3 Plugin Development Essentials Create your own powerful, interactive plugins to extend and add features to your WordPress site         Read more about this book       WordPress is a popular content management system (CMS), most renowned for its use as a blogging / publishing application. According to usage statistics tracker, BuiltWith (http://builtWith.com), WordPress is considered to be the most popular blogging software on the planet—not bad for something that has only been around officially since 2003. Before we develop any substantial plugins of our own, let's take a few moments to look at what other people have done, so we get an idea of what the final product might look like. By this point, you should have a fresh version of WordPress installed and running somewhere for you to play with. It is important that your installation of WordPress is one with which you can tinker. In this article by Brian Bondari and Everett Griffiths, authors of WordPress 3 Plugin Development Essentials, we will purposely break a few things to help see how they work, so please don't try anything in this article on a live production site. Deconstructing an existing plugin: "Hello Dolly" WordPress ships with a simple plugin named "Hello Dolly". Its name is a whimsical take on the programmer's obligatory "Hello, World!", and it is trotted out only for pedantic explanations like the one that follows (unless, of course, you really do want random lyrics by Jerry Herman to grace your administration screens). Activating the plugin Let's activate this plugin so we can have a look at what it does: Browse to your WordPress Dashboard at http://yoursite.com/wp-admin/. Navigate to the Plugins section. Under the Hello Dolly title, click on the Activate link. You should now see a random lyric appear in the top-right portion of the Dashboard. Refresh the page a few times to get the full effect. Examining the hello.php file Now that we've tried out the "Hello Dolly" plugin, let's have a closer look. In your favorite text editor, open up the /wp-content/plugins/hello.php file. Can you identify the following integral parts? The Information Header which describes details about the plugin (author and description). This is contained in a large PHP /* comment */. User-defined functions, such as the hello_dolly() function. The add_action() and/or add_filter() functions, which hook a WordPress event to a user-defined function. It looks pretty simple, right? That's all you need for a plugin: An information header Some user-defined functions add_action() and/or add_filter() functions In your WordPress Dashboard, ensure that the "Hello Dolly" plugin has been activated. If applicable, use your preferred (s)FTP program to connect to your WordPress installation. Using your text editor, temporarily delete the information header from wpcontent/ plugins/hello.php and save the file (you can save the header elsewhere for now). Save the file. Refresh the Plugins page in your browser. You should get a warning from WordPress stating that the plugin does not have a valid header: Ensure that the "Hello Dolly" plugin is active. Open the /wp-content/plugins/hello.php file in your text editor. Immediately before the line that contains function hello_dolly_get_lyric, type in some gibberish text, such as "asdfasdf" and save the file. Reload the plugins page in your browser. This should generate a parse error, something like: pre width="70"> Parse error: syntax error, unexpected T_FUNCTION in /path/to/ wordpress/html/wp-content/plugins/hello.php on line 16 Author: Listed below the plugin name Author URI: Together with "Author", this creates a link to the author's site Description: Main block of text describing the plugin Plugin Name: The displayed name of the plugin Plugin URI: Destination of the "Visit plugin site" link Version: Use this to track your changes over time Now that we've identified the critical component parts, let's examine them in more detail. Information header Don't just skim this section thinking it's a waste of breath on the self-explanatory header fields. Unlike a normal PHP file in which the comments are purely optional, in WordPress plugin and theme files, the Information Header is required! It is this block of text that causes a file to show up on WordPress' radar so that you can activate it or deactivate it. If your plugin is missing a valid information header, you cannot use it! Exercise—breaking the header To reinforce that the information header is an integral part of a plugin, try the following exercise: After you've seen the tragic consequences, put the header information back into the hello.php file. This should make it abundantly clear to you that the information header is absolutely vital for every WordPress plugin. If your plugin has multiple files, the header should be inside the primary file—in this article we use index.php as our primary file, but many plugins use a file named after the plugin name as their primary file. Location, name, and format The header itself is similar in form and function to other content management systems, such as Drupal's module.info files or Joomla's XML module configurations—it offers a way to store additional information about a plugin in a standardized format. The values can be extended, but the most common header values are listed below: For more information about header blocks, see the WordPress codex at: http://codex.wordpress.org/File_Header. In order for a PHP file to show up in WordPress' Plugins menu: The file must have a .php extension. The file must contain the information header somewhere in it (preferably at the beginning). The file must be either in the /wp-content/plugins directory, or in a subdirectory of the plugins directory. It cannot be more deeply nested. Understanding the Includes When you activate a plugin, the name of the file containing the information header is stored in the WordPress database. Each time a page is requested, WordPress goes through a laundry list of PHP files it needs to load, so activating a plugin ensures that your own files are on that list. To help illustrate this concept, let's break WordPress again. Exercise – parse errors Try the following exercise: Yikes! Your site is now broken. Why did this happen? We introduced errors into the plugin's main file (hello.php), so including it caused PHP and WordPress to choke. Delete the gibberish line from the hello.php file and save to return the plugin back to normal. The parse error only occurs if there is an error in an active plugin. Deactivated plugins are not included by WordPress and therefore their code is not parsed. You can try the same exercise after deactivating the plugin and you'll notice that WordPress does not raise any errors. Bonus for the curious In case you're wondering exactly where and how WordPress stores the information about activated plugins, have a look in the database. Using your MySQL client, you can browse the wp_options table or execute the following query: SELECT option_value FROM wp_options WHERE option_name='active_ plugins'; The active plugins are stored as a serialized PHP hash, referencing the file containing the header. The following is an example of what the serialized hash might contain if you had activated a plugin named "Bad Example". You can use PHP's unserialize() function to parse the contents of this string into a PHP variable as in the following script: <?php $active_plugin_str = 'a:1:{i:0;s:27:"bad-example/bad-example. php";}'; print_r( unserialize($active_plugin_str) ); ?> And here's its output: Array ( [0] => bad-example/bad-example.php )
Read more
  • 0
  • 1
  • 20947
article-image-aspnet-4-social-networking-implementing-complete-messaging-system
Packt
25 Mar 2011
12 min read
Save for later

ASP.NET 4 Social Networking: Implementing a Complete Messaging System

Packt
25 Mar 2011
12 min read
Problem A basic messaging system should be able to manage messages, senders and recipients, folders that contain the messages, and email notifications. In our case, we are going to try and keep things simple where it makes sense to do so, but in one area, we will do things in a more complicated way simply because it will result in less wear and tear on the overall system. This is how the messages will be delivered to the users. Rather than following a standard email messaging system where each person gets a physical copy of a message, we are going to build our system in the same way that the MS Exchange server works. We are going to make one copy of a message and subscribe users to that message. So rather than have 50 messages for 50 recipients, we will have one message and 50 recipient subscriptions. The next problem lies in building a WYSIWYG (what you see is what you get) messaging editor. For this feature, there are many open source WYSIWYG editors; we will use one of those to save us a bit of time. We will be using one of the popular editors—X INHA. This editor can be downloaded for free here at http://xinha.webfactional.com/. You may have seen this editor already as it is widely used across many popular community sites. Design Let's take a look at the design of these features. Messages Messages are the core of any messaging system. Generally, a message would contain details like the sender of the message, receiver of the message, and other metadata like time sent, server from where it was sent, etc. and the message, subject, and body. In our case, the message will contain the sender, subject, body, and the data sent. It will also contain one additional field, i.e. the type of message (message, friend request, and so on). We will need to create a page that allows a user to compose a new message (as seen in the image at the start of this article). This interface should also allow a user to add his/her friends easily rather than force them to remember everyone. Also, this interface should allow a user to quickly snap together some HTML without ever having to look at HTML. This can be accomplished with a WYSIWYG editor. Recipients As we have already discussed that we are going to move some of the complexity away from the message, following a subscription model instead, you will find that most of the complexity of this system lies around the recipient concepts. In this case, the recipient subscription is what will be contained in a folder and will have a read status. With this design, we will remove some of the burden from the database. The overhead of doing this of course means that we now need to manage our data closely, as it is kept in many pieces. A more simple design that would result in more copies of data to be managed would be to create one message for each recipient. This is easier as each message can easily be deleted and moved around without having to worry about the copies of that message of the other recipients. Having said that, if the message is quite large, and more importantly if we were to allow file attachments, all the copies of the messages would be identical for each recipient. This would quickly bloat your database! Solution Now let's take a look at our solution. Implementing the database First let's take a look at what tables are needed: Messages A message will primarily be made up of the subject and its body. In addition to that we will need to know what type of message we are sending so that we can do some more fancy things in the UI down the road. In addition to this, we are going to maintain who owns/created the message at this level. There aren't really any major complexities to note here other than the fact that the Body is made up of a varchar(MAX) data type. If you feel this is too large for your system, feel free to make it anything you are comfortable with. The value you eventually use will drive the message for your system. MessageTypes Message Types allows us to assign a type to our messages. This is purely a lookup table that will allow us to know what the types are during queries. We will keep a list of enums in the code to make the lookups easier from that end. MessageRecipients A message recipient is simply the receiving party to the message. But as we try to minimize the data that we manage in our system, the message recipient is also a very important part of the message. In our case, it is the receiving party as well as all the things that the receiving party does with their subscription of that message. We will use this subscription to denote which folder the receiver is keeping the message in, and whether the receiver has read the message or not. Also, if the receiver chooses to delete the message, he/she can just delete the subscription to a message (unless they are the last subscription, in which case we will delete the message as well). The SQL for this subscription is actually quite straightforward. It tracks a relationship to the message, a relationship to the receiver, which folder the subscription is currently in, and the status of the message for this receiver. MessageRecipientTypes The message recipient type allows us to track the receiver of this message addressed in the TO, CC, or BCC fields. Initially, our interface will only have a TO field. We should add this bit of metadata though just in case we want to expand our capabilities down the road! This is another example of a lookup table that we might need to use in the SQL queries. In our case, we will have an enum defined that maintains this lookup for us on the code side. MessageStatusTypes MessageStatusTypes allows us to track what a recipient is doing with his/her copy of the message, whether they have read the message, replied to the message, and so on. This is primarily so that we can change the UI to refiect its status to the recipient. However, we could also create a dashboard down the road for the senders of the messages to know whether their message was read or not and by whom (think of all the big brother things one could do...but probably should not do!). MessageFolders MessageFolders in our first round of implementation will simply hold copies of new messages in the Inbox and copies of sent messages in the Sent folder. We will also have a trash folder and a spam folder. That said, we always wanted to build a system with the future in mind if it doesn't require a lot of extra work, and so we have also baked in the concept of a user being able to create and manage his/her own folders. Therefore, rather than just see the MessageFolders table as another lookup table, you will see that there is an IsSystem fiag to denote which folders are to be seen system-wide. And you will see an AccountID column for custom folders so that we know who owns which folders. Creating the relationships Once all the tables are created, we can create the relationships. For this set of tables, we have relationships between the following tables: Messages and MessageRecipients Messages and Accounts Messages and MessageTypes MessageRecipients and MessageRecipientTypes MessageRecipients and MessageFolders MessageRecipients and MessageStatusTypes Setting up the data access layer The data access layer in this case is very straightforward. Open up your Fisharoo.edmx file and add all of your new message-oriented tables. Once you save this, you should now have a list of new domain objects in your arsenal (see the previous screenshot). Building repositories With these new tables come some additional repositories. We will create the following repositories. MessageRepository MessageRecipientRepository MessageFolderRepository A detailed creation of repositories is out of the scope of this article. We will create a method for selecting a single entity by ID, a group of entities by their parents, saving entities, and deleting entities. Having said that, there are a couple of methods that have something special in the set of repositories. As we are using message subscriptions, we don't necessarily want to delete recipients haphazardly. We may want to delete a recipient, and if that recipient is the last recipient with a subscription to a message, we may also want to delete the message. On the other end of the spectrum, if we do delete a message, we may also want to remove all the recipient subscriptions. In addition to these different ways of deleting data, we will also run into a scenario where selecting a single entity from our repositories won't be quite good enough. So in this case, we have created an aggregate class that will allow us to select several entities at once for use in our inbox scenarios. MessageRepository When we think of a standard inbox, we know that we need to see the messages that we have, who sent them, when they were sent, and at least the subject of their message. In this case, we have discussed two different entities here. When we think about the fact that we also need to know who they were sent to, we have added a third entity. While we could run three separate queries for this data, it would be better for us to run one query (as we would have done in the old days) and return the data that we need in one shot. What do we do? In this case, we need to create an aggregate. This is a class that contains other entities. We will therefore create a MessageWithRecipient class that will contain the sender's account info, the message, and the recipient. This should provide us with enough data to represent messages in our inbox view later. Before we write any queries, we first need to create the aggregate. //Fisharoo/DataAccess/MessageWithRecipient.cs namespace Fisharoo.DataAccess { public class MessageWithRecipient { public Account Sender { get; set; } public Message Message { get; set; } public MessageRecipient MessageRecipient{ get; set; } } } With this aggregate in place we can now turn our attention to the repository that will get all this data for us. //Fisharoo/DataAccess/Repositories/MessageRepository.cs public List<MessageWithRecipient> GetMessagesByAccountID(Int32 AccountID, Int32 PageNumber, MessageFolders Folder) { List<MessageWithRecipient> result = new List<MessageWithRecipient>(); using(FisharooDataContext dc = conn.GetContext()) { IEnumerable<MessageWithRecipient> messages = (from r in dc.MessageRecipients join m in dc.Messages on r.MessageID equals m.MessageID join a in dc.Accounts on m.SentByAccountID equals a.AccountID where r.AccountID == AccountID && r.MessageFolderID == (int)Folder orderby m.CreateDate descending select new MessageWithRecipient() { Sender = a, Message = m, MessageRecipient = r }).Skip((PageNumber - 1)*10).Take(10); result = messages.ToList(); } return result; } This is a fun method! This method involves selecting a list of our MessageWithRecipient aggregate objects. The LINQ query is joining all the tables that we need and selecting a new instance of the MessageWithRecipient aggregate, that is then populated with the three classes that we need in the aggregate. Additionally, we have introduced some paging logic with the .Skip and .Take methods to produce a subset of the MessageWithRecipient objects. In addition to the selection method above, we also need to discuss the delete method for this repository. As we have the data holding a subscription to our message data, it is important that we first remove all the subscriptions prior to removing the message itself. //Fisharoo/DataAccess/Repositories/MessageRepository.cs public void DeleteMessage(Message message) { using (FisharooDataContext dc = conn.GetContext()) { IEnumerable<MessageRecipient> recipients = dc.MessageRecipients .Where(mr => mr.MessageID == message.MessageID); foreach (MessageRecipient mr in recipients) { dc.MessageRecipients.DeleteObject(mr); } dc.Messages.DeleteObject(message); dc.SaveChanges(); } } This is easily accomplished by retrieving all the MessageRecipients for the needed MessageID from the MessageRecipients in DataContext. Once we have the list, we iterate over each recipient and remove it from DataContext's MessageRecipients list. Finally, we delete the message and save changes. MessageRecipientRepository The message recipient repository is considerably easier. It simply has an altered delete statement to adjust for the fact that if we delete the last subscription to a message, it will amount to deleting the message. //Fisharoo/DataAccess/Repositories/MessageRecipientRepository.cs public void DeleteMessageRecipient(MessageRecipient messageRecipient) { using (FisharooDataContext dc = conn.GetContext()) { dc.MessageRecipients.DeleteObject(dc.MessageRecipients.Where (mr=> mr.MessageRecipientID.Equals (messageRecipient.MessageRecipientID)) .FirstOrDefault()); //if the last recipient was deleted //...also delete the message int RemainingRecipientCount = dc.MessageRecipients.Where(mr => mr.MessageID == messageRecipient.MessageID).Count(); if (RemainingRecipientCount == 0) { dc.Messages.DeleteObject(dc.Messages.Where(m => m.MessageID == messageRecipient.MessageID). FirstOrDefault()); } dc.SaveChanges(); } } In this method, we delete the recipient in question. We then get a count of the remaining recipients for the message, which has the last recipient removed. If that count is zero, then there are no more recipients remaining for that message. In that case we perform a delete on that message and remove it from the system as well.
Read more
  • 0
  • 0
  • 3173

article-image-joomla-16-managing-site-users-access-control
Packt
17 Mar 2011
9 min read
Save for later

Joomla! 1.6: Managing Site Users with Access Control

Packt
17 Mar 2011
9 min read
Joomla! 1.6 First Look A concise guide to everything that's new in Joomla! 1.6.     What's new about the Access Control Levels system? In Joomla! 1.5, a fixed set of user groups was available, ranging from "Public" users (anyone with access to the frontend of the site) to "Super Administrators", allowed to log in to the backend and do anything. The ACL system in Joomla! 1.6 is much more flexible: Instead of fixed user groups with fixed sets of permissions, you can create as many groups as you want and grant the people in those groups any combination of permissions. ACL enables you to control anything users can do on the site: log in, create, edit, delete, publish, unpublish, trash, archive, manage, or administer things. Users are no longer limited to only one group: a user can belong to different groups at the same time. This allows you to give particular users both the set of permissions for one group and another group without having to create a third, combined set of permissions from the ground up. Permissions no longer apply to the whole site as they did in Joomla! 1.5. You can now set permissions for specific parts of the site. Permissions apply to either the whole site, or to specific components, categories, or items (such as a single article). What are the default user groups and permissions? The flexibility of the new ACL system has a downside: it can also get quite complex. The power to create as many user groups as you like, each with very fine-grained sets of permissions assigned to them, means you can easily get entangled in a web of user groups, Joomla! Objects, and permissions. You should carefully plan the combinations of permissions you need to assign to different user groups. Before you change anything in Joomla!, sketch an outline or use mind mapping tools (such as http://bubbl.us) to get an overview of what you want to accomplish through Joomla! ACL: who (which users) should be able to see or do what in which parts of the site? In many cases, you might not need to go beyond the default setup and just use the default users groups and permissions that are already present when you install Joomla! 1.6. So, before we go and find out how you can craft custom user groups and their distinctive sets of permissions, let's have a look at the default Joomla! 1.6 ACL setup. The default site-wide settings In broad terms, the default groups and permissions present in Joomla! 1.6 are much like the ACL system that was available in Joomla! 1.5. To view the default groups and their permissions, go to Site | Global Configuration | Permissions. The Permission Settings screen is displayed, showing a list of User Groups. A user group is a collection of users sharing the same permissions, such as Public, Manager, or Administrator. By default the permission settings of the Public user group are shown; clicking any of the other user group names reveals the settings for that particular group. On the right-hand side of the Permission Settings screen, the generic (site-wide) action permissions for this group are displayed: Site Login, Admin Login, and so on. Actions are the things users are allowed do on the site. For the sample user groups, these action permissions have already been set. Default user groups Let's find out what these default user groups are about. We'll discuss the user groups from the most basic level (Public) to the most powerful (Super Users). Public – the guest group This is the most basic level; anyone visiting your site is considered part of the Public group. Members of the Public group can view the frontend of the site, but they don't have any special permissions. Registered – the user group that can log in Registered users are regular site visitors, except for the fact that they are allowed to log in to the frontend of the site. After they have logged in with their account details, they can view content that may be hidden from ordinary site visitors because the Access level of that content has been set to Registered. This way, Registered users can be presented all kinds of content ordinary (Public) users can't see. Registered users, however, can't contribute content. They're part of the user community, not web team. Author, Editor, Publisher – the frontend content team Authors, Editors, and Publishers are allowed to log in to the frontend, to edit or add articles. There are three types of frontend content contributors, each with their specific permission levels: Authors can create new content for approval by a Publisher or someone higher in rank. They can edit their own articles, but can't edit existing articles created by others. Editors can create new articles and edit existing articles. A Publisher or higher must approve their submissions. Publishers can create, edit, and publish, unpublish, or trash articles in the frontend. They cannot delete content. Manager, Administrator, Super User – the backend administrators Managers, Administrators and Super Users are allowed to log in to the backend to add and manage content and to perform administrative tasks. Managers can do all that Publishers can, but they are also allowed to log in to the backend of the site to create, edit, or delete articles. They can also create and manage categories. They have limited access to administration functions. Administrators can do all that Managers can and have access to more administration functions. They can manage users, edit, or configure extensions and change the site template. They can use manager screens (User Manager, Article Manager, and so on) and can create, delete, edit, and change the state of users, articles, and so on. Super Users can do everything possible in the backend. (In Joomla! 1.5, this user group type was called Super Administrator). When Joomla! is installed, there's always one Super User account created. That's usually the person who builds and customizes the website. In the current example website, you're the Super User. Shop Suppliers and Customers – two sample user groups You'll notice two groups in the Permission Settings screen that we haven't covered yet: Shop Suppliers and Customer. These are added when you install the Joomla! 1.6 sample data. These aren't default user groups; they are used in the sample Fruit Shop site to show how you can create customized groups. Are there also sample users available? As there are user groups present in the sample data, you might expect there are also sample users. This is not the case. There are no (sample) users assigned to the sample user groups. There's just one user available after you've installed Joomla!— you. You can view your details by navigating to Users | User Manager. You're taken to the User Manager: Users screen: Here you can see that your name is Super User, your user name is admin (unless you've changed this yourself when setting up your account), and you're part of the user group called Super Users. There's also a shortcut available to take you to your own basic user settings: click on Site | My Profile or—even faster—just click on the Edit Profile shortcut in the Control Panel. However, you can't manage user permissions here; the purpose of the My Profile screen is only to manage basic user settings. Action Permissions: what users can do We've now seen what types of users are present in the default setup of Joomla! 1.6. The action permissions that you can grant these user groups—things they can do on the site—are shown per user group in the Site | Global Configuration | Permissions screen. Click on any of the user group names to see the permission settings for that group: You'll also find these permissions (such as Site Login, Create, Delete, Edit) on other places in the Joomla! interface: after all, you don't just apply permissions on a site-wide basis (as you could in previous versions of Joomla!), but also on the level of components, categories, or individual items. To allow or deny users to do things, each of the available actions can be set to Allowed or Denied for a specific user group. If the permission for an action isn't explicitly allowed or denied, it is Not Set. Permissions are inherited You don't have to set each and every permission on every level manually: permissions are inherited between groups. That is, a child user group automatically gets the permissions set for its parent. Wait a minute—parents, children, inheritance ... how does that work? To understand these relationships, let's have a look at the overview of user groups in the Permission Settings screen. This shows all available user groups (I've edited this screen image a little to be able to show all the user groups in one column): You'll notice that all user group names are displayed indented, apart from Public. This indicates the permissions hierarchy: Public is the parent group, Manager (indented one position) is a child of Public, Administrator (indented two positions) is a child of Manager. Permissions for a parent group are automatically inherited by all child groups (unless these permissions are explicitly set to Allowed or Denied to "break" the inheritance relationship). In other words: a child group can do anything a parent group can do—and more, as it is a child and therefore has its own specific permissions set. For example, as Authors are children of the Registered group, they inherit the permissions of the Registered group (that is, the permission to log in to the frontend of the site). Apart from that, Authors have their own specific permissions added to the permissions of the Registered group. Setting an action to Denied is very powerful: you can't allow an action for a lower level in the permission hierarchy if it is set to Denied higher up in the hierarchy. So, if an action is set to Denied for a higher group, this action will be inherited all the way down the permissions "tree" and will always be denied for all lower levels—even if you explicitly set the lower level to Allowed.  
Read more
  • 0
  • 0
  • 2036