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 - Web Development

1797 Articles
article-image-getting-started-freeradius
Packt
07 Sep 2011
6 min read
Save for later

Getting Started with FreeRADIUS

Packt
07 Sep 2011
6 min read
After FreeRADIUS has been installed it needs to be configured for our requirements. This article by Dirk van der Walt, author of FreeRADIUS Beginner's Guide, will help you to get familiar with FreeRADIUS. It assumes that you already know the basics of the RADIUS protocol. In this article we shall: Perform a basic configuration of FreeRADIUS and test it Discover ways of getting help Learn the recommended way to configure and test FreeRADIUS See how everything fits together with FreeRADIUS (For more resources on this subject, see here.) Before you startThis article assumes that you have a clean installation of FreeRADIUS. You will need root access to edit FreeRADIUS configuration files for the basic configuration and testing. A simple setup We start this article by creating a simple setup of FreeRADIUS with the following: The localhost defined as an NAS device (RADIUS client) Alice defined as a test user After we have defined the client and the test user, we will use the radtest program to fill the role of a RADIUS client and test the authentication of Alice. Time for action – configuring FreeRADIUS FreeRADIUS is set up by modifying configuration files. The location of these files depends on how FreeRADIUS was installed: If you have installed the standard FreeRADIUS packages that are provided with the distribution, it will be under /etc/raddb on CentOS and SLES. On Ubuntu it will be under /etc/freeradius. If you have built and installed FreeRADIUS from source using the distribution's package management system it will also be under /etc/raddb on CentOS and SLEs. On Ubuntu it will be under /etc/freeradius. If you have compiled and installed FreeRADIUS using configure, make, make install it will be under /usr/local/etc/raddb. The following instructions assume that the FreeRADIUS configuration directory is your current working directory: Ensure that you are root in order to be able to edit the configuration files. FreeRADIUS includes a default client called localhost. This client can be used by RADIUS client programs on the localhost to help with troubleshooting and testing. Confirm that the following entry exists in the clients.conf file: client localhost { ipaddr = 127.0.0.1 secret = testing123 require_message_authenticator = no nastype = other} Define Alice as a FreeRADIUS test user. Add the following lines at the top of the users file. Make sure the second and third lines are indented by a single tab character: "alice" Cleartext-Password := "passme" Framed-IP-Address = 192.168.1.65, Reply-Message = "Hello, %{User-Name}" Start the FreeRADIUS server in debug mode. Make sure that there is no other instance running by shutting it down through the startup script. We assume Ubuntu in this case. $> sudo su#> /etc/init.d/freeradius stop#> freeradius -X You can also use the more brutal method of kill -9 $(pidof freeradius) or killall freeradius on Ubuntu and kill -9 $(pidof radius) or killall radiusd on CentOS and SLES if the startup script does not stop FreeRADIUS. Ensure FreeRADIUS has started correctly by confirming that the last line on your screen says the following: Ready to process requests. If this did not happen, read through the output of the FreeRADIUS server started in debug mode to see what problem was identified and a possible location thereof. Authenticate Alice using the following command: $> radtest alice passme 127.0.0.1 100 testing123 The debug output of FreeRADIUS will show how the Access-Request packet arrives and how the FreeRADIUS server responds to this request. Radtest will also show the response of the FreeRADIUS server: Sending Access-Request of id 17 to 127.0.0.1 port 1812 User-Name = "alice" User-Password = "passme" NAS-IP-Address = 127.0.1.1 NAS-Port = 100rad_recv: Access-Accept packet from host 127.0.0.1 port 1812,id=147, length=40 Framed-IP-Address = 192.168.1.65 Reply-Message = "Hello, alice" What just happened? We have created a test user on the FreeRADIUS server. We have also used the radtest command as a client to the FreeRADIUS server to test authentication. Let's elaborate on some interesting and important points. Configuring FreeRADIUS Configuration of the FreeRADIUS server is logically divided into different files. These files are modified to configure a certain function, component, or module of FreeRADIUS. There is, however, a main configuration file that sources the various sub-files. This file is called radiusd.conf. The default configuration is suitable for most installations. Very few changes are required to make FreeRADIUS useful in your environment. Clients Although there are many files inside the FreeRADIUS server configuration directory, only a few require further changes. The clients.conf file is used to define clients to the FreeRADIUS server. Before an NAS can use the FreeRADIUS server it has to be defined as a client on the FreeRADIUS server. Let's look at some points about client definitions. Sections A client is defined by a client section. FreeRADIUS uses sections to group and define various things. A section starts with a keyword indicating the section name. This is followed by enclosing brackets. Inside the enclosing brackets are various settings specific to that section. Sections can also be nested. Sometimes the section's keyword is followed by a single word to differentiate between sections of the same type. This allows us to have different client entries in clients.conf. Each client has a short name to distinguish it from the others. The clients.conf file is not the only file where client sections can be defined although it is the usual and most logical place. The following image shows nested client definitions inside a server section: (Move the mouse over the image to enlarge.) Client identification The FreeRADIUS server identifies a client by its IP Address. If an unknown client sends a request to the server, the request will be silently ignored. Shared secret The client and server also require to have a shared secret, which will be used to encrypt and decrypt certain AVPs. The value of the User-Password AVP is encrypted using this shared secret. When the shared secret differs between the client and server, FreeRADIUS server will detect it and warn you when running in debug mode: Failed to authenticate the user. WARNING: Unprintable characters in the password. Double-check the shared secret on the server and the NAS! Message-Authenticator When defining a client you can enforce the presence of the Message-Authenticator AVP in all the requests. Since we will be using the radtest program, which does not include it, we disable it for localhost by setting require_message_authenticator to no. Nastype The nastype is set to other. The value of nastype will determine how the checkrad Perl script will behave. Checkrad is used to determine if a user is already using resources on an NAS. Since localhost does not have this function or need we will define it as other. Common errors If the server is down or the packets from radtest cannot reach the server because of a firewall between them, radtest will try three times and then give up with the following message: radclient: no response from server for ID 133 socket 3 If you run radtest as a normal user it may complain about not having access to the FreeRADIUS dictionary file. This is required for normal operations. The way to solve this is either to change the permissions on the reported file or to run radtest as root.
Read more
  • 0
  • 0
  • 5073

article-image-how-add-static-material-course-moodle
Packt
06 Sep 2011
7 min read
Save for later

How to Add Static Material to a Course in Moodle

Packt
06 Sep 2011
7 min read
  (For more resources on Moodle, see here.)   Kinds of static course material that can be added Static course material is added from the Add a resource drop-down menu. Using this menu, you can create: Web pages Links to anything on the Web Files A label that displays any text or image Multimedia   Adding links On your Moodle site, you can show content from anywhere on the Web by using a link. You can also link to files that you've uploaded into your course. By default, this content appears in a frame within your course. You can also choose to display it in a new window. When using content from outside sites, you need to consider the legality and reliability of using the link. Is it legal to display the material on your Moodle site? Will the material still be there when your course is running? In this example, I've linked to an online resource from the BBC, which is a fairly reliable source: Remember that the bottom of the window displays Window Settings, so you can choose to display this resource in its own window. You can also set the size of the window. You may want to make it appear in a smaller window, so that it does not completely obscure the window of your Moodle site. This will make it clearer to the student that he or she has opened a new window. To add a link to a resource on the Web: Log in to your course as a Teacher or Site Administrator. In the upper-right corner of the page, if you see a button that reads, Turn editing on, click on this button. If it reads Turn editing off, then you do not need to click on this button. (You will also find this button in the Settings menu on the leftmost side of the page.) From the Add a resource... drop-down menu, select URL. Moodle displays the Adding a new URL page. Enter a Name for the link. This is the name that people will see on the home page of your course. Enter a Description for the link. When the student sees the course's home page, they will see the Name and not the Description. However, whenever this resource is selected from the Navigation bar, the Description will be displayed. Here is a link as it appears on the home page of a course: Here is the same link, as it appears when selected from the Navigation bar: In the External URL field, enter the Web address for this link. From the Display drop-down menu, select the method that you want Moodle to use when displaying the linked page. Embed will insert the linked page into a Moodle page. Your students will see the Navigation bar, any blocks that you have added to the course and navigation links across the top of the page, just like when they view any other page in Moodle. The center of the page will be occupied by the linked page. Open will take the student away from your site, and open the linked page in the window that was occupied by Moodle. In pop-up will launch a new window, containing the linked page on top of the Moodle page. Automatic will make Moodle choose the best method for displaying the linked page. The checkboxes for Display URL name and Display URL description will affect the display of the page, only if Embed is chosen as the display method. If selected, the Name of the link will be displayed above the embedded page, and the Description will be displayed below the embedded page. Under Options, the ShowAdvanced button will display fields that allow you to set the size of the popup window. If you don't select In pop-up as the display method, these fields have no effect. Under Parameters, you can add parameters to the link. In a Web link, a parameter would add information about the course or student to the link. If you have Web programming experience, you might take advantage of this feature. For more about passing parameters in URLs, see http://en.wikipedia.org/wiki/Query_string. Under Common Module Settings, the Visible setting determines if this resource is visible to students. Teachers and site Administrators can always see the resource. Setting this to Hide will completely hide the resource. Teachers can hide some resources and activities at the beginning of a course, and reveal them as the course progresses. Show/Hide versus Restrict availability If you want a resource to be visible, but not available, then use the Restrict Availability settings further down on the page. Those settings enable you to have a resource's name and its description appear, but still make the resource unavailable. You might want to do this for resources that will be used later in a course, when you don't want the student to work ahead of the syllabus. The ID number field allows you to enter an identifier for this resource, which will appear in the Gradebook. If you export grades from the Gradebook and then import them into an external database, you might want the course ID number here to match the ID number that you use in that database. The Restrict Availability settings allow you to set two kinds of conditions that will control whether this resource is available to the student. The Accessible from and Accessible until settings enable you to set dates for when this resource will be available. The Grade condition setting allows you to specify the grade that a student must achieve in another Activity in this course, before being able to access this Resource. The setting for Before activity is available determines if the Resource will be visible while it is unavailable. If it is visible but unavailable, Moodle will display the conditions needed to make it available (achieve a grade, wait for a date, and so on.). Click on one of the Save buttons at the bottom of the page to save your work.   Adding pages Under the Add a resource drop-down menu, select Page to add a Web page to a course. A link to the page that you create will appear on the course's home page. Moodle's HTML editor When you add a Page to your course, Moodle displays a Web page editor. This editor is based on an open source web page editor called TinyMCE. You can use this editor to compose a web page for your course. This page can contain almost anything that a web page outside of Moodle can contain. Pasting text into a Moodle page Many times, we prefer to write text in our favorite word processor instead of writing it in Moodle. Or we may find text that we can legally copy and paste into a Moodle page, somewhere else. Moodle's text editor does allow you to do this. To paste text into a page, you can just use the appropriate keyboard shortcut. Try Ctrl + V for Windows PCs and Apple + V for Macintoshes. If you use this method, the format of the text will be preserved. To paste plain text, without the format of the original text, click on the Paste as Plain Text icon, as shown below: When you paste text from a Microsoft Word document into a web page, it usually includes a lot of non-standard HTML code. This code doesn't work well in all browsers, and makes it more difficult to edit the HTML code in your page. Many advanced web page editors, such as AdobeDreamWeaver, have the ability to clean up Word HTML code. Moodle's web page editor can also clean up Word HTML code. When pasting text that was copied from Word, use the Paste from Word icon, as shown in the image below. This will strip out most of Word's non-standard HTML code.  
Read more
  • 0
  • 0
  • 3726

article-image-yii-11-using-zii-components
Packt
05 Sep 2011
10 min read
Save for later

Yii 1.1: Using Zii Components

Packt
05 Sep 2011
10 min read
  (For more resources on this subject, see here.) Introduction Yii have a useful library called Zii. It's bundled with framework and includes some classes aimed to make the developer's life easier. Its most handy components are grids and lists which allow you to build data in both the admin and user parts of a website in a very fast and efficient way. In this article you'll learn how to use and adjust these components to fit your needs. Also you'll learn about data providers. They are part of the core framework, not Zii, but since they are used extensively with grids and lists, we'll review them here. We'll use Sakila sample database version 0.8 available from official MySQL website: http://dev.mysql.com/doc/sakila/en/sakila.html. Using data providers Data providers are used to encapsulate common data model operations such as sorting, pagination and querying. They are used with grids and lists extensively. Because both widgets and providers are standardized, you can display the same data using different widgets and you can get data for a widget from various providers. Switching providers and widgets is relatively transparent. Currently there are CActiveDataProvider, CArrayDataProvider, and CSqlDataProvider implemented to get data from ActiveRecord models, arrays, and SQL queries respectively. Let's try all these providers to fill a grid with data. Getting ready Create a new application using yiic webapp as described in the official guide. Download the Sakila database from http://dev.mysql.com/doc/sakila/en/sakila.html and execute the downloaded SQLs: first schema then data. Configure the DB connection in protected/config/main.php. Use Gii to create a model for the film table. How to do it... Let's start with a view for a grid controller. Create protected/views/grid/index.php: <?php $this->widget('zii.widgets.grid.CGridView', array('dataProvider' => $dataProvider,))?> Then create a protected/controllers/GridController.php: <?phpclass GridController extends Controller{ public function actionAR() { $dataProvider = new CActiveDataProvider('Film', array( 'pagination'=>array( 'pageSize'=>10, ), 'sort'=>array( 'defaultOrder'=> array('title'=>false), ) )); $this->render('index', array( 'dataProvider' => $dataProvider, )); } public function actionArray() { $yiiDevelopers = array( array( 'name'=>'Qiang Xue', 'id'=>'2', 'forumName'=>'qiang', 'memberSince'=>'Jan 2008', 'location'=>'Washington DC, USA', 'duty'=>'founder and project lead', 'active'=>true, ), array( 'name'=>'Wei Zhuo', 'id'=>'3', 'forumName'=>'wei', 'memberSince'=>'Jan 2008', 'location'=>'Sydney, Australia', 'duty'=>'project site maintenance and development', 'active'=>true, ), array( 'name'=>'Sebastián Thierer', 'id'=>'54', 'forumName'=>'sebas', 'memberSince'=>'Sep 2009', 'location'=>'Argentina', 'duty'=>'component development', 'active'=>true, ), array( 'name'=>'Alexander Makarov', 'id'=>'415', 'forumName'=>'samdark', 'memberSince'=>'Mar 2010', 'location'=>'Russia', 'duty'=>'core framework development', 'active'=>true, ), array( 'name'=>'Maurizio Domba', 'id'=>'2650', 'forumName'=>'mdomba', 'memberSince'=>'Aug 2010', 'location'=>'Croatia', 'duty'=>'core framework development', 'active'=>true, ), array( 'name'=>'Y!!', 'id'=>'1644', 'forumName'=>'Y!!', 'memberSince'=>'Aug 2010', 'location'=>'Germany', 'duty'=>'core framework development', 'active'=>true, ), array( 'name'=>'Jeffrey Winesett', 'id'=>'15', 'forumName'=>'jefftulsa', 'memberSince'=>'Sep 2010', 'location'=>'Austin, TX, USA', 'duty'=>'documentation and marketing', 'active'=>true, ), array( 'name'=>'Jonah Turnquist', 'id'=>'127', 'forumName'=>'jonah', 'memberSince'=>'Sep 2009 - Aug 2010', 'location'=>'California, US', 'duty'=>'component development', 'active'=>false, ), array( 'name'=>'István Beregszászi', 'id'=>'1286', 'forumName'=>'pestaa', 'memberSince'=>'Sep 2009 - Mar 2010', 'location'=>'Hungary', 'duty'=>'core framework development', 'active'=>false, ), ); $dataProvider = new CArrayDataProvider( $yiiDevelopers, array( 'sort'=>array( 'attributes'=>array('name', 'id', 'active'), 'defaultOrder'=>array('active' => true, 'name' => false), ), 'pagination'=>array( 'pageSize'=>10, ), )); $this->render('index', array( 'dataProvider' => $dataProvider, )); } public function actionSQL() { $count=Yii::app()->db->createCommand('SELECT COUNT(*) FROM film')->queryScalar(); $sql='SELECT * FROM film'; $dataProvider=new CSqlDataProvider($sql, array( 'keyField'=>'film_id', 'totalItemCount'=>$count, 'sort'=>array( 'attributes'=>array('title'), 'defaultOrder'=>array('title' => false), ), 'pagination'=>array( 'pageSize'=>10, ), )); $this->render('index', array( 'dataProvider' => $dataProvider, )); }} Now run grid/aR, grid/array and grid/sql actions and try using the grids. How it works... The view is pretty simple and stays the same for all data providers. We are calling the grid widget and passing the data provider instance to it. Let's review actions one by one starting with actionAR: $dataProvider = new CActiveDataProvider('Film', array( 'pagination'=>array( 'pageSize'=>10, ), 'sort'=>array( 'defaultOrder'=>array('title'=>false), ))); CActiveDataProvider works with active record models. Model class is passed as a first argument of class constructor. Second argument is an array that defines class public properties. In the code above, we are setting pagination to 10 items per page and default sorting by title. Note that instead of using a string we are using an array where keys are column names and values are true or false. true means order is DESC while false means that order is ASC. Defining the default order this way allows Yii to render a triangle showing sorting direction in the column header. In actionArray we are using CArrayDataProvider that can consume any array. $dataProvider = new CArrayDataProvider($yiiDevelopers, array( 'sort'=>array( 'attributes'=>array('name', 'id', 'active'), 'defaultOrder'=>array('active' => true, 'name' => false), ), 'pagination'=>array( 'pageSize'=>10, ),)); First argument accepts an associative array where keys are column names and values are corresponding values. Second argument accepts an array with the same options as in CActiveDataProvider case. In actionSQL, we are using CSqlDataProvider that consumes the SQL query and modifies it automatically allowing pagination. First argument accepts a string with SQL and a second argument with data provider parameters. This time we need to supply calculateTotalItemCount with total count of records manually. For this purpose we need to execute the extra SQL query manually. Also we need to define keyField since the primary key of this table is not id but film_id. To sum up, all data providers are accepting the following properties: pagination CPagination object or an array of initial values for new instance of CPagination. sort CSort object or an array of initial values for new instance of CSort. totalItemCount We need to set this only if the provider, such as CsqlDataProvider, does not implement the calculateTotalItemCount method. There's more... You can use data providers without any special widgets. Replace protected/views/grid/ index.php content with the following: <?php foreach($dataProvider->data as $film):?> <?php echo $film->title?><?php endforeach?> <?php $this->widget('CLinkPager',array( 'pages'=>$dataProvider->pagination))?> Further reading To learn more about data providers refer to the following API pages:   http://www.yiiframework.com/doc/api/CDataProvider http://www.yiiframework.com/doc/api/CActiveDataProvider http://www.yiiframework.com/doc/api/CArrayDataProvider http://www.yiiframework.com/doc/api/CSqlDataProvider http://www.yiiframework.com/doc/api/CSort http://www.yiiframework.com/doc/api/CPagination Using grids Zii grids are very useful to quickly create efficient application admin pages or any pages you need to manage data on. Let's use Gii to generate a grid, see how it works, and how we can customize it. Getting ready Carry out the following steps: Create a new application using yiic webapp as described in the official guide. Download the Sakila database from http://dev.mysql.com/doc/sakila/en/sakila.html. Execute the downloaded SQLs: first schema then data. Configure the DB connection in protected/config/main.php. Use Gii to create models for customer, address, and city tables. How to do it... Open Gii, select Crud Generator, and enter Customer into the Model Class field. Press Preview and then Generate. Gii will generate a controller in protected/controllers/CustomerController.php and a group of views under protected/views/customer/. Run customer controller and go to Manage Customer link. After logging in you should see the grid generated: How it works... Let's start with the admin action of customer controller: public function actionAdmin(){ $model=new Customer('search'); $model->unsetAttributes(); // clear any default values if(isset($_GET['Customer'])) $model->attributes=$_GET['Customer']; $this->render('admin',array( 'model'=>$model, ));} Customer model is created with search scenario, all attribute values are cleaned up, and then filled up with data from $_GET. On the first request $_GET is empty but when you are changing the page, or filtering by first name attribute using the input field below the column name, the following GET parameters are passed to the same action via an AJAX request: Customer[address_id] =Customer[customer_id] =Customer[email] =Customer[first_name] = alexCustomer[last_name] =Customer[store_id] =Customer_page = 2ajax = customer-grid Since scenario is search, the corresponding validation rules from Customer::rules are applied. For the search scenario, Gii generates a safe rule that allows to mass assigning for all fields: array('customer_id, store_id, first_name, last_name, email, address_id, active, create_date, last_update', 'safe','on'=>'search'), Then model is passed to a view protected/views/customer/admin.php. It renders advanced search form and then passes the model to the grid widget: <?php $this->widget('zii.widgets.grid.CGridView', array( 'id'=>'customer-grid', 'dataProvider'=>$model->search(), 'filter'=>$model, 'columns'=>array( 'customer_id', 'store_id', 'first_name', 'last_name', 'email', 'address_id', /* 'active', 'create_date', 'last_update', */ array( 'class'=>'CButtonColumn', ), ),)); ?> Columns used in the grid are passed to columns. When just a name is passed, the corresponding field from data provider is used. Also we can use custom column represented by a class specified. In this case we are using CButtonColumn that renders view, update and delete buttons that are linked to the same named actions and are passing row ID to them so action can be done to a model representing specific row from database. filter property accepts a model filled with data. If it's set, a grid will display multiple text fields at the top that the user can fill to filter the grid. The dataProvider property takes an instance of data provider. In our case it's returned by the model's search method : public function search(){ // Warning: Please modify the following code to remove attributes that // should not be searched. $criteria=new CDbCriteria; $criteria->compare('customer_id',$this->customer_id); $criteria->compare('store_id',$this->store_id); $criteria->compare('first_name',$this->first_name,true); $criteria->compare('last_name',$this->last_name,true); $criteria->compare('email',$this->email,true); $criteria->compare('address_id',$this->address_id); $criteria->compare('active',$this->active); $criteria->compare('create_date',$this->create_date,true); $criteria->compare('last_update',$this->last_update,true); return new CActiveDataProvider(get_class($this), array( 'criteria'=>$criteria, ));} This method is called after the model was filled with $_GET data from the filtering fields so we can use field values to form the criteria for the data provider. In this case all numeric values are compared exactly while string values are compared using partial match.
Read more
  • 0
  • 0
  • 4803
Visually different images

article-image-plone-4-development-understanding-zope-security
Packt
30 Aug 2011
6 min read
Save for later

Plone 4 Development: Understanding Zope Security

Packt
30 Aug 2011
6 min read
Security primitives Zope's security is declarative: views, actions, and attributes on content objects are declared to be protected by permissions. Zope takes care of verifying that the current user has the appropriate access rights for a resource. If not, an AccessControl.Unauthorized exception will be raised. This is caught by an error handler which will either redirect the user to a login screen or show an access denied error page. Permissions are not granted to users directly. Instead, they are assigned to roles. Users can be given any number of roles, either site-wide, or in the context of a particular folder, in which case they are referred to as local roles. Global and local roles can also be assigned to groups, in which case all users in that group will have the particular role. (In fact, Zope considers users and groups largely interchangeable, and refers to them more generally as principals.) This makes security settings much more flexible than if they were assigned to individual users. Users and groups Users and groups are kept in user folders, which are found in the ZMI with the name acl_users. There is one user folder at the root of the Zope instance, typically containing only the default Zope-wide administrator that is created by our development buildout the first time it is run. There is also an acl_users folder inside Plone, which manages Plone's users and groups. Plone employs the Pluggable Authentication Service (PAS), a particularly flexible kind of user folder. In PAS, users, groups, their roles, their properties, and other security-related policy are constructed using various interchangeable plugins. For example, an LDAP plugin could allow users to authenticate against an LDAP repository. In day-to-day administration, users and groups are normally managed from Plone's Users and Groups control panel. Permissions Plone relies on a large number of permissions to control various aspects of its functionality. Permissions can be viewed from the Security tab in the ZMI, which lets us assign permissions to roles at a particular object. Note that most permissions are set to Acquire—the default—meaning that they cascade down from the parent folder. Role assignments are additive when permissions are set to acquire. Sometimes, it is appropriate to change permission settings at the root of the Plone site (which can be done using the rolemap.xml GenericSetup import step—more on that follows), but managing permissions from the Security tab anywhere else is almost never a good idea. Keeping track of which security settings are made where in a complex site can be a nightmare. Permissions are the most granular piece of the security puzzle, and can be seen as a consequence of a user's roles in a particular context. Security-aware code should almost always check permissions, rather than roles, because roles can change depending on the current folder and security policy of the site, or even based on an external source such as an LDAP or Active Directory repository. Permissions can be logically divided into three main categories: Those that relate to basic content operations, such as View and Modify portal content. These are used by almost all content types, and defined as constants in the module Products.CMFCore.permissions. Core permissions are normally managed by workflow. Those that control the creation of particular types of content, such as ATContentTypes: Add Image. These are usually set at the Plone site root to apply to the whole site, but they may be managed by workflow on folders. Those that control site-wide policy. For example, the Portlets: Manage portlets permission is usually given to the Manager and Site Administrator roles, because this is typically an operation that only the site's administrator will need to perform. These permissions are usually set at the site root and acquired everywhere else. Occasionally, it may be appropriate to change them here. For example, the Add portal member permission controls whether anonymous users can add themselves (that is, "join" the site) or not. Note that there is a control panel setting for this, under Security in Site Setup. Developers can create new permissions when necessary, although they are encouraged to reuse the ones in Products.CMFCore.permissions if possible. The most commonly used permissions are: Permission Constant Zope Toolkit name Controls Access contents information AccessContents Information zope2.AccessContents Information Low-level Zope permission controlling access to objects View View zope2.View Access to the main view of a content object List folder contents ListFolderContents cmf.ListFolderContents Ability to view folder listings Modify portal content ModifyPortalContent cmf.ModifyPortalContent Edit operations on content Change portal events N/A N/A Modification of the Event content type (largely a historical accident) Manage portal ManagePortal cmf.ManagePortal Operations typically restricted to the Manager role. Request review RequestReview cmf.RequestReview Ability to submit content for review in many workflows. Review portal content ReviewPortalContent cmf.ReviewPortalContent Ability to approve or reject items submitted for review in many workflows. Add portal content AddPortalContent cmf.AddPortalContent add new content in a folder. Note that most content types have their own "add" permissions. In this case, both this permission and the type-specific permission are required. The Constant column in the preceding table refers to constants defined in Products. CMFCore.permissions. The Zope Toolkit name column lists the equivalent names found in ZCML files in packages such as Products.CMFCore, Products.Five and (at least from Zope 2.13), AccessControl. They contain directives such as: <permission id="zope2.View" title="View" /> This is how permissions are defined in the Zope Toolkit. Custom permissions can also be created in this way. Sometimes, we will use ZCML directives which expect a permission attribute, such as: <browser:page name="some-view" class=".someview.SomeView" for="*" permission="zope2.View" /> The permission attribute here must be a Zope Toolkit permission ID. The title of the <permission /> directive is used to map the Zope 2-style permissions (which are really just strings) to Zope Toolkit permission IDs. To declare that a particular view or other resource defined in ZCML should not be subject to security checks, we can use the special permission zope.Public.
Read more
  • 0
  • 0
  • 1711

article-image-plone-4-development-creating-custom-workflow
Packt
30 Aug 2011
7 min read
Save for later

Plone 4 Development: Creating a Custom Workflow

Packt
30 Aug 2011
7 min read
Professional Plone 4 Development Build robust, content-centric web applications with Plone 4.        Keeping control with workflow As we have alluded to before, managing permissions directly anywhere other than the site root is usually a bad idea. Every content object in a Plone site is subject to security, and will in most cases inherit permission settings from its parent. If we start making special settings in particular folders, we will quickly lose control. However, if settings are always acquired, how can we restrict access to particular folders or prevent authors from editing published content whilst still giving them rights to work on items in a draft state? The answer to both of these problems is workflow. Workflows are managed by the portal_workflow tool. This controls a mapping of content types to workflows definitions, and sets a default workflow for types not explicitly mapped. The workflow tool allows a workflow chain of multiple workflows to be assigned to a content type. Each workflow is given its own state variable. Multiple workflows can manage permissions concurrently. Plone's user interface does not explicitly support more than one workflow, but can be used in combination with custom user interface elements to address complex security and workflow requirements. The workflow definitions themselves are objects found inside the portal_workflow tool, under the Contents tab. Each definition consists of states, such as private or published, and transitions between them. Transitions can be protected by permissions or restricted to particular roles. Although it is fairly common to protect workflow transitions by role, this is not actually a very good use of the security system. It would be much more sensible to use an appropriate permission. The exception is when custom roles are used solely for the purpose of defining roles in a workflow. Some transitions are automatic, which means that they will be invoked as soon as an object enters a state that has this transition as a possible exit (that is, provided the relevant guard conditions are met). More commonly, transitions are invoked following some user action, normally through the State drop-down menu in Plone's user interface. It is possible to execute code immediately before or after a transition is executed. States may be used simply for information purposes. For example, it is useful to be able to mark a content object as "published" and be able to search for all published content. More commonly, states are also used to control content item security. When an object enters a particular state, either its initial state, when it is first created, or a state that is the result of a workflow transition, the workflow tool can set a number of permissions according to a predefined permissions map associated with the target state. The permissions that are managed by a particular workflow are listed under the Permissions tab on the workflow definition: These permissions are used in a permission map for each state: If you change workflow security settings, your changes will not take effect immediately, since permissions are only modified upon workflow transitions. To synchronize permissions with the current workflow definitions, use the Update security settings button at the bottom of the Workflows tab of the portal_workflow tool. Note that this can take a long time on large sites, because it needs to find all content items using the old settings and update their permissions. If you use the Types control panel in Plone's Site Setup to change workflows, this reindexing happens automatically. Workflows can also be used to manage role-to-group assignments in the same way they can be used to manage role-to-permission assignments. This feature is rarely used in Plone, however. All workflows manage a number of workflow variables, whose values can change with transitions and be queried through the workflow tool. These are rarely changed, however, and Plone relies on a number of the default ones. These include the previous transition (action), the user ID of the person who performed that transition (actor), any associated comments (comments), the date/time of the last transition (time), and the full transition history (review_history). Finally, workflows can define work lists, which are used by Plone's Review list portlet to show pending tasks for the current user. A work list in effect performs a catalog search using the workflow's state variable. In Plone, the state variable is always called review_state. The workflow system is very powerful, and can be used to solve many kinds of problems where objects of the same type need to be in different states. Learning to use it effectively can pay off greatly in the long run. Interacting with workflow in code Interacting with workflow from our own code is usually straightforward. To get the workflow state of a particular object, we can do: from Products.CMFCore.utils import getToolByName wftool = getToolByName(context, 'portal_workflow') review_state = wftool.getInfoFor(context, 'review_state') However, if we are doing a search using the portal_catalog tool, the results it returns has the review state as metadata already: from Products.CMFCore.utils import getToolByName catalog = getToolByName(context, 'portal_catalog') for result in catalog(dict( portal_type=('Document', 'News Item',), review_state=('published', 'public', 'visible',), )): review_state = result.review_state # do something with the review_state To change the workflow state of an object, we can use the following line of code: wftool.doActionFor(context, action='publish') The action here is the name of a transition, which must be available to the current user, from current state of context. There is no (easy) way to directly specify the target state. This is by design: recall that transitions form the paths between states, and may involve additional security restrictions or the triggering of scripts. Again, the Doc tab for the portal_workflow tool and its sub-objects (the workflow definitions and their states and transitions) should be your first point of call if you need more detail. The workflow code can be found in Products.CMFCore.WorkflowTool and Products.DCWorkflow. Installing a custom workflow It is fairly common to create custom workflows when building a Plone website. Plone ships with several useful workflows, but security and approvals processes tend to differ from site to site, so we will often find ourselves creating our own workflows. Workflows are a form of customization. We should ensure they are installable using GenericSetup. However, the workflow XML syntax is quite verbose, so it is often easier to start from the ZMI and export the workflow definition to the filesystem. Designing a workflow for Optilux Cinemas It is important to get the design of a workflow policy right, considering the different roles that need to interact with the objects, and the permissions they should have in the various states. Draft content should be visible to cinema staff, but not customers, and should go through review before being published. The following diagram illustrates this workflow: This workflow will be made the default, and should therefore apply to most content. However, we will keep the standard Plone policy of omitting workflow for the File and Image types. This means that permissions for content items of these types will be acquired from the Folder in which they are contained, making them simpler to manage. In particular, this means it is not necessary to separately publish linked files and embedded images when publishing a Page. Because we need to distinguish between logged-in customers and staff members, we will introduce a new role called StaffMember. This role will be granted View permission by default for all items in the site, much like a Manager or Site Administrator user is by default (although workflow may override this). We will let the Site Administrator role represent site administrators, and the Reviewer role represent content reviewers, as they do in a default Plone installation. We will also create a new group, Staff, which is given the StaffMember role. Among other things, this will allow us to easily grant the Reader, Editor and Contributor role in particular folders to all staff from the Sharing screen. The preceding workflow is designed for content production and review. This is probably the most common use for workflow in Plone, but it is by no means the only use case. For example, the author once used workflows to control the payment status on an Invoice content type. As you become more proficient with the workflow engine, you will find that it is useful in a number of scenarios.
Read more
  • 0
  • 0
  • 1936

article-image-professional-plone-4-development-developing-site-strategy
Packt
26 Aug 2011
9 min read
Save for later

Professional Plone 4 Development: Developing a Site Strategy

Packt
26 Aug 2011
9 min read
  Professional Plone 4 Development Build robust, content-centric web applications with Plone 4.         Read more about this book       (For more resources on Plone, see here.) Creating a policy package Our policy package is just a package that can be installed as a Plone add-on. We will use a GenericSetup extension profile in this package to turn a standard Plone installation into one that is configured to our client's needs. We could have used a full-site GenericSetup base profile instead, but by using a GenericSetup extension profile we can avoid replicating the majority of the configuration that is done by Plone. We will use ZopeSkel to create an initial skeleton for the package, which we will call optilux.policy, adopting the optilux.* namespace for all Optilux-specific packages. In your own code, you should of course use a different namespace. It is usually a good idea to base this on the owning organization's name, as we have done here. Note that package names should be all lowercase, without spaces, underscores, or other special characters. If you intend to release your code into the Plone Collective, you can use the collective.* namespace, although other namespaces are allowed too. The plone.* namespace is reserved for packages in the core Plone repository, where the copyright has been transferred to the Plone Foundation. You should normally not use this without first coordinating with the Plone Framework Team. We go into the src/ directory of the buildout and run the following command: $ ../bin/zopeskel plone optilux.policy This uses the plone ZopeSkel template to create a new package called optilux.policy. This will ask us a few questions. We will stick with "easy" mode for now, and answer True when asked whether to register a GenericSetup profile. Note that ZopeSkel will download some packages used by its local command support. This may mean the initial bin/zopeskel command takes a little while to complete, and assumes that we are currently connected to the internet. A local command is a feature of PasteScript, upon which ZopeSkel is built. ZopeSkel registers an addcontent command, which can be used to insert additional snippets of code, such as view registrations or new content types, into the initial skeleton generated by ZopeSkel. We will not use this feature, preferring instead to retain full control over the code we write and avoid the potential pitfalls of code generation. If you wish to use this feature, you will either need to install ZopeSkel and PasteScript into the global Python environment, or add PasteScript to the ${zopeskel:eggs} option in buildout.cfg, so that you get access to the bin/paster command. Run bin/zopeskel --help from the buildout root directory for more information about ZopeSkel and its options. Distribution details Let us now take a closer look at what ZopeSkel has generated for us. We will also consider which files should be added to version control, and which files should be ignored. Item Version control Purpose setup.py Yes Contains instructions for how Setuptools/Distribute (and thus Buildout) should manage the package's distribution. We will make a few modifications to this file later. optilux.policy.egg-info/ Yes Contains additional distribution configuration. In this case, ZopeSkel keeps track of which template was used to generate the initial skeleton using this file. *.egg No ZopeSkel downloads a few eggs that are used for its local command support (Paste, PasteScript, and PasteDeploy) into the distribution directory root. If you do not intend to use the local command support, you can delete these. You should not add these to version control. README.txt Yes If you intend to release your package to the public, you should document it here. PyPI requires that this file be present in the root of a distribution. It is also read into the long_description variable in setup.py. PyPI will attempt to render this as reStructuredText markup (see http://docutils.sourceforge.net/rst.html). docs/ Yes Contains additional documentation, including the software license (which should be the GNU General Public License, version 2, for any packages that import directly from any of Plone's GPL-licensed packages) and a change log. Changes to setup.py Before we can progress, we will make a few modifications to setup.py. Our revised file looks similar to the following code, with changes highlighted: from setuptools import setup, find_packagesimport osversion = '2.0'setup(name='optilux.policy', version=version, description="Policy package for the Optilux Cinemas project", long_description=open("README.txt").read() + "n" + open(os.path.join("docs", "HISTORY.txt")).read(), # Get more strings from # http://pypi.python.org/pypi?%3Aaction=list_classifiers classifiers=[ "Framework :: Plone", "Programming Language :: Python", ], keywords='', author='Martin Aspeli', author_email='[email protected]', url='http://optilux-cinemas.com', license='GPL', packages=find_packages(exclude=['ez_setup']), namespace_packages=['optilux'], include_package_data=True, zip_safe=False, install_requires=[ 'setuptools', 'Plone', ], extras_require={ 'test': ['plone.app.testing',] }, entry_points=""" # -*- Entry points: -*- [z3c.autoinclude.plugin] target = plone """,# setup_requires=["PasteScript"],# paster_plugins=["ZopeSkel"], ) The changes are as follows: We have added an author name, e-mail address, and updated project URL. These are used as metadata if the distribution is ever uploaded to PyPI. For internal projects, they are less important. We have declared an explicit dependency on the Plone distribution, that is, on Plone itself. This ensures that when our package is installed, so is Plone. We will shortly update our main working set to contain only the optilux. policy distribution. This dependency ensures that Plone is installed as part of our application policy. We have then added a [tests] extra, which adds a dependency on plone. app.testing. We will install this extra as part of the following test working set, making plone.app.testing available in the test runner (but not in the Zope runtime). Finally, we have commented out the setup_requires and paster_plugins options. These are used to support ZopeSkel local commands, which we have decided not to use. The main reason to comment them out is to avoid having Buildout download these additional dependencies into the distribution root directory, saving time, and reducing the number of files in the build. Also note that, unlike distributions downloaded by Buildout in general, there is no "offline" support for these options. Changes to configure.zcml We will also make a minor change to the generated configure.zcml file, removing the line: <five:registerPackage package="." initialize=".initialize" /> This directive is used to register the package as an old-style Zope 2 product. The main reason to do this is to ensure that the initialize() function is called on Zope startup. This may be a useful hook, but most of the time it is superfluous, and requires additional test setup that can make tests more brittle. We can also remove the (empty) initialize() function itself from the optilux/policy/__init__.py file, effectively leaving the file blank. Do not delete __init__.py, however, as it is needed to make this directory into a Python package. Updating the buildout Before we can use our new distribution, we need to add it to our development buildout. We will consider two scenarios: The distribution is under version control in a repository module separate to the development buildout itself. This is the recommended approach. The distribution is not under version control, or is kept inside the version control module of the buildout itself. The example source code that comes with this article is distributed as a simple archive, so it uses this approach. Given the approach we have taken to separating out our buildout configuration into multiple files, we must first update packages.cfg to add the new package. Under the [sources] section, we could add: [sources]optilux.policy = svn https://some-svn-server/optilux.policy/trunk Or, for distributions without a separate version control URL: [sources]optilux.policy = fs optilux.policy We must also update the main and test working sets in the same file: [eggs]main = optilux.policytest = optilux.policy [test] Finally, we must tell Buildout to automatically add this distribution as a develop egg when running the development buildout. This is done near the top of buildout.cfg: auto-checkout = optilux.policy We must rerun buildout to let the changes take effect: $ bin/buildout We can test that the package is now available for import using the zopepy interpreter: $ bin/zopepy>>> from optilux import policy>>> The absence of an ImportError tells us that this package will now be known to the Zope instance in the buildout. To be absolutely sure, you can also open the bin/instance script in a text editor (bin/instance-script.py on Windows) and look for a line in the sys.path mangling referencing the package. Working sets and component configuration It is worth deliberating a little more on how Plone and our new policy package are loaded and configured. At build time: Buildout installs the [instance] part, which will generate the bin/instance script. The plone.recipe.zope2instance recipe calculates a working set from its eggs option, which in our buildout references ${eggs:main}. This contains exactly one distribution: optilux.policy. This in turn depends on the Plone distribution which in turn causes Buildout to install all of Plone. Here, we have made a policy decision to depend on a "big" Plone distribution that includes some optional add-ons. We could also have depended on the smaller Products.CMFPlone distribution (which works for Plone 4.0.2 onwards), which includes only the core of Plone, perhaps adding specific dependencies for add-ons we are interested in. When declaring actual dependencies used by distributions that contain reusable code instead of just policy, you should always depend on the packages you import from or otherwise depend on, and no more. That is, if you import from Products.CMFPlone, you should depend on this, and not on the Plone meta-egg (which itself contains no code, but only declares dependencies on other distributions, including Products. CMFPlone). To learn more about the rationale behind the Products. CMFPlone distribution, see http://dev.plone.org/plone/ticket/10877. At runtime: The bin/instance script starts Zope. Zope loads the site.zcml file (parts/instance/etc/site.zcml) as part of its startup process. This automatically includes the ZCML configuration for packages in the Products.* namespace, including Products.CMFPlone, Plone's main package. Plone uses z3c.autoinclude to automatically load the ZCML configuration of packages that opt into this using the z3c.autoinclude.plugin entry point target = plone. The optilux.policy distribution contains such an entry point, so it will be configured, along with any packages or files it explicitly includes from its own configure.zcml file.
Read more
  • 0
  • 0
  • 1198
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 €14.99/month. Cancel anytime
article-image-magento-14-theming-making-our-theme-shine
Packt
23 Aug 2011
8 min read
Save for later

Magento 1.4 Theming: Making Our Theme Shine

Packt
23 Aug 2011
8 min read
  Magento 1.4 Theming Cookbook Over 40 recipes to create a fully functional, feature rich, customized Magento theme         Read more about this book       (For more resources on this subject, see here.) Looks quite interesting, doesn't it? Let's get started! Introduction You will find all the necessary code in the code bundle; however, some JavaScript libraries won't be included. Don't worry, they are very easy to find and download! Using Cufón to include any font we like in our theme This technique, which allows us to use any font we like in our site, is quite common these days, and is very, very useful. Years ago, if we wanted to include some uncommon font in our design, we could only do it by using a substitutive image. Nowadays, we have many options, such as some PHP extensions, @font-face, Flash (sIFR), and, of course, Cufón. And that last option is the one we are about to use. Getting ready If you would like to copy the code, instead of writing it, remember you can find all the necessary code in the code bundle in Chapter 5, recipe 1. How to do it... Ready to start this first recipe? Let's go: First we have to decide which font to use; this is totally up to you. In this example I'm going to use this one: http://www.dafont.com/aldo.font. It's a free font, and looks very good! Thanks to Sacha Rein. Just download it or find any other font of your liking. Now we need to use the Cufón generator in order to create the font package. We will go to this URL: http://cufon.shoqolate.com/generate/. There we will be able to see something similar to the following screenshot: On that screen we only have to follow all the instructions and click on the Let's do this button: This will create a file called Aldo_600.font.js, which will be the one we will be using in this example. But we also need something more, the Cufón library. Download it by clicking the Download button: After downloading the Cufón library, we will download a file called cufon-yui.js. We now have all the necessary tools. It's time to make use of them. First place cufon-yui.js and Aldo_600.font.js inside skin/frontend/default/rafael/js. Now we need to edit our layout file. Let's open: app/design/frontend/default/rafael/layout/page.xml. Once we have this file opened we are going to look for this piece of code: <action method="addCss"><stylesheet>css/960_24_col.css</stylesheet></action> <action method="addCss"><stylesheet>css/styles.css</stylesheet></action> And just below it we are going to add the following: <action method="addJs"><script>../skin/frontend/default/rafael/js/cufon-yui.js</script></action> <action method="addJs"><script>../skin/frontend/default/rafael/js/Aldo_600.font.js</script></action> See, we are adding our two JavaScript files. The path is relative to Magento's root JavaScript folder. With this done, our theme will load these two JS files. Now we are going to make use of them. Just open app/design/frontend/default/rafael/template/page/2columns-right.phtml. At the bottom of this file we are going to add the following code: <script type="text/javascript"> Cufon.replace('h1'); </script></body></html> And that's all we need. Check the difference! Before we had something like the following: And now we have this: Every h1 tag of our site will now use our Aldo font, or any other font of your liking. The possibilities are endless! How it works... This recipe was quite easy, but full of possibilities. We first downloaded the necessary JavaScript files, and then made use of them with Magento's add JS layout tag. Later we were able to use the libraries in our template as in any other HTML file. SlideDeck content slider Sometimes our home page is crowded with info, and we still need to place more and more things. A great way of doing so is using sliders. And the SlideDeck one offers a very configurable one. In this recipe we are going to see how to add it to our Magento theme. You shouldn't miss this recipe! How to do it... Making use of the slider in our theme is quite simple, let's see: First we need to go to http://www.slidedeck.com/ and download SlideDeck Lite, as we will be using the Lite version in this recipe. Once downloaded we will end up with a file called slidedeck-1.2.1-litewordpress-1.3.6.zip. Unzip it. Go to skin/frontend/default/rafael/css and place the following files in it: slidedeck.skin.css slidedeck.skin.ie.css back.png corner.png slides.png spines.png Next, place the following files in skin/frontend/default/rafael/js: jquery-1.3.2.min.js slidedeck.jquery.lite.pack.js Good, now everything is in place. Next, open: app/design/frontend/default/rafael/layout/page.xml. Now look for the following piece of code: <block type="page/html_head" name="head" as="head"> <action method="addJs"><script>prototype/prototype.js</script></action> <action method="addJs" ifconfig="dev/js/deprecation"><script>prototype/deprecation.js</script></action> <action method="addJs"><script>lib/ccard.js</script></action> Place the jQuery load tag just before the prototype one, so we have no conflict between libraries: <block type="page/html_head" name="head" as="head"> <action method="addJs"><script>../skin/frontend/default/rafael/js/jquery-1.3.2.min.js</script></action> <action method="addJs"><script>prototype/prototype.js</script></action> <action method="addJs" ifconfig="dev/js/deprecation"><script>prototype/deprecation.js</script></action> Also add the following code before the closing of the block: <action method="addCss"><stylesheet>css/slidedeck.skin.css</stylesheet></action><action method="addCss"><stylesheet>css/slidedeck.skin.ie.css</stylesheet></action><action method="addJs"><script>../skin/frontend/default/rafael/js/slidedeck.jquery.lite.pack.js</script></action> The following steps require us to log in to the administrator panel. Just go to: http://127.0.0.1/magento/index.php/admin. Now to CMS/Pages, open the home page one: Once inside, go to the Content tab. Click on Show/Hide editor. Find the following code: <div class="grid_18"> <a href="#"><img src="{{skin url='img_products/big_banner.jpg'}}" alt="Big banner" title="Big banner" /></a> </div><!-- Big banner → And replace it with the following: <div class="grid_18"> <style type="text/css"> #slidedeck_frame { width: 610px; height: 300px; } </style> <div id="slidedeck_frame" class="skin-slidedeck"> <dl class="slidedeck"> <dt>Slide 1</dt> <dd>Sample slide content</dd> <dt>Slide 2</dt> <dd>Sample slide content</dd> </dl> </div> <script type="text/javascript"> jQuery(document).ready(function($) { $('.slidedeck').slidedeck(); }); </script> <!-- Help support SlideDeck! Place this noscript tag onyour page when you deploy a SlideDeck to provide a link back! --> <noscript> <p>Powered By <a href="http://www.slidedeck.com"title="Visit SlideDeck.com">SlideDeck</a></p> </noscript></div><!-- Big banner → Save the page and reload the frontend. Our front page should have a slider just like the one seen in the following screenshot: And we are done! Remember you can place any content you want inside these tags: <dl class="slidedeck"> <dt>Slide 1</dt> <dd>Sample slide content</dd> <dt>Slide 2</dt> <dd>Sample slide content</dd> </dl> How it works... This recipe is also quite easy. We only need to load the necessary JavaScript files and edit the content of the home page, in order to add the necessary code.
Read more
  • 0
  • 0
  • 1315

article-image-magento-14-theming-working-existing-themes
Packt
16 Aug 2011
5 min read
Save for later

Magento 1.4 Theming: Working with Existing Themes

Packt
16 Aug 2011
5 min read
  Magento 1.4 Theming Cookbook Over 40 recipes to create a fully functional, feature rich, customized Magento theme         Read more about this book       (For more resources on this subject, see here.) Introduction As we have just noted, this article is going to be more practical. We are going to see some basic things that will help us modify the appearance of our site, from looking for free templates to the process of installing them and making some tiny changes. I am sure this article helps us establish a good foundation though most of the things we are going to see are quite simple, so this is going to be a good introduction. Installing a theme through Magento Connect We are going to see two ways in which we can install a new Magento theme. The first one is through Magento Connect. This involves a number of steps that we are going to follow along this recipe. Getting ready First we need to go to Magento Connect: http://www.magentocommerce.com/magentoconnect. There, search for the theme Magento Classic Theme Free, or, alternatively, load this link: http://www.magentocommerce.com/magento-connect/TemplatesMaster/extension/928/magento-classic-theme. How to do it... This theme, the Magento Classic Theme, is the one we are going to use through this article. Follow these steps to install it: First we need to log into our www.magentocommerce.com site account. This is a necessary step to get the Extension Key. The extension key can be found in a box that looks like the following screenshot: We also find some other useful info there, like the compatibility version, and the price, free in this case. There's also a button that says Get Extension Key. Click on that button: After clicking on the Get Extension Key button, the box that we can see in the preceding screenshot appears. On that image we must accept the license agreement, select the Magento version we are using, and again click on Get Extension Key: This is the last screen. We need to obtain the extension key and copy it as we are going to use it very soon. For the next steps we need to go to our Magento installation Admin area screen. There, carry out the following instructions: Go to System menu, then Magento Connect and finally Magento Connect Manager. The Magento Connect Manager screen will appear, just like the following screenshot: Here we need to insert the same login info as we used in our Magento Admin screen. In the next screen we need to insert the key we have just copied: When we click on the install button the installation process starts. It will only take a few seconds and the theme will be installed into our site. Fast and easy! How it works... We have just selected a theme from the Magento site, and installed it into our own Magento installation through the Magento Connect Manager. We can do this as many times as we want, and install as many themes as we need to. Installing a theme manually In this recipe we are going to see another method of installing themes into our Magento installation. This time we are going to see how to install a theme manually. Why is this important? Just because we may want to use themes that are not available through Magento Connect, as they can be themes purchased in other places, or downloaded from free themes. Getting ready In order to follow this method we need a downloaded theme. You can get the Magento Classic theme from this link: http://blog.templates-master.com/free-magento-classic-theme/ Once done, we will get a file called f002.classic_1.zip; just unzip it. Inside we will find many folders: graphic source: This folder has all the PSD files necessary to help us modify the theme installation: This folder is where we can find installation instructions template source 1.3.2: The theme is for Magento version 1.3.2 template source 1.4.0.1: This theme is for Magento 1.4.0.1 template source 1.4.1.0: This theme is for Magento 1.4.1.0 Though our Magento version is not 1.4.1.0, we could use the theme without problems. What can we find inside that folder? Another two folders: app skin This is the folder structure we should expect from a Magento theme. How to do it... Installing a theme is as easy as copying those two folders into our Magento installation, with all their sub folders and files. In our Magento installation you will see another app and skin folder, so the contents in the folder of the downloaded theme will combine with the already existing ones. No overwriting should occur. And that's all; we don't need to do anything else. Selecting the recently installed theme Good, now we have installed one theme, one way or the other. So, how do we enable this theme? In fact it's quite easy; we can achieve just that from our site admin panel. Getting ready If you haven't logged into your Magento installation, do it now. How to do it... Well, once we are inside the admin panel of our site, we need to carry out the following steps to select our new theme: Go to System menu, and then click on Configuration. Look at the General block and select Design. There you will see the following screenshot: There, in Current Package Name, we can leave it as default. In the Themes section, in the Default column, we can enter the name of the theme, f002 for this example. We are done. Click on the Save config button and refresh the frontend. You will be able to see the changes. How it works... We are done. We have just selected the new theme. As promised it was quite easy, wasn't it? Try it yourself!
Read more
  • 0
  • 0
  • 1289

article-image-magento-exploring-themes
Packt
16 Aug 2011
6 min read
Save for later

Magento: Exploring Themes

Packt
16 Aug 2011
6 min read
  Magento 1.4 Themes Design Magento terminology Before you look at Magento themes, it's beneficial to know the difference between what Magento calls interfaces and what Magento calls themes, and the distinguishing factors of websites and stores. Magento websites and Magento stores To add to this, the terms websites and stores have a slightly different meaning in Magento than in general and in other systems. For example, if your business is called M2, you might have three Magento stores (managed through the same installation of Magento) called: Blue Store Red Store Yellow Store In this case, Magento refers to M2 as the website and the stores are Blue Store, Red Store, and Yellow Store. Each store then has one or more store views associated with it too. The simplest Magento website consists of a store and store view (usually of the same name): A slightly more complex Magento store may just have one store view for each store. This is a useful technique if you want to manage more than one store in the same Magento installation, with each store selling different products (for example, the Blue Store sells blue products and the Yellow Store sells yellow products). If a store were to make use of more than one Magento store view, it might be, to present customers with a bi-lingual website. For example, our Blue Store may have an English, French, and Japanese store view associated with it: Magento interfaces An interface consists of one or more Magento themes that comprise how your stores look and function for your customers. Interfaces can be assigned at two levels in Magento: At the website level At the store view level If you assign an interface at the website level of your Magento installation, all stores associated with the interface inherit the interface. For example, imagine your website is known as M2 in Magento and it contains three stores called: Blue Store Red Store Yellow Store If you assign an interface at the website level (that is, M2), then the subsequent stores, Blue Store, Red Store, and Yellow Store, inherit this interface: If you assigned the interface at the store view level of Magento, then each store view can retain a different interface: Magento packages A Magento package typically contains a base theme, which contains all of the templates, and other files that Magento needs to run successfully, and a custom theme. Let's take a typical example of a Magento store, M2. This may have two packages: the base package, located in the app/design/frontend/base/ directory and another package which itself consists of two themes: The base theme is in the app/design/frontend/base/ directory. The second package contains the custom theme's default theme in the app/design/frontend/ default/ directory, which acts as a base theme within the package. The custom theme itself, which is the non-default theme, is in the app/design/frontend/our-custom- theme/default/ and app/design/frontend/our-custom-theme/custom-theme/ directories. By default, Magento will look for a required file in the following order: Custom theme directory: app/design/frontend/our-custom-theme/ custom-theme/ Custom theme's default directory: app/design/frontend/our-custom-theme/ default/ Base directory: app/design/frontend/base/ Magento themes A Magento theme fits in to the Magento hierarchy in a number of positions: it can act as an interface or as a store view. There's more to discover about Magento themes yet, though there are two types of Magento theme: a base theme (this was called a default theme in Magento 1.3) and a non-default theme. Base theme A base theme provides all conceivable files that a Magento store requires to run without error, so that non-default themes built to customize a Magento store will not cause errors if a file does not exist within it. The base theme does not contain all of the CSS and images required to style your store, as you'll be doing this with our non-default theme. Don't change the base package! It is important that you do not edit any files in the base package and that you do not attempt to create a custom theme in the base package, as this will make upgrading Magento fully difficult. Make sure any custom themes you are working on are within their own design package; for example, your theme's files should be located at app/design/ frontend/your-package-name/default and skin/frontend/ your-package-name/default. Default themes A default theme in Magento 1.4 changes aspects of your store but does not need to include every file required by Magento as a base theme does, though it must just contain at least one file for at least one aspect of a theme (that is, locales, skins, templates, layout): Default themes in Magento 1.3 In Magento 1.3, the default theme acted the way the base theme did in Magento 1.4, providing every file that your Magento store required to operate. Non-default themes A non-default theme changes aspects of a Magento store but does not need to include every file required by Magento as the base theme does; it must just contain at least one file for at least one aspect of a theme (that is, locales, skins, templates, layout): In this way, non-default themes are similar to a default theme in Magento. Non-default themes can be used to alter your Magento store for different seasonal events such as Christmas, Easter, Eid, Passover, and other religious festivals, as well as events in your industry's corporate calendar such as annual exhibitions and conferences. Blocks in Magento Magento uses blocks to differentiate between the various components of its functionality, with the idea that this makes it easier for Magento developers and Magento theme designers to customize the functionality of Magento and the look and feel of Magento respectively. There are two types of blocks in Magento: Content blocks Structural blocks Content blocks A content block displays the generated XHTML provided by Magento for any given feature. Content blocks are used within Magento structural blocks. Examples of content blocks in Magento include the following: The search feature Product listings The mini cart Category listings Site navigation links Callouts (advertising blocks) The following diagram illustrates how a Magento store might have content blocks positioned within its structural blocks: Simply, content blocks are the what of a Magento theme: they define what type of content appears within any given page or view within Magento. Structural blocks In Magento, a structural block exists only to maintain a visual hierarchy to a page. Typical structural blocks in a Magento theme include: Header Primary area Left column Right column Footer
Read more
  • 0
  • 0
  • 1656

article-image-overview-node-package-manager
Packt
11 Aug 2011
5 min read
Save for later

An Overview of the Node Package Manager

Packt
11 Aug 2011
5 min read
Node Web Development npm package format An npm package is a directory structure with a package.json file describing the package. This is exactly what we just referred to as a Complex Module, except npm recognizes many more package.json tags than does Node. The starting point for npm's package.json is the CommonJS Packages/1.0 specification. The documentation for npm's package.json implementation is accessed with the following command: $ npm help json A basic package.json file is as follows: { name: "packageName", version: "1.0", main: "mainModuleName", modules: { "mod1": "lib/mod1", "mod2": "lib/mod2" } } The file is in JSON format which, as a JavaScript programmer, you should already have seen a few hundred times. The most important tags are name and version. The name will appear in URLs and command names, so choose one that's safe for both. If you desire to publish a package in the public npm repository it's helpful to check and see if a particular name is already being used, at http://search.npmjs.org or with the following command: $ npm search packageName The main tag is treated the same as complex modules. It references the module that will be returned when invoking require('packageName'). Packages can contain many modules within themselves, and those can be listed in the modules list. Packages can be bundled as tar-gzip tarballs, especially to send them over the Internet. A package can declare dependencies on other packages. That way npm can automatically install other modules required by the module being installed. Dependencies are declared as follows: "dependencies": { "foo" : "1.0.0 - 2.9999.9999" , "bar" : ">=1.0.2 <2.1.2" } The description and keywords fields help people to find the package when searching in an npm repository (http://search.npmjs.org). Ownership of a package can be documented in the homepage, author, or contributors fields: "description": "My wonderful packages walks dogs", "homepage": "http://npm.dogs.org/dogwalker/", "author": [email protected] Some npm packages provide executable programs meant to be in the user's PATH. These are declared using the bin tag. It's a map of command names to the script which implements that command. The command scripts are installed into the directory containing the node executable using the name given. bin: { 'nodeload.js': './nodeload.js', 'nl.js': './nl.js' }, The directories tag documents the package directory structure. The lib directory is automatically scanned for modules to load. There are other directory tags for binaries, manuals, and documentation. directories: { lib: './lib', bin: './bin' }, The script tags are script commands run at various events in the lifecycle of the package. These events include install, activate, uninstall, update, and more. For more information about script commands, use the following command: $ npm help scripts This was only a taste of the npm package format; see the documentation (npm help json) for more. Finding npm packages By default npm modules are retrieved over the Internet from the public package registry maintained on http://npmjs.org. If you know the module name it can be installed simply by typing the following: $ npm install moduleName But what if you don't know the module name? How do you discover the interesting modules? The website http://npmjs.org publishes an index of the modules in that registry, and the http://search.npmjs.org site lets you search that index. npm also has a command-line search function to consult the same index: $ npm search mp3 mediatags Tools extracting for media meta-data tags =coolaj86 util m4a aac mp3 id3 jpeg exiv xmp node3p An Amazon MP3 downloader for NodeJS. =ncb000gt Of course upon finding a module it's installed as follows: $ npm install mediatags After installing a module one may want to see the documentation, which would be on the module's website. The homepage tag in the package.json lists that URL. The easiest way to look at the package.json file is with the npm view command, as follows: $ npm view zombie ... { name: 'zombie', description: 'Insanely fast, full-stack, headless browser testing using Node.js', ... version: '0.9.4', homepage: 'http://zombie.labnotes.org/', ... npm ok You can use npm view to extract any tag from package.json, like the following which lets you view just the homepage tag: $ npm view zombie homepage http://zombie.labnotes.org/ Using the npm commands The main npm command has a long list of sub-commands for specific package management operations. These cover every aspect of the lifecycle of publishing packages (as a package author), and downloading, using, or removing packages (as an npm consumer). Getting help with npm Perhaps the most important thing is to learn where to turn to get help. The main help is delivered along with the npm command accessed as follows: For most of the commands you can access the help text for that command by typing the following: $ npm help <command> The npm website (http://npmjs.org/) has a FAQ that is also delivered with the npm software. Perhaps the most important question (and answer) is: Why does npm hate me? npm is not capable of hatred. It loves everyone, even you.  
Read more
  • 0
  • 0
  • 5994
article-image-understanding-and-developing-node-modules
Packt
11 Aug 2011
5 min read
Save for later

Understanding and Developing Node Modules

Packt
11 Aug 2011
5 min read
Node Web Development A practical introduction to Node, the exciting new server-side JavaScript web development stack What's a module? Modules are the basic building block of constructing Node applications. We have already seen modules in action; every JavaScript file we use in Node is itself a module. It's time to see what they are and how they work. The following code to pull in the fs module, gives us access to its functions: var fs = require('fs'); The require function searches for modules, and loads the module definition into the Node runtime, making its functions available. The fs object (in this case) contains the code (and data) exported by the fs module. Let's look at a brief example of this before we start diving into the details. Ponder over this module, simple.js: var count = 0; exports.next = function() { return count++; } This defines an exported function and a local variable. Now let's use it: The object returned from require('./simple') is the same object, exports, we assigned a function to inside simple.js. Each call to s.next calls the function next in simple.js, which returns (and increments) the value of the count variable, explaining why s.next returns progressively bigger numbers. The rule is that, anything (functions, objects) assigned as a field of exports is exported from the module, and objects inside the module but not assigned to exports are not visible to any code outside the module. This is an example of encapsulation. Now that we've got a taste of modules, let's take a deeper look. Node modules Node's module implementation is strongly inspired by, but not identical to, the CommonJS module specification. The differences between them might only be important if you need to share code between Node and other CommonJS systems. A quick scan of the Modules/1.1.1 spec indicates that the differences are minor, and for our purposes it's enough to just get on with the task of learning to use Node without dwelling too long on the differences. How does Node resolve require('module')? In Node, modules are stored in files, one module per file. There are several ways to specify module names, and several ways to organize the deployment of modules in the file system. It's quite flexible, especially when used with npm, the de-facto standard package manager for Node. Module identifiers and path names Generally speaking the module name is a path name, but with the file extension removed. That is, when we write require('./simple'), Node knows to add .js to the file name and load in simple.js. Modules whose file names end in .js are of course expected to be written in JavaScript. Node also supports binary code native libraries as Node modules. In this case the file name extension to use is .node. It's outside our scope to discuss implementation of a native code Node module, but this gives you enough knowledge to recognize them when you come across them. Some Node modules are not files in the file system, but are baked into the Node executable. These are the Core modules, the ones documented on nodejs.org. Their original existence is as files in the Node source tree but the build process compiles them into the binary Node executable. There are three types of module identifiers: relative, absolute, and top-level. Relative module identifiers begin with "./" or "../" and absolute identifiers begin with "/". These are identical with POSIX file system semantics with path names being relative to the file being executed. Absolute module identifiers obviously are relative to the root of the file system. Top-level module identifiers do not begin with "." , "..", or "/" and instead are simply the module name. These modules are stored in one of several directories, such as a node_modules directory, or those directories listed in the array require.paths, designated by Node to hold these modules. Local modules within your application The universe of all possible modules is split neatly into two kinds, those modules that are part of a specific application, and those modules that aren't. Hopefully the modules that aren't part of a specific application were written to serve a generalized purpose. Let's begin with implementation of modules used within your application. Typically your application will have a directory structure of module files sitting next to each other in the source control system, and then deployed to servers. These modules will know the relative path to their sibling modules within the application, and should use that knowledge to refer to each other using relative module identifiers. For example, to help us understand this, let's look at the structure of an existing Node package, the Express web application framework. It includes several modules structured in a hierarchy that the Express developers found to be useful. You can imagine creating a similar hierarchy for applications reaching a certain level of complexity, subdividing the application into chunks larger than a module but smaller than an application. Unfortunately there isn't a word to describe this, in Node, so we're left with a clumsy phrase like "subdivide into chunks larger than a module". Each subdivided chunk would be implemented as a directory with a few modules in it. In this example, the most likely relative module reference is to utils.js. Depending on the source file which wants to use utils.js it would use one of the following require statements: var utils = require('./lib/utils'); var utils = require('./utils'); var utils = require('../utils');  
Read more
  • 0
  • 0
  • 6950

article-image-jquery-ui-themes-states-cues-overlays-and-shadows
Packt
05 Aug 2011
7 min read
Save for later

jQuery UI Themes: States, Cues, Overlays and Shadows

Packt
05 Aug 2011
7 min read
jQuery UI Themes Beginner's Guide Create new themes for your JQuery site with this step-by-step guide States jQueryUi widgets are always in one state or another. These states also play a role in themes. A widget in one state should look different than widgets in another state. These different appearances are controlled by CSS style properties within the theme. States are especially prevalent in widgets that interact with mouse events. When a user hovers over a widget that is interested in these types of events, the widget changes into a hover state. When the mouse leaves the widget, it returns to a default state. Even when nothing is happening with a widget—no events are taking place that the widget is interested in—the widget is in a default state. The reason we need a default state for widgets is so that they can return to their default appearance. The appearance of these states is entirely controlled through the applied theme. In this section, we'll change the ThemeRoller settings for widget states. Time for action - setting default state styles Some widgets that interact with the mouse have a default state applied to them. We can adjust how this state changes the appearance of the widget using ThemeRoller settings: Continuing with our theme design, expand the Clickable: default state section. In the Background color & texture section, click on the texture selector in the middle. Select the inset hard texture. In the Background color & texture section, set the background opacity to 65%. Change the Border color setting value to #b0b0b0. Change the Icon color setting value to #555555: What just happened? We've just changed the look and feel of the default widget state. We changed the background texture to match that of the header theme settings. Likewise, we also changed the background opacity to 65%, also to match the header theme settings. The border color is now slightly darker - this looks better with the new default state background settings. Finally, the icon color was updated to match the default state font color. Here is what the sample button looked like before we made our changes: Here is what the sample button looks like after we've updated our theme settings: Time for action - setting hover state styles The same widgets that may be in a default state, for instance, a button, may also be in a hover state. Widgets enter a hover state when a user moves the mouse pointer over the widget. We want our user interface to give some kind of visual indication that the user has hovered over something they can click. It's time to give our theme some hover state styles: Continuing with our theme design, expand the Clickable: hover state section. In the Background color & texture section, click on the texture selector in the middle. Select the inset hard texture. Change the Border color setting value to #787878. Change the Icon color setting value to #212121: What just happened? When we hover over widgets that support the hover state, their appearance is now harmonized with our theme settings. The background texture was updated to match the texture of the default state styles. The border color is now slightly darker. This makes the widget really stand out when the user hovers over it. At the same, it isn't so dark that it conflicts with the rest of the theme settings. Finally, we updated the icon color to match that of the font color. Here is what the sample button widget looked like before we change the hover state settings: Here is what the sample button widget looked like after we updated the hover state theme settings: Time for action - setting active state styles Some jQuery UI widgets, the same widgets that can be in either a default or hover state, can also be in an active state. Widgets become active after a user clicks them. For instance, the currently selected tab in a tabs widget is in an active state. We can control the appearance of active widgets through the ThemeRoller: Continuing with our theme design, expand the Clickable: active state section. In the Background color & texture section, change the color setting value on the left to #f9f9f9. In the Background color & texture section, click the texture selector in the middle. Select the flat texture. In the Background color & texture section, set the opacity setting value on the right-hand side to 100%. Change the Border color setting value to #808080. Change the Icon color setting value to #212121: What just happened? Widgets in the active state will now use our updated theme styles. We've changed the background color to something only marginally darker. The reason being, we are using the highlight soft texture in our content theme settings. This means that the color gets lighter toward the top. The color at the top is what we're aiming for in the active state styles. The texture has been changed to flat. Flat textures, unlike the others, have no pattern - they're simply a color. Accordingly, we've changed the background opacity to 100%. We do this because for these theme settings, we're only interested in showing the color. The active state border is slightly darker, a visual cue to show that the widget is in fact active. Finally, like other adjustments we've made in our theme, the icon color now mirrors the text color. Here is what the sample tabs widget looked like before we changed the active state theme settings: Here is what the sample tabs widget looks like after we've updated the active state theme settings. Notice that the selected tab's border stands out among the other tabs and how the selected tab blends better with the tab content. Cues In any web application, it is important to have the ability to notify users of events that have taken place. Perhaps an order was successfully processed, or a registration field was entered incorrectly. Both occurrences are worth letting the user know about. These are types of cues. The jQuery UI theming framework defines two types of cues used to notify the user. These are highlights and errors. A highlight cue is informational, something that needs to be brought to the user's attention. An error is something exceptional that should not have happened. Both cue categories can be customized to meet the requirements of any theme. It is important to keep in mind that cues are meant to aggressively grab the attention of the user - not to passively display information. So the theme styles applied to these elements really stand out. In this section we'll take a look at how to make this happen with the ThemeRoller. Time for action - changing the highlight cue A user of your jQuery UI application has just saved something. How do they know it was successful? Your application needs to inform them somehow—it needs to highlight the fact that something interesting just happened. To do this, your application will display a highlight cue. Let's add some highlight styles to our theme: Continuing with our theme design, expand the Highlight section. In the Background color & texture section, change the color setting value to #faf2c7. In the Background color & texture section, change the opacity setting value to 85%. Change the Border color setting value to #f8df49. Change the Text color setting value to #212121: What just happened? The theme settings for any highlight cues we display for the user have been updated. The background color is a shade darker and the opacity has been increased by 10%. The border color is now significantly darker than the background color. The contrast between the background and border colors defined here are now better aligned with the background-border contrast defined in other theme sections. Finally, we've updated the text color to be the same as the text in other sections. This is not for a noticeable difference (there isn't any), but for consistency reasons. Here is what the sample highlight cue looked like before we updated the theme settings: Here is what the sample highlight widget looks like after the theme setting changes:
Read more
  • 0
  • 0
  • 2127

article-image-jquery-ui-themes-using-themeroller
Packt
04 Aug 2011
8 min read
Save for later

jQuery UI Themes: Using the ThemeRoller

Packt
04 Aug 2011
8 min read
jQuery UI Themes Beginner's Guide Create new themes for your JQuery site with this step-by-step guide ThemeRoller basics Before we start using the ThemeRoller application to design and build our own themes, we'll take a quick look at what makes it such a handy tool. There is a lot more to the ThemeRoller than simply changing themes—we also use it to build them. You can think of it as an IDE for jQuery UI themes. Instant feedback What makes the ThemeRoller application such a powerful development tool is the speed with which you get feedback to changes made in the theme design. Any change made in the ThemeRoller is instantaneously reflected in the sample widgets provided on the page. For instance, if I were to change a font setting, that change would be reflected immediately in the sample widgets provided on the same page. There is no need to update the application you're building to see the results of small adjustments made to theme style settings. The same is true of prepackaged themes in the ThemeRoller gallery. Selecting a theme will apply it to the same widgets - you get immediate feedback. This is very helpful in deciding on prepackaged themes. If you can see how it looks with jQuery UI widgets right away, that may dissuade you from using the theme or it may close the deal. The idea behind this feedback mechanism offered by the ThemeRoller is a sped-up development cycle. Eliminating several steps when developing anything, themes included, is a welcome feature. The dev tool The ThemeRoller dev tool is a simple bookmarket for Firefox that brings the entire ThemeRoller application into any page with jQuery UI widgets. The benefit of the dev tool is that it allows you to see immediate theme changes in the context of the application you're building. If you use the ThemeRoller application from the jQuery UI website, you can only see changes as they apply to the sample widgets provided. This can give you a better idea of what the theme changes will look like on a finished product. There are some limitations to using the dev tool though. If you're developing your application locally, not on a development server, you can't use the dev tool due to security restrictions. The dev tool is better suited for viewing changes to themes, or viewing different themes entirely, on a deployed user interface. Having said that, if you're designing a user interface with several collaborators, you might have a remote development server. In this scenario, the dev tool suits its name. Portability The ThemeRoller application is portable in more ways than one. The dev tool for Firefox allows us to use the application within any jQuery UI application. This means that we can design and tweak our jQuery UI themes as we build the widgets. This portability between applications means that we can build a single theme that works for a suite of applications, or a product line, if we're so inclined. We can also use the ThemeRoller application directly from the jQueryUI website. This is handy if we don't have any widgets built or if you're trying jQuery UI out for the first time and just want to browse the wide selection of prepackaged themes. Whatever approach you take, the application is the same and will always be consistent, as it is a hosted application. You don't need to concern yourself with installing an IDE for theme authors to collaborate with. The ThemeRoller application is available wherever they are. ThemeRoller gallery It is nice to have a wide variety of prepackaged themes to choose from. It isn't all that helpful if you can't see how they look. The ThemeRoller application has a gallery where we can not only browse prepackaged themes but also take them for a test drive. This section is about using the ThemeRoller gallery to view themes and get a feel of the variety available to us. Viewing themes The ThemeRoller application doesn't hide anything about the prepackaged themes in the gallery. When we preview a theme, we get to see how it looks when applied to widgets. The theme gallery even gives us a thumbnail in the browser to show a bird's eye view of the theme. So if you see a lot of black and you're looking for something bright, you don't need to bother selecting it to see how the widgets look with it. Time for action - previewing a theme It's time for us to preview a jQuery UI theme before we actually download it. We can get an idea of what a theme in the ThemeRoller gallery will look like when applied to widgets: Point your web browser to http://jqueryui.com/themeroller/. Select the Gallery tab in the ThemeRoller section on the right-hand side. Move your mouse pointer over any theme in the gallery. A visual indicator will be displayed. Select the theme thumbnail:   What just happened? We've just selected a theme to preview from the ThemeRoller gallery. You'll notice that all the sample widgets to the right are instantly updated with the new theme. If we wanted to, we could change our theme selection and the sample widgets are once again updated with the theme changes. You'll notice that once you make a theme selection, the URL in your address bar is now long and ugly. These are the individual theme settings for the chosen theme being passed to the ThemeRoller page with the sample widgets. You'll also notice that the theme selection on the left-hand side of the page isn't preserved. This is because we're passing individual theme settings and not the name of the theme itself, for example, instancetheme=darkness. We'll see why this distinction is important in a little bit. Downloading themes Once you've selected a theme from the gallery and you're happy with how it looks, it is time to download it and use it with your jQuery UI project. Downloading a theme is easy—each prepackaged theme has a download button that will take you to the jQuery UI download page. If we wanted to, we could download all themes in a single package to experiment with, locally. This would also eliminate the need for the ThemeRoller application, which you probably don't want to do. Time for action - downloading a theme The gallery is a nice way to preview a theme, but now we want to use it in our application. To do this, we need to download it. This is similar to downloading the jQuery UI toolkit: Point your web browser to http://jqueryui.com/themeroller/. Select the Gallery tab in the ThemeRoller section on the left-hand side. Find a theme you wish to download. Click on the Download button underneath the theme thumbnail. This will bring you to the jQuery UI download page. Notice that your chosen theme is selected on the right-hand side of the page. Click on the Download button to download your theme: What just happened? We've just selected a prepackaged theme from the ThemeRoller gallery and downloaded it. In fact, you just downloaded jQuery UI again. The difference being, the downloaded ZIP archive contains the theme you selected from the gallery. The same principles apply for extracting the archive and using your theme with your jQuery UI application. The downside is that if you're downloading a theme, chances are you already have a jQuery UI application under development. In this case, downloading jQuery UI JavaScript files is redundant. However, there is no easy way around this. This is one of the drawbacks to having a useful tool available to us—a minor drawback at that. If you're only interested in the theme, you simply need to extract the theme folder from the ZIP archive and copy it to your jQuery UI application directory. You then need to update your path in your HTML in including the appropriate CSS file. You'll also notice that after clicking on the Download button from the theme gallery, you're brought to the download page with an ugly URL. That is, you'll see something like /download/?themeParams=%3FffDefault instead of just /download. This is a requirement of the ThemeRoller application that allows developers to edit existing themes or to roll their own. Without these parameters, we wouldn't be able to download themes we have made changes to. The jQuery UI download page also includes an Advanced Settings section that is hidden by default. This is because you rarely need to use it. It allows you to set the CSS scope for your theme, useful if you're using multiple themes in a single user interface. This isn't a recommended practice; the key idea behind jQuery UI themes is consistency. The advanced settings also lets you change the name of the downloaded theme folder. This can be useful if you plan on changing your theme later, but you can always rename the folder after downloading it.
Read more
  • 0
  • 0
  • 2523
article-image-play-framework-binding-and-validating-objects-and-rendering-json-output
Packt
03 Aug 2011
4 min read
Save for later

Play Framework: Binding and Validating Objects and Rendering JSON Output

Packt
03 Aug 2011
4 min read
Binding and validating objects using custom binders Read the Play documentation about binding and validating objects. As validation is extremely important in any application, it basically has to fulfill several tasks. First, it should not allow the user to enter wrong data. After a user has filled a form, he should get a positive or negative feedback, irrespective of whether the entered content was valid or not. The same goes for storing data. Before storing data you should make sure that storing it does not pose any future problems as now the model and the view layer should make sure that only valid data is stored or shown in the application. The perfect place to put such a validation is the controller. As a HTTP request basically is composed of a list of keys and values, the web framework needs to have a certain logic to create real objects out of this argument to make sure the application developer does not have to do this tedious task. You can find the source code of this example in the chapter2/binder directory. How to do it... Create or reuse a class you want created from an item as shown in the following code snippet: public class OrderItem { @Required public String itemId; public Boolean hazardous; public Boolean bulk; public Boolean toxic; public Integer piecesIncluded; public String toString() { return MessageFormat.format("{0}/{1}/{2}/{3}/{4}", itemId, piecesIncluded, bulk, toxic, hazardous); } } Create an appropriate form snippet for the index.xml template: #{form @Application.createOrder()} <input type="text" name="item" /><br /> <input type="submit" value="Create Order"> #{/form} Create the controller: public static void createOrder(@Valid OrderItem item) { if (validation.hasErrors()) { render("@index"); } renderText(item.toString()); } Create the type binder doing this magic: @Global public class OrderItemBinder implements TypeBinder<OrderItem> { @Override public Object bind(String name, Annotation[] annotations, String value, Class actualClass) throws Exception { OrderItem item = new OrderItem(); List<String> identifier = Arrays.asList(value.split("-", 3)); if (identifier.size() >= 3) { item.piecesIncluded = Integer.parseInt(identifier.get(2)); } if (identifier.size() >= 2) { int c = Integer.parseInt(identifier.get(1)); item.bulk = (c & 4) == 4; item.hazardous = (c & 2) == 2; item.toxic = (c & 1) == 1; } if (identifier.size() >= 1) { item.itemId = identifier.get(0); } return item; } } How it works... With the exception of the binder definition all of the preceding code has been seen earlier. By working with the Play samples you already got to know how to handle objects as arguments in controllers. This specific example creates a complete object out of a simple String. By naming the string in the form value (<input …name="item" />) the same as the controller argument name (createOrder(@Valid OrderItem item)) and using the controller argument class type in the OrderItemBinder definition (OrderItemBinder implements TypeBinder<OrderItem>), the mapping is done. The binder splits the string by a hyphen, uses the first value for item ID, the last for piìesIncluded, and checks certain bits in order to set some Boolean properties. By using curl you can verify the behavior very easily as shown: curl -v -X POST --data "item=Foo-3-5" localhost:9000/order Foo/5/false/true/true Here Foo resembles the item ID, 5 is the piecesIncluded property, and 3 is the argument means that the first two bits are set and so the hazardous and toxic properties are set, while bulk is not. There's more... The TypeBinder feature has been introduced in Play 1.1 and is documented at http://www.playframework.org/documentation/1.2/controllers#custombinding. Using type binders on objects Currently, it is only possible to create objects out of one single string with a TypeBinder. If you want to create one object out of several submitted form values you will have to create your own plugin for this as workaround. You can check more about this at: http://groups.google.com/group/play-framework/browse_thread/thread/62e7fbeac2c9e42d Be careful with JPA using model classes As soon as you try to use model classes with a type binder you will stumble upon strange behavior, as your objects will always only have null or default values when freshly instanced. The JPA plugin already uses a binding and overwrites every binding you are doing.
Read more
  • 0
  • 0
  • 2640

article-image-integrating-phplist-2-facebook
Packt
02 Aug 2011
3 min read
Save for later

Integrating phpList 2 with Facebook

Packt
02 Aug 2011
3 min read
  PHPList 2 E-mail Campaign Manager Prerequisites For this section, we'll make the following assumptions: We already have a Facebook account We already have a Facebook page We already have the Facebook developer's application installed (http://www.facebook.com/developers) Preparing phpList Facebook allows us to include any content on our page in an iframe with a maximum width of 520 px. phpList's default theming won't fit in 520 px and so it will either get cut off and look odd, or will invoke awkward scroll bars in the middle of the page. To resolve this, we'll need to change the styling of phpList. Note that this will also affect how the public URLs to our phpList site are displayed outside of Facebook (that is, the default sign up page). Navigate to the configure page in phpList's admin interface, using the right-hand navigation panel: Scroll down to the section starting with Header of public pages and click on edit. This is the HTML code that is added to the top of every public (not admin) page. In the following example, we've removed the background image, the HTML table, and images, but left the CSS styling unchanged: Having saved your changes, edit the next section labeled Footer of public pages and make the corresponding changes: Remember that the actual content that the user sees will be "sandwiched" between the header and footer. This means that if you open a tag in the header, you need to make sure it's closed again in the footer. Again in this example, we just closed the HTML body tag in the footer: Having changed the header and footer of the public pages, browse to your default public page (http://your-site.com/lists/, for example) to see how the page looks: Note that there is hardly any styling now, but that there are no fixed-width elements which will cause issues with our iframe. Tweaking the design of using the public header and footer code is a task left to the reader. Creating the Facebook app Before we can add phpList to our Facebook page, we need to create an App. From http://www.facebook.com/developers/, click on the Set Up New App button: Click the radio button to indicate that you agree to the Facebook terms and then click on Create App: Prove you're a human by completing the CAPTCHA: You're taken to the edit page for your new app. Under the Facebook Integration section, enter at least the following details: IFrame Size: Auto-resize (we don't want scrollbars) Tab Name (what the tab will be called when your page is displayed) Tab URL (the full URL to the page you want loaded in your iframe. Generally, this would be a phpList subscribe page) Once you've saved your changes, you're taken to your list of applications. Click on Application Profile Page to see the application as other Facebook users would see it (as opposed to the developer): On the application's profile page, click on Add to My Page to add this application to your Facebook page: When prompted, choose which of your pages you want to add the application to. In this example, we've created a page for this article, so we add the application to this page:  
Read more
  • 0
  • 0
  • 1271