Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-games-fortune-scratch-14
Packt
15 Oct 2009
4 min read
Save for later

Games of Fortune with Scratch 1.4

Packt
15 Oct 2009
4 min read
Fortune-teller Most of us enjoy a good circus, carnival, or county fair. There's fun, food, and fortunes. Aah, yes, what would a fair be without the fortune-teller's tent? By the end of this article, you'll know everything you need to spin your fortunes and amaze your friends with your wisdom. Before we start the first exercise, create a new project and add two sprites. The first sprite will be the seeker. The second sprite will be the teller. Choose any sprites you want. My seeker will be a clam and my teller will be a snowman. If you want to add a background, go ahead. Time for action – create a list of questions In order to have a successful fortune-telling, we need two things: a question and an answer. Let's start by defining some questions and answers: Select the seeker from the list of sprites. From the Variables palette, click the Make a list button. In the list name dialog box, type questions and select For this sprite only. Click OK to create the list. Several new blocks display in the Variables palette, and an empty block titled seeker questions displays on the stage. Let's think about a couple of questions we may be tempted to ask, such as the following: Will my hair fall out? How many children will I have? Let's add our proposed questions to the questions list. Click the plus sign located in the bottom-left corner of the seeker questions box (on the stage) to display a text input field. Type Will my hair fall out? Press the plus sign again and enter the second question: How many children will I have? We now have two questions in our list. To automatically add the next item in the list, press enter. Let's add a say for 2 secs block to the scripts area of the seeker sprite so that we can start the dialog. From the Variables palette, drag the item of questions block to the input value of the say for 2 secs block. Double-click on the block and the seeker asks, "Will my hair fall out?" Change the value on the item block to last and double-click the block again. This time the seeker asks, "How many children will I have?" What just happened? I'm certain you could come up with a hundred different questions to ask a fortune-teller. Don't worry, you'll get your chance to ask more questions later. Did you notice that the new list we created behaved a lot like a variable? We were able to make the questions list private; we don't want our teller to peek at our questions, after all. Also, the list became visible on the screen allowing us to edit the contents. The most notable difference is that we added more than one item, and each item corresponds to a number. We essentially created a numbered list. If you work with other programming languages, then you might refer to lists as arrays. Because the seeker's questions were contained in a list, we used the item block to provide special instructions to the     say block in order to ask the question. The first value of the item block was position, which defaulted to one. The second value was the name of the list, which defaulted to questions. In contrast, if we used a variable to store a question, we would only need to supply the name of the variable to the say block. Have a go hero Create an answers list for the teller sprite, and add several items to the list. Remember, there are no wrong answers in this exercise. Work with an item in a list We can use lists to group related items, but accessing the items in the list requires an extra level of specificity. We need to know the name of the list and the position of the item within the list before we can do anything with the values. The following table shows the available ways to access a specific item in a list.
Read more
  • 0
  • 0
  • 3302

article-image-html-php-and-content-posting-drupal-6
Packt
15 Oct 2009
9 min read
Save for later

HTML, PHP, and Content Posting in Drupal 6

Packt
15 Oct 2009
9 min read
Input Formats and Filters It is necessary to stipulate the type of content we will be posting, in any given post. This is done through the use of the Input format setting that is displayed when posting content to the site—assuming the user in question has sufficient permissions to post different types of content. In order to control what is and is not allowed, head on over to the Input formats link under Site configuration. This will bring up a list of the currently defined input formats, like this: At the moment, you might be wondering why we need to go to all this trouble to decide whether people can add certain HTML tags to their content. The answer to this is that because both HTML and PHP are so powerful, it is not hard to subvert even fairly simple abilities for malicious purposes. For example, you might decide to allow users the ability to link to their homepages from their blogs. Using the ability to add a hyperlink to their postings, a malicious user could create a Trojan, virus or some other harmful content, and link to it from an innocuous and friendly looking piece of HTML like this: <p>Hi Friends! My <a href="link_to_trojan.exe">homepage</a> is a great place to meet and learn about my interests and hobbies. </p> This snippet writes out a short paragraph with a link, supposedly to the author's homepage. In reality, the hyperlink reference attribute points to a trojan, link_to_trojan.exe. That's just HTML! PHP can do a lot more damage—to the extent that if you don't have proper security or disaster-recovery policies in place, then it is possible that your site can be rendered useless or destroyed entirely. Security is the main reason why, as you may have noticed from the previous screenshot, anything other than Filtered HTML is unavailable for use by anyone except the administrator. By default, PHP is not even present, let alone disabled. When thinking about what permissions to allow, it is important to re-iterate the tenet: Never allow users more permissions than they require to complete their intended tasks! As they stand, you might not find the input formats to your liking, and so Drupal provides some functionality to modify them. Click on the configure link adjacent to the Filtered HTML option, and this will bring up the following page: The Edit tab provides the option to alter the Name property of the input format; the Roles section in this case cannot be changed, but as you will see when we come around to creating our own input format, roles can be assigned however you wish to allow certain users to make use of an input format, or not. The final section provides a checklist of the types of Filters to apply when using this input format. In this previous screenshot, all have been selected, and this causes the input format to apply the: HTML corrector – corrects any broken HTML within postings to prevent undesirable results in the rest of your page. HTML filter – determines whether or not to strip or remove unwanted HTML. Line break converter – Turns standard typed line breaks (i.e. whenever a poster clicks Enter) into standard HTML. URL filter – allows recognized links and email addresses to be clickable without having to write the HTML tags, manually. The line break converter is particularly useful for users because it means that they do not have to explicitly enter <br> or <p> HTML tags in order to display new lines or paragraph breaks—this can get tedious by the time you are writing your 400th blog entry. If this is disabled, unless the user has the ability to add the relevant HTML tags, the content may end up looking like this: Click on the Configure tab, at the top of the page, in order to begin working with the HTML filter. You should be presented with something like this: The URL filter option is really there to help protect the formatting and layout of your site. It is possible to have quite long URLs these days, and because URLs do not contain spaces, there is nowhere to naturally split them up. As a result, a browser might do some strange things to cater for the long string and whatever it is; this will make your site look odd. Decide how many characters the longest string should be and enter that number in the space provided. Remember that some content may appear in the sidebars, so you can't let it get too long if they is supposed to be a fixed width. The HTML filter section lets you specify whether to Strip disallowed tags, or escape them (Escape all tags causes any tags that are present in the post to be displayed as written). Remember that if all the tags are stripped from the content, you should enable the Line break converter so that users can at least paragraph their content properly. Which tags are to be stripped is decided in the Allowed HTML tags section, where a list of all the tags that are to be allowed can be entered—anything else gets handled appropriately. Selecting Display HTML help forces Drupal to provide HTML help for users posting content—try enabling and disabling this option and browsing to this relative URL in each case to see the difference: filter/tips. There is quite a bit of helpful information on HTML in the long filter tips; so take a moment to read over those. The filter tips can be reached whenever a user expands the Input format section of the content post and clicks on More information about formatting options at the bottom of that section. Finally, the Spam link deterrent is a useful tool if the site is being used to bombard members with links to unsanctioned (and often unsavory) products. Spammers will use anonymous accounts to post junk (assuming anonymous users are allowed to post content) and enabling this for anonymous posts is an effective way of breaking them. This is not the end of the story, because we also need to be able to create input formats in the event we require something that the default options can't cater for. For our example, there are several ways in which this can be done, but there are three main criteria that need to be satisfied before we can consider creating the page. We need to be able to: Upload image files and attach them to the post. Insert and display the image files within the body of the post. Use PHP in order to dynamically generate some of the content (this option is really only necessary to demonstrate how to embed PHP in a posting for future reference). There are several methods for displaying image files within posts. The one we will discuss here, does not require us to download and install any contribution modules, such as Img_assist. Instead, we will use HTML directly to achieve this, specifically, we use the <img> tag. Take a look at the previous screenshot that shows the configure page of the Filtered HTML input format. Notice that the <img> tag is not available for use. Let's create our own input format to cater for this, instead of modifying this default format. Before we do, first enable the PHP Filter module under Modules in Site building so that it can easily be used when the time comes. With that change saved, you will find that there is now an extra option to the Filters section of each input format configuration page: It's not a good idea to enable the PHP evaluator for either of the default options, but adding it to one of our own input formats will be ok to play with. Head on back to the main input formats page under Site configuration (notice that there is an additional input format available, called PHP code) and click on Add input format. This will bring up the same configuration type page we looked at earlier. It is easy to implement whatever new settings you want, based on how the input format is to be used. For our example, we need the ability to post images and make use of PHP scripts, so make the new input format as follows: As we will need to make use of some PHP code a bit later on, we have enabled the PHP evaluator option, as well as prevented the use of this format for anyone but ourselves—normally, you would create a format for a group of users who require the modified posting abilities, but in this case, we are simply demonstrating how to create a new input format; so this is fine for now. PHP should not be enabled for anyone other than yourself, or a highly trusted administrator who needs it to complete his or her work. Click Save configuration to add this new format to the list, and then click on the Configure tab to work on the HTML filter. The only change required between this input format and the default Filtered HTML, in terms of HTML, is the addition of the <img> and <div> tags, separated by a space in the Allowed HTML tags list, as follows: As things stand at the moment, you may run into problems with adding PHP code to any content postings. This is because some filters affect the function of others, and to be on the safe side, click on the Rearrange tab and set the PHP evaluator to execute first: Since the PHP evaluator's weight is the lowest, it is treated first, with all the others following suit. It's a safe bet that if you are getting unexpected results when using a certain type of filter, you need to come to this page and change the settings. We'll see a bit more about this, in a moment. Now, the PHP evaluator gets dibs on the content and can properly process any PHP. For the purposes of adding images and PHP to posts (as the primary user), this is all that is needed for now. Once satisfied with the settings save the changes. Before building the new page, it is probably most useful to have a short discourse on HTML, because it is a requirement if you are to attempt more complex postings.  
Read more
  • 0
  • 1
  • 20066

article-image-drupal-6-social-networking-communicating-users
Packt
14 Oct 2009
6 min read
Save for later

Drupal 6 Social Networking: Communicating with Users

Packt
14 Oct 2009
6 min read
Getting started We are going to look at a few different modules, some of which we will use. These need to be installed first, so let's do that now to save us time. The modules We need to download the following modules: Addresses module (http://drupal.org/project/addresses) enable the Addresses, Addresses - Phone/Fax and Addresses - Users components. Simplenews module (http://drupal.org/project/simplenews) And extract them to our sites/all/modules folder, and enable them via the administration interface. A look back We have already looked at one very important aspect to communicate with our users—user e-mail settings. Within the User settings page (Administer | User management | User settings), we have a group of settings under the heading User e-mail settings. These are various email templates that are sent to our users upon certain events, such as registration, account activation, password reset, account being blocked or account being deleted. The content of these emails can be very important depending on the nature of the web site. In our Dino Space site, we may use a very informal, welcoming and fun tone for our automated emails. But for a business-oriented social network, we would want to use a much more formal tone. Modules Don't forget, many modules also have their own email templates for sending emails to users, all of which can normally be changed easily from their respective sections in the administration area. Communicating on an individual basis As we have installed the contact form module on our site, we can also communicate with our users on an individual basis using the contact forms on their profiles. This is handy for those times when we do need to contact an individual user, maybe because of complaints against them by other members of the community, or perhaps to invite them to become a moderator or contributor to the site. Alternatively, we can contact the user directly via their email addresses listed in their accounts, as this is viewable from the administration area. Inactive users We may wish to contact users who have not been active on the site for a long time, to remind them that the site is still there, and that they would be welcome to become active in the community once again. Drupal records the time a user was last active, which allows us to easily sort the list of users by their activity. A module (Inactive user) is available for Drupal 5, which is intended to contact inactive users automatically, but (at the time of writing this) one is not available for Drupal 6. You may wish to keep watch on the modules list on the Drupal.org web site to see if anything comes up in future http://drupal.org/project/inactive_user Communicating with individuals publicly Don't forget, we also have access to all of the communication methods available for our users to communicate with one another, such as replying to posts, commenting on content, or posting on their profiles. So if we need to contact a user, and we can contact them publicly, we can use these features. Mailing lists Drupal has a number of modules available for sending emails to our users. Many of them are still currently under heavy development, or had their development stopped after the release of a previous version of Drupal. One of these modules is Simplenews, which is a native Drupal system for managing newsletters. One limitation of the Simplenews module, and most of the modules available, is that it can't send to all our users; it requires users to subscribe to the mailing list. We can manage the Simplenews module via Administer | Newsletter. The features available to us are quite comprehensive. Let's have a look at how the module works: Newsletters are created and managed from here Users subscribe to various Newsletters Users can be imported into Newsletters to become a subscriber A message is sent to a newsletter (this is referred to as an issue) by creating Newsletters content Issues which have been sent are saved within the module Issues which have not yet been sent are saved within the module as drafts By default, we have a newsletter, which is generic to our site based on our site name. From here we can also create new Newsletters should we wish so. The Subscriptions tab allows us to see and manage the subscriptions to our various newsletters, the Sent issues tab lists issues sent out to the newsletter lists, and the Drafts tab lists issues which are still being written. From within the Settings tab, we can set how new issues for newsletters are created, as well as the email address shown as the sender of issues. Don't forget to set the permissions; you want your users to be able to subscribe to newsletters. Users can subscribe to newsletters from within their account, or we can enable blocks for the relevant newsletters we have on our site. To send an "issue" to our newsletter list, we need to create the issue as a new content element via Create content | Newsletter issue. We enter the subject of our email as the Title, select the newsletter to send the message to from the Newsletter drop-down list, and the message is entered into the Bodybox. Beneath these options, we have some newsletter specific-options within the Newsletter sending options box. These options allow us to set the priority of the email message (this is often ignored by email clients), if we wish to request a receipt to see if a user has read the message (this is also often ignored by email clients) and finally, we can select a sending method. There are three sending methods, which are: Don't send now—this won't send the message, and will save it as a draft. Send one test newsletter to the test address—this will send the email message to the test email addresses, which we can set in the administration area. This allows us to review the newsletter, as if we were a subscriber, make any final alterations and then send it to our list. Send newsletter—this sends the email to our newsletter list. How to send an email to all our users? We can use the module to send an email to all of our users, by taking advantage of the subscriber import feature. Within Administer | Content management | Newsletters | Subscriptions, we have the ability to Import subscriptions, as shown in the following screenshot: Importing subscribers consists of entering the E-mail addresses (separated by a comma) and selecting the newsletter which we wish the user to subscribe to. To get all of our current members to subscribe to the mailing list, we could export all of our users' email addresses directly from the Drupal database, using a tool such as phpMyAdmin. If we use the tool correctly, we can even get the data in a comma-separated list ready to be pasted into the form.
Read more
  • 0
  • 0
  • 1697

article-image-creating-administration-interface-django-10
Packt
14 Oct 2009
5 min read
Save for later

Creating an Administration Interface with Django 1.0

Packt
14 Oct 2009
5 min read
Activating the administration interface The administration interface comes as a Django application. To activate it, we will follow a simple procedure that is similar to enabling the user authentication system. The administration application is located in the django.contrib.admin package. So the first step is adding the path of this package to the INSTALLED_APPS variable. Open the settings.py file, locate INSTALLED_APPS, and edit it as follows: INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.admin', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.comments', 'django_bookmarks.bookmarks',) Next, run the following command to create the necessary tables for the administration application: $ python manage.py syncdb Now we need to make the administration interface accessible from within our site by adding URL entries for it. The admin application defines many views (as we will see later), so manually adding a separate entry for each view can become a tedious task. Therefore, the admin interface provides a shortcut for this. There is a single object that encapsulates all the admin views. To use it, open the urls.py file and edit it as follows: from django.contrib import adminadmin.autodiscover()urlpatterns = ('', [...] # Admin interface (r'^admin/(.*)', admin.site.root),) Here, we are importing the admin module, calling a method in it, and mapping all the URLs under the path ^admin/ to a view called admin.site.root. This will make the views of the administration interface accessible from within our project. One last thing remains before we see the administration page in action. We need to tell Django what models can be managed in the administration interface. This is done by creating a new file called the admin.py file in the bookmarks directory. Create the bookmarks/admin.py file and add the following code to it: from django.contrib import adminfrom bookmarks.models import *class LinkAdmin(admin.ModelAdmin): passadmin.site.register(Link, LinkAdmin) We created a class derived from the admin.ModelAdmin class and mapped it to the Link model using the admin.site.register method. This effectively tells Django to enable the Link model in the administration interface. The keyword pass means that the class is empty. Later, we will use this class to customize the administration page; so it won't remain empty. Do the same to the Bookmark, Tag, and SharedBookmark models and add it to the bookmarks/admin.py file. Now, create an empty admin class for each of them and register it. The User model is provided by Django and, therefore, we don't have control over it. But fortunately, it already has an Admin class so it's available in the administration interface by default. Next, launch the development server and direct your browser to http://127.0.0.1:8000/admin/. You will be greeted by a login page. The superuser account after writing the database model is the account that you have to use in order to log in: Next, you will see a list of the models that are available to the administration interface. As discussed earlier, only models that have admin classes in the bookmarks/admin.py file will appear on this page. If you click on a model name, you will get a list of the objects that are stored in the database under this model. You can use this page to view or edit a particular object, or to add a new one. The following figure shows the listing page for the Link model: The edit form is generated according to the fields that exist in the model. The Link form, for example, contains a single text field called Url. You can use this form to view and change the URL of a Link object. In addition, the form performs proper validation of fields before saving the object. So if you try to save a Link object with an invalid URL, you will receive an error message asking you to correct the field. The following figure shows a validation error when trying to save an invalid link: Fields are mapped to form widgets according to their type. For example, date fields are edited using a calendar widget, whereas foreign key fields are edited using a list widget, and so on. The following figure shows a calendar widget from the user edit page. Django uses it for date and time fields. As you may have noticed, the administration interface represents models by using the string returned by the __unicode__ method. It was indeed a good idea to replace the generic strings returned by the default __unicode__ method with more helpful ones. This greatly helps when working with the administration page, as well as with debugging. Experiment with the administration pages. Try to create, edit, and delete objects. Notice how changes made in the administration interface are immediately reflected on the live site. Also, the administration interface keeps a track of the actions that you make and lets you review the history of changes for each object. This section has covered most of what you need to know in order to use the administration interface provided by Django. This feature is actually one of the main advantages of using Django. You get a fully featured administration interface from writing only a few lines of code! Next, we will see how to tweak and customize the administration pages. As a bonus, we will learn more about the permissions system offered by Django.
Read more
  • 0
  • 0
  • 5044

article-image-anatomy-typo3-extension
Packt
14 Oct 2009
8 min read
Save for later

Anatomy of TYPO3 Extension

Packt
14 Oct 2009
8 min read
TYPO3 Extension Categories All TYPO3 extensions are classified into several predefined categories. These categories do not actually differentiate the extensions. They are more like hints for users about extension functionality. Often, it is difficult for the developer to decide which category an extension should belong to. The same extension can provide PHP code that fits into many categories. An extension can contain Frontend (FE) plugins, Backend (BE) modules, static data, and services, all at once. While it is not always the best solution to make such a monster extension, sometimes it is necessary. In this case, the extension author should choose the category that best fits the extension's purpose. For example, if an extension provides a reservation system for website visitors, it is probably FE related, even if it includes a BE module for viewing registrations. If an extension provides a service to log in users, it is most likely a service extension, even if it logs in FE users. It will be easier to decide where the extension fits after we review all the extension categories in this article. Choosing a category for an extension is mandatory. While the TYPO3 Extension Manager can still display extensions without a proper category, this may change and such extensions may be removed from TER (TYPO3 Extension Repository) in the future. The extension category is visible in several places. Firstly, extensions are sorted and grouped by category in the Extension Manager. Secondly, when an extension is clicked in the Extension Manager, its category is displayed in the extension details. If an extension's category is changed from one to another, it does not affect extension functionality. The Extension Manager will show the extension in a different category. So, categories are truly just hints for the user. They do not have any significant meaning in TYPO3. So, why do we care and talk about them? We do so because it is one of those things that make a good extension. If an extension developer starts making a new extension, they should do it properly from the very beginning. And one of the first things to do properly is to decide where an extension belongs. So, let's look into the various extension categories in more detail. Category: Frontend Extensions that belong to the Frontend category provide functionality related to the FE. It does not mean that they generate website output. Typically, extensions from the FE category extend FE functionality in other ways. For example, they can transform links from standard /index.php?id=12345 to /news/new-typo3-bookis-out.htm. Or, they can filter output and clean it up, compress, add or remove HTML comments, and so on. Often, these extensions use one or more hooks in the FE classes. For example, TSFE has hooks to process submitted data, or to post‑filter content (and many others). Examples of FE extensions are source_optimization and realurl. Category: Frontend plugins Frontend plugins is possibly the most popular extension category. Extensions from this category typically generate content for the website. They provide new content objects, or extend existing types of content objects. Typical examples of extensions from the Frontend plugins category are tt_news, comments, ratings, etc. Category: Backend Extensions from the Backend category provide additional functionality for TYPO3 Backend. Often, they are not seen inside TYPO3 BE, but they still do some work. Examples of such extensions are various debugging extensions (such as rlmp_ filedevlog) and extensions that add or change the pop-up menu in the BE (such as extra_page_cm_options system extension). This category is rarely used because extensions belonging to it are very special. Category: Backend module Extensions from this category provide additional modules for TYPO3 BE. Typical examples are system extensions such as beuser (provides Tools | Users module) or tstemplate (provides Web | Template module). Category: Services Services extend core TYPO3 functionality. Most known and most popular service extensions are authentication services. TYPO3 Extension Repository contains extensions to authenticate TYPO3 users over phpBB, vBulletine, or LDAP user databases. Services are somewhat special and will not be covered in this article. Extension developers who are interested in the development of services should consult appropriate documentation on the typo3.org website. Category: Examples Extensions from this category provide examples. There are not many, and are typically meant for beginners or for those who want to learn a specific feature of TYPO3, or features that another TYPO3 extension provides. Category: Templates Extensions from this category provide templates. Most often, they have preformatted HTML and CSS files in order to use them with the templateautoparser extension or map with TemplaVoila. Sometimes, they also contain TypoScript templates, for example, tmpl_andreas01 and tmpl_andreas09 extensions. Once installed, they provide pre‑mapped TemplaVoila templates for any website, making it easy to have a website up and running within minutes. Category: Documentation Documentation extensions provide TYPO3 documentation. Normally, TYPO3 extensions contain documentation within themselves, though sometimes, a document is too big to be shipped with extensions. In such cases, it is stored separately. There is an unofficial convention to start an extension key for such extensions with the doc_ prefix (that is, doc_indexed_search). Category: Miscellaneous Everything else that does not fit into any other category goes here; typical examples are skins. But do not put your extension here if you just cannot decide where it fits. In all probability, it should go into one of the other categories, not into Miscellaneous. Extension Files TYPO3 extensions consist of several files. Some of these files have predefined names, and serve a predefined purpose. Others provide code or data but also follow certain naming conventions. We will review all the predefined files in this article and see what purpose they serve. We will look into the files according to their logical grouping. While reading this section, you can take any extension from the typo3conf/ext/ directory at your TYPO3 installation and check the contents of each discussed file. Some files may be missing if the extension does not use them. There is only one file which is mandatory for any TYPO3 extension, ext_emconf.php. We will start examining files starting from this one. Common Files All files from this group have predefined names, and TYPO3 expects to find certain information in them. Hacking these files to serve another purpose or to have a different format usually results in incompatibility with other extensions or TYPO3 itself. While it may work in one installation, it may fail in others. So, avoid doing anything non-standard with these files. ext_emconf.php This is the only required file for any TYPO3 extension. And this is the only file that should be modified with great care. If it is corrupt, TYPO3 will not load any extension. This file contains information on the TYPO3 Extension Manager. This information tells the Extension Manager what the extension does, provides, requires, and conflicts with. It also contains a checksum for each file in the extension. This checksum is updated automatically when the extension is sent to TER (TYPO3 Extension Repository). The server administrator can easily check if anyone has hijacked the extension files by looking into the extension details in the Extension Manager. The modified files are shown in red. Here is a tip. If you (as an extension developer) send your own extension directly to the customer (bypassing TER upload), or plan to use it on your own server, always update the ext_emconf.php file using the Backup/Delete function of the Extension Manager. This will ensure that TYPO3 shows up-to-date data in the Extension Manager. Here is an example of a ext_emconf.php file from the smoothuploader extension: <?php ############################################################# # Extension Manager/Repository config file for ext: ↵ # "smoothuploader" # Auto generated 29-02-2008 12:36 # Manual updates: # Only the data in the array - anything else is removed by ↵ # next write. # "version" and "dependencies" must not be touched! ############################################################# $EM_CONF[$_EXTKEY] = array( 'title' => 'SmoothGallery Uploader', 'description' => 'Uploads images to SmoothGallery', 'category' => 'plugin', 'author' => 'Dmitry Dulepov [Netcreators]', 'author_email' => 'dmitry@typo3.org', 'shy' => '', 'dependencies' => 'rgsmoothgallery', 'conflicts' => '', 'priority' => '', 'module' => '', 'state' => 'beta', 'internal' => '', 'uploadfolder' => 0, 'createDirs' => '', 'modify_tables' => 'tx_rgsmoothgallery_image', 'clearCacheOnLoad' => 0, 'lockType' => '', 'author_company' => 'Netcreators BV', 'version' => '0.3.0', 'constraints' => array( 'depends' => array( 'rgsmoothgallery' => '1.1.1-', ), 'conflicts' => array( ), 'suggests' => array( ), ), '_md5_values_when_last_written' => 'a:12:{s:9:...;}', 'suggests' => array( ), ); ?> The variable _md5_values_when_last_written is shortened in the listing above.
Read more
  • 0
  • 0
  • 3221

article-image-building-facebook-application-part-1
Packt
14 Oct 2009
4 min read
Save for later

Building a Facebook Application: Part 1

Packt
14 Oct 2009
4 min read
A simple Facebook application Well, with the Facebook side of things set up, it's now over to your server to build the application itself. The server could of course be: Your web host's server – This must support PHP, and it may be worthwhile for you to check if you have any bandwidth limits. Your own server – Obviously, you'll need Apache and PHP (and you'll also need a fixed IP address). Getting the server ready for action Once you have selected your server, you'll need to create a directory in which you'll build your application, for example: mkdir -p /www/htdocs/f8/penguin_picd /www/htdocs/f8/penguin_pi If you haven't already done so, then this is the time to download and uncompress the Facebook Platform libraries: wget http://developers.facebook.com/clientlibs/facebook-platform.tar.gztar -xvzf facebook-platform.tar.gz We're not actually going to use all of the files in the library, so you can copy the ones that you're going to use into your application directory: cp facebook-platform/client/facebook.phpcp facebook-platform/client/facebookapi_php5_restlib.php And once that's done, you can delete the unwanted files: rm -rf facebook-platform.tar.gz facebook-platform Now, you're ready to start building your application. Creating your first Facebook application Well, you're nearly ready to start building your application. First, you'll need to create a file (let's call it appinclude.php) that initiates the application. The application initiation code We've got some code that needs to be executed every time our application is accessed, and that code is: <?phprequire_once 'facebook.php'; #Load the Facebook API$appapikey = '322d68147c78d2621079317b778cfe10'; #Your API Key$appsecret = '0a53919566eeb272d7b96a76369ed90c'; #Your Secret$facebook = new Facebook($appapikey, $appsecret); #A Facebook object$user = $facebook->require_login(); #get the current user$appcallbackurl = 'http://213.123.183.16/f8/penguin_pi/'; #callback Url#Catch an invalid session_keytry { if (!$facebook->api_client->users_isAppAdded()) { $facebook->redirect($facebook->get_add_url()); }} catch (Exception $ex) { #If invalid then redirect to a login prompt $facebook->set_user(null, null); $facebook->redirect($appcallbackurl);}?> You'll notice that the code must include your API Key and your secret (they were created when you set up your application in Facebook). The PHP file also handles any invalid sessions. Now, you're ready to start building your application, and your code must be written into a file named index.php. The application code Our application code needs to call the initiation file, and then we can do whatever we want: <?phprequire_once 'appinclude.php'; #Your application initiation fileecho "<p>Hi $user, ";echo "welcome to Pygoscelis P. Ellsworthy's Suspect Tracker</p>";?> Of course, now that you've written the code for the application, you'll want to see what it looks like. Viewing the new application Start by typing your Canvas Page URL into a browser (you'll need to type in your own, but in the case of Pygoscelis P. Ellesworthy's Suspect Tracker, this would be http://apps.facebook.com/penguin_pi/): You can then add the application just as you would add any other application: And at last, you can view your new application: It is worth noting, however, that you won't yet be able to view your application on your profile. For the time being, you can only access the application by typing in your Canvas Page URL. That being said, your profile will register the fact that you've added your application: That's the obligatory "Hello World" done. Let's look at how to further develop the application.
Read more
  • 0
  • 0
  • 2469
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-content-editing-and-management-open-souce-cms
Packt
14 Oct 2009
11 min read
Save for later

Content Editing and Management in an Open Souce CMS

Packt
14 Oct 2009
11 min read
There are exciting things ahead in this article, so let's get started. Adding content to our site Adding, updating, and deleting page content is at the heart of a CMS. We will use the Joomla! content management system for our examples in this article. Joomla! is a very popular and powerful CMS. Let's see how we can manage content with Joomla!. Time for action-adding a page Log in to the administration section of Joomla!. It is generally athttp://yoursite.com/joomla/administrator/. Click on the large icon that says Add New Article. We want to create a page about Surya Namaskara, or Sun Salutation, one of the most popular yoga postures. Enter Surya Namaskara in the Title field, and Sun Salutation in the Alias field. We have already created a few sections and categories in Joomla!. Select Posturesas Section, and Featured as Category from the drop downs. The Word-like area below is a content editor. It is also known as the WYSIWYG (What You See Is What You Get) editor. Type in the following text in the area that looks like a white page. We took this text from Wikipedia, but you can type a statement of your choice. Surya Namaskara or Sun Salutation (lit. "salute to the sun"), is a common sequence of Hatha yoga asanas. Its origins lie in a worship of Surya, the Hindu solar deity. Don't see a Word-like editor? If you don't see a Word-like text editor, you may be missing some browser plug-ins. Your browser may warn you of missing plug-ins. In such a case, go ahead and install the missing plug-ins. If it still does not work, go toSite | Global Configuration | Site | Site Settings | Default WYSIWYG Editor and select TinyMCE or XStandard. You can also configure the editor per user from User Manager. Press Enter after the first paragraph. Add two more sentences like this: Surya Namaskara is an excellent exercise for the whole body. Mastering this asana will help you stay fit forever. "Asana" is the Sanskrit word for posture. Yoga postures are called Asanas. We want to highlight that Surya Namaskara is an excellent exercise for the whole body. Select that portion of text and click on the B icon to make it bold. You will immediately see the result in the editing window. At this stage, your editing window will look like this. If you want to write additional text, go ahead and add it. Click on the large Save icon at the top right of the page when you are done. Now our content is saved. Click on the Preview link in the Joomla! menu bar and you will see the content on the site's home page. Here's how it will look: What just happened? We used Joomla! to create our first content page. We added a page title, an alias, and the section and category this page belongs to. We then used a Word-like editor to enter text for our page. We emphasized keywords by making them bold. This was done by selecting the keywords, and clicking on the B icon button in the toolbar. Notice that we can use this editor to apply a variety of other formatting to selected text. This kind of text editor is called aWYSIWYG editor. What is WYSIWYG? Why is it important?  WYSIWYG (pronounced 'wize,wig) is an acronym for What You See Is What You Get.The Word-like content editor we saw is WYSIWYG because our page looks the same in the editor as it does on the site. The fonts, formatting, colors, and alignments—all work consistently between the editing interface and the actual site.  Most CMSs come with a WYSIWYG editor. Such editors make it very easy for authors to add content and the formatting style that they like. These formatting options look and behave in a way similar to Microsoft Word or OpenOffice Writer. But the complexity of options provided may vary between CMSs. The following image shows the WYSIWYG editor toolbars of Joomla! (top) and WordPress (bottom). As you see, WordPress offers a simpler editor, but with lesser options. An amateur user will find it easier to work with an editor with fewer choices. As a matter of fact, WordPress's editor toolbar shows only the first row of options by default. You can enable a second row by clicking on the last button in first row: Show / Hide Kitchen Sink. On the other hand, Joomla! comes ready with all options visible. This is useful for a professional who wants better control over content formatting. Evaluate how important is it for you to have a WYSIWYG editor. Also, see if the CMS comes with it by default, or you have to add it via a plug-in or extension. For example, Drupal does not have a WYSIWYG editor module by default; but you can easily add it via a module. This also means some CMSs may not have a WYSIWYG editor. So, if there is no WYSIWYG editor, how do you add content? Well, if your content does not require a fancy format, you can live with simple textual content. Else, you can always use HTML. Surya Namaskara or Sun Salutation (lit. "salute to the sun"), is a common sequence of Hatha yoga asanas. Its origins lie in a worship of Surya, the Hindu solar deity. Do I need to learn HTML?  HTML is the language to layout and format web site pages. If you know HTML, it will be easier to manage your CMS. If HTML is not an option, a WYSIWYG editor can be really helpful. Here are some links for learning the basics of HTML:http://www.html.net/tutorials/html/http://www.w3schools.com/html/DEFAULT.asp Adding images We have added the basic content to our page. Now, we will try to include some pictures in our page. Images add a lot of meaning to the content, apart from adding a decorative value. Let's add an image to our page now. Time for action-adding images If you are not already logged in to the Joomla! administration, log in now. Click on Site in the main menu. That should open a submenu of site management options. Click on Media Manager. You will see previews of current images in Joomla!. Click on the stories folder to go into it. You will now see images within this folder. Let's create a new folder here to store images of different asanas/postures. In the Create Folder text box near the top right side, type in asanas and click on the button. This should create a new folder within stories. Click on it to move inside. We can now upload an image here. Click within the text box of the Upload File section at the page end. This will bring up a dialog window to select a file you want to upload. We want to upload an image for Surya Namaskara. Select an image of your choice. Now click on the Start Upload button.                                               File uploading requires correct permissions on the server To upload files to your site, you require correct permissions on yourserver. In technical terms, this is called making a folder world-writable or changing mode to 777. You can change folder permissions using an FTPapplication, or your site's control panel. Technically, it's sufficient to give a 666permission—read-and-write permission to the owner, group, and others—butnormally everyone gives a 777 permission, including execute permission for allthree. Here's a screenshot of setting these permissions using FireFTP, an FTPextension for the Firefox browser. The file upload operation may take a few seconds to complete, depending on image size. Once the image is uploaded, you will see its thumbnail in the list. Upload more images if you want to. Finally, your folder may look like this. We are now ready to insert an image in our page. Select Content  Article Manager  from the main menu. Click on the Surya Namaskara page to edit it. Inside our WYSIWYG editor, keep your cursor where you want to insert the image. Click on the Image button below the WYSIWYG editor. A window will open up with a thumbnail list of images available. Click on the b we created earlier. Click and select an image you want to insert. Add a description and title. Click on the Insert button at the top right. That will insert our image into the content area. Re-size it using the handles on the corners if you wish. Here's how it will look: Congratulations! You have successfully added an image to our page. What just happened?  We uploaded an image from our computer and added it to a page. In the process, we learned about the Media Manager, creating folders, and uploading files to Joomla!. We also learned how to select images to use on a page and even saw image insertion options.  Adding an image involved multiple activities. We had to first add it to the Media Manager.Because this was the first time we were adding an image, we also created a new folder. It was as simple as typing in a name and clicking a button.  We added images within folders since it will help us manage the images better. Once we add an image to the Media Manager, we can use that image on as many pages as we want. The Image button on the content editing screen allows us to select images to use on that page. It also helps us to add captions and correctly align inserted images with the text. You can also upload images using that image selection window itself.We took the Media Manager route to learn more. You can also upload images using that image selection window itself.We took the Media Manager route to learn more. Have a go hero-image formatting options  We have learned enough about inserting images to content now. It is time we try out something else. Once you insert an image, click on it, and then click on the small photo icon in the WYSIWYG editor's toolbar. Go ahead and try out different image properties, different alignment options, spacing, caption, and alternative text. See how the result changes in the preview.                                                       Don't let your images sink your site!                                                     Make sure your images are optimized and sized for web usage. Avoid changing the width and height via image properties. If you want to show a smaller image than the one you uploaded, resize it using photo editing software and use that new version. Large images take longer to load and can make your site slow.                                                      Have a go hero-adding a video  Our Yoga site may also require videos. Look around and find how a video can be added to the page.  Completed? Alright! We have now looked at how to edit a page and insert images/videos into it. Let's see the other options we have in editing and maintaining site content.
Read more
  • 0
  • 0
  • 1619

article-image-enhancing-user-experience-wordpress-27part-1
Packt
14 Oct 2009
6 min read
Save for later

Enhancing User Experience with WordPress 2.7(Part 1)

Packt
14 Oct 2009
6 min read
As a blogger, I read loads of blog posts every day, on many different blogs. Very often, I'm scared to see how many blogs have a non user-friendly interface. How often does it happen that you can't click on the logo to go back to the blog homepage, or can't find what you're looking for by using the search engine? It is a well known fact that in blogging the content is king, but a nice, user friendly interface makes your blog look a lot more professional, and much easier to navigate. In this article, I'll show you what can be done for enhancing user experience and making your blog a better place. Replacing the Next and Previous links by a paginator When a web site, or blog, publishes lots of articles on a single page, the list can quickly become very long and hard to read. To solve this problem, paginations were created. Pagination allows displaying 10 articles (for example) on a page. If the user wants, then he or she can go to the next page, or click on a page number to directly go to the related page. I definitely don't understand why WordPress still doesn't have a built-in pagination system. Instead, at the bottom of each page you'll find a Next link to go to the next page, and a Previous link to go back. This works fine when you're on page two and would like to go to page three, but what if you're on page one, and remember a very interesting article which was located on page eight? Are you going to browse page per page until you find your article? The answer is yes, because you don't have the choice. You can't jump from page one to page eight. In this recipe, I'll show you how to integrate a pagination plugin in your WordPress blog theme. One very good point of this recipe is that the plugin file is embedded in your theme, so if you're a theme designer, you can distribute a theme which has a built-in pagination system. Getting ready To execute this recipe you need to grab a copy of the WP-PageNavi plugin, which can be found at http://wordpress.org/extend/plugins/wp-pagenavi/. I have used version 2.40 of the Wp-PageNavi plugin in this example. Once you have downloaded it, unzip the zip file but don't install the plugin yet. How to do it Open the WP-PageNavi directory and copy the following files into your WordPress theme directory (For example, http://www.yourblog.com/wp-content/ theme/yourtheme). wp-pagenavi.php wp-pagenavi.css Once done, edit the index.php file. You can do the same with other files, such as categories.php or search.php as well. Find the following code (or similar) in your index.php file: <div class="navigation"> <div class="alignleft"><?php next_posts_link('Previous entries') ?></div> <div class="alignright"><?php previous_posts_link('Next entries') ?></div></div> Replace that with the following code: <?php include('wp-pagenavi.php'); if(function_exists('wp_pagenavi')) { wp_pagenavi(); } ?> Save the index.php file. If you visit your blog now, you'll see that nothing has changed. This is because we have to call a function in the wp-pagenavi.php file. Open this file and find the following code (line 61): function wp_pagenavi($before = '', $after = '') {global $wpdb, $wp_query; We have to call the pagenavi_init() function, so let's do this in the following way: function wp_pagenavi($before = '', $after = '') {global $wpdb, $wp_query;pagenavi_init(); //Calling the pagenavi_init() function Now, save the file and refresh your blog. The pagination is now displayed! This is great news, but the pagination doesn't look good. To solve this problem, you simply have to integrate the wp-pagenavi.css file that you copied earlier in your theme directory. To do so, open the header.php file from your theme and paste the following line between the <head> and </head> tags: <link rel="stylesheet" href="<?php echo TEMPLATEPATH.'/pagenavi. css';?>" type="text/css" media="screen" /> Visit your blog homepage one more time. The pagination looks a lot better. You may have to edit the wp-pagenavi.css file in order to make your pagination look and feel ft your blog style. How it works In this recipe, you have discovered a very useful technique that I often use on my blogs, or in the themes that I distribute—the integration of a WordPress plugin into a theme. When the plugin is integrated into your theme as I have shown you in this example, there's no activation process needed. All of the work is done directly from the theme. The WP-PageNavi plugin itself works by using two values—the number of posts to be displayed per page and the first post to be displayed. Then, it executes the relevant query to WordPress database to get the posts. The pagination bar is calculated by using the total number of posts from your blog, and then dividing this value by the number of posts per page. One good point of this technique is that the plugin is integrated in your blog and you can redistribute the theme if you want. The end user will not have to install or configure anything. Highlighting searched text in search results I must admit that I'm not a big fan of the WordPress built-in search engine. One of its weakest features is the fact that searched text aren't highlighted in the results, so the visitor is unable to see the searched text in the context of your article. Getting ready Luckily, there's a nice hack using regular expressions to automatically highlight searched text in search results. This code has been created by Joost de Valk who blogs at www.yoast.com. How to do it This useful code is definitely easy to use on your own blog: Open your search.php file and find the following: echo $title; Replace it with the following code: <?php $title = get_the_title(); $keys= explode(" ",$s); $title = preg_replace('/('.implode('|', $keys) .')/iu', '<strong class="search-excerpt"></strong>',$title);?> Save the search.php file and open the style.css file. Append the following line to it: strong.search-excerpt { background: yellow; } You're done. Now, the searched text will be highlighted in your search results. How it works This code is using PHP regular expressions to find the searched terms in the text returned by WordPress. When an occurrence has been found, it is wrapped in a <strong> HTML element. Then, I simply used CSS to define a yellow background to this element.
Read more
  • 0
  • 0
  • 1920

article-image-managing-posts-wordpress-plugin
Packt
14 Oct 2009
8 min read
Save for later

Managing Posts with WordPress Plugin

Packt
14 Oct 2009
8 min read
Programming the Manage panel The Manage Posts screen can be changed to show extra columns, or remove unwanted columns in the listing. Let's say that we want to show the post type—Normal, Photo, or Link. Remember the custom field post-type that we added to our posts? We can use it now to differentiate post types. Time for action – Add post type column in the Manage panel We want to add a new column to the Manage panel, and we will call it Type. The value of the column will represent the post type—Normal, Photo, or Link. Expand the admin_menu() function to load the function to handle Manage Page hooks: add_submenu_page('post-new.php', __('Add URL',$this->plugin_domain) , __('URL', $this->plugin_domain) , 1 ,'add-url', array(&$this, 'display_form') );// handle Manage page hooksadd_action('load-edit.php', array(&$this, 'handle_load_edit') );} Add the hooks to the columns on the Manage screen: // Manage page hooksfunction handle_load_edit(){ // handle Manage screen functions add_filter('manage_posts_columns', array(&$this, 'handle_posts_columns')); add_action('manage_posts_custom_column', array(&$this, 'handle_posts_custom_column'), 10, 2);} Then implement the function to add a new Column, remove the author and replace the date with our date format: // Handle Column headerfunction handle_posts_columns($columns){ // add 'type' column $columns['type'] = __('Type',$this->plugin_domain); return $columns;} For date key replacement, we need an extra function:     function array_change_key_name( $orig, $new, &$array ){ foreach ( $array as $k => $v ) $return[ ( $k === $orig ) ? $new : $k ] = $v; return ( array ) $return;} And finally, insert a function to handle the display of information in that column: // Handle Type column displayfunction handle_posts_custom_column($column_name, $id){ // 'type' column handling based on post type if( $column_name == 'type' ) { $type=get_post_meta($id, 'post-type', true); echo $type ? $type : __('Normal',$this->plugin_domain); }} Don't forget to add the Manage page to the list of localized pages: // pages where our plugin needs translation$local_pages=array('plugins.php', 'post-new.php', 'edit.php');if (in_array($pagenow, $local_pages)) As a result, we now have a new column that displays the post type using information from a post custom field. What just happened? We have used the load-edit.php action to specify that we want our hooks to be assigned only on the Manage Posts page (edit.php). This is similar to the optimization we did when we loaded the localization files. The handle_posts_columns is a filter that accepts the columns as a parameter and allows you to insert a new column: function handle_posts_columns($columns){ $columns['type'] = __('Type',$this->plugin_domain); return $columns;} You are also able to remove a column. This example would remove the Author column: unset($columns['author']); To handle information display in that column, we use the handle_posts_custom_column action. The action is called for each entry (post), whenever an unknown column is encountered. WordPress passes the name of the column and current post ID as parameters. That allows us to extract the post type from a custom field: function handle_posts_custom_column($column_name, $id){ if( $column_name == 'type' ) { $type=get_post_meta($id, 'post-type', true); It also allows us to print it out: echo $type ? $type : __('Normal',$this->plugin_domain); }} Modifying an existing column We can also modify an existing column. Let's say we want to change the way Date is displayed. Here are the changes we would make to the code: // Handle Column headerfunction handle_posts_columns($columns){ // add 'type' column $columns['type'] = __('Type',$this->plugin_domain); // remove 'author' column //unset($columns['author']); // change 'date' column $columns = $this->array_change_key_name( 'date', 'date_new', $columns ); return $columns;}// Handle Type column displayfunction handle_posts_custom_column($column_name, $id){ // 'type' column handling based on post type if( $column_name == 'type' ) { $type=get_post_meta($id, 'post-type', true); echo $type ? $type : __('Normal',$this->plugin_domain); } // new date column handling if( $column_name == 'date_new' ) { the_time('Y-m-d <br > g:i:s a'); } }function array_change_key_name( $orig, $new, &$array ){ foreach ( $array as $k => $v ) $return[ ( $k === $orig ) ? $new : $k ] = $v; return ( array ) $return;} The example replaces the date column with our own date_new column and uses it to display the date with our preferred formatting. Manage screen search filter WordPress allows us to show all the posts by date and category, but what if we want to show all the posts depending on post type? No problem! We can add a new filter select box straight to the Manage panel. Time for action – Add a search filter box Let's start by adding two more hooks to the handle_load_edit() function. The restrict_manage_posts function draws the search box and the posts_where alters the database query to select only the posts of the type we want to show. // Manage page hooksfunction handle_load_edit(){ // handle Manage screen functions add_filter('manage_posts_columns', array(&$this, 'handle_posts_columns')); add_action('manage_posts_custom_column', array(&$this, 'handle_posts_custom_column'), 10, 2); // handle search box filter add_filter('posts_where', array(&$this, 'handle_posts_where')); add_action('restrict_manage_posts', array(&$this, 'handle_restrict_manage_posts'));} Let's write the corresponding function to draw the select box: // Handle select box for Manage pagefunction handle_restrict_manage_posts(){ ?> <select name="post_type" id="post_type" class="postform"> <option value="0">View all types</option> <option value="normal" <?php if( $_GET['post_type']=='normal') echo 'selected="selected"' ?>><?php _e ('Normal',$this->plugin_domain); ?></option> <option value="photo" <?php if( $_GET['post_type']=='photo') echo 'selected="selected"' ?>><?php _e ('Photo',$this->plugin_domain); ?></option> <option value="link" <?php if( $_GET['post_type']=='link') echo 'selected="selected"' ?>><?php _e ('Link',$this->plugin_domain); ?></option> </select> <?php} And finally, we need a function that will change the query to retrieve only the posts of the selected type: // Handle query for Manage pagefunction handle_posts_where($where){ global $wpdb; if( $_GET['post_type'] == 'photo' ) { $where .= " AND ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='post-type' AND metavalue='".__ ('Photo',$this->plugin_domain)."' )"; } else if( $_GET['post_type'] == 'link' ) { $where .= " AND ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='post-type' AND metavalue='".__ ('Link',$this->plugin_domain)."' )"; } else if( $_GET['post_type'] == 'normal' ) { $where .= " AND ID NOT IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='post-type' )"; } return $where;} What just happened? We have added a new select box to the header of the Manage panel. It allows us to filter the post types we want to show. We added the box using the restrict_manage_posts action that is triggered at the end of the Manage panel header and allows us to insert HTML code, which we used to draw a select box. To actually perform the filtering, we use the posts_where filter, which is run when a query is made to fetch the posts from the database. if( $_GET['post_type'] == 'photo' ){ $where .= " AND ID IN (SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='post-type' AND metavalue='".__ ('Photo',$this->plugin_domain)."' )"; If a photo is selected, we inspect the WordPress database postmeta table and select posts that have the post-type key with the value, Photo. At this point, we have a functional plugin. What we can do further to improve it is to add user permissions checks, so that only those users allowed to write posts and upload files are allowed to use it. Quick referencemanage_posts_columns($columns): This acts as a filter for adding/removing columns in the Manage Posts panel. Similarly, we use the function, manage_pages_columns for the Manage Pages panel.manage_posts_custom_column($column, $post_id): This acts as an action to display information for the given column and post. Alternatively, manage_pages_custom_column for Manage Pages panel.posts_where($where): This acts as a filter for the where clause in the query that gets the posts.restrict_manage_posts: This acts as an action that runs at the end of the Manage panel header and allows you to insert HTML.
Read more
  • 0
  • 0
  • 3365

article-image-autoproxy-spring-aspect-oriented-programming-aop
Packt
14 Oct 2009
5 min read
Save for later

Autoproxy in Spring Aspect-Oriented Programming (AOP)

Packt
14 Oct 2009
5 min read
Autoproxy with classic Spring By using the class ProxyFactoryBean, AOP can be used in a classic way. But writing separately for each bean on which we want to apply an advisor is not a pleasant thing to see, especially if they are many. So let's consider it as a practicable way only if the beans to be configured in that modality are few. On the other hand, if the beans to which we have to apply AOP are many, in order to avoid finding ourselves with very long configuration files, we adopt another tactic: We use the auto proxy creator's system, which allows us to automatically create proxies for the beans and prevent using ProxyFactoryBean. There are two classes made available by Spring to allow the auto proxy creator: BeanNameAutoProxyCreator and DefaultAdvisorAutoProxyCreator. BeanNameAutoProxyCreator BeanNameAutoProxyCreator just has a list of beans names to which proxy can be created automatically. The way in which the autoproxy is created is really simple. It implements the BeanPostProcessor interface, which in its implementation replaces the bean (target) with a proxy. Example: This is the interface describing an animal. package org.springaop.chapter.three.autoproxy.domain;public interface Animal { public Integer getNumberPaws(); public Boolean hasTail(); public boolean hasFur(); public Boolean hasHotBlood(); } The (interface) Bird extends Animal. package org.springaop.chapter.three.autoproxy.domain;public interface Bird extends Animal{ public Boolean hasBeak(); public Boolean hasFeathers(); } The class that implements the Animal interface to describe Cat: package org.springaop.chapter.three.autoproxy.domain;public class Cat implements Animal{ public boolean hasFur() { return true; } public Integer getNumberPaws() { return 4; } public Boolean hasTail() { return true; } public Boolean hasHotBlood() { return true; } public void setSpecies(String species) { this.species = species; } public String getSpecies() { return species; } public String getColour() { return colour; } public void setColour(String colour) { this.colour = colour; } private String species, colour;} The class that implements Animal and Bird to describe a Seabird: package org.springaop.chapter.three.autoproxy.domain;public class Seabird implements Animal,Bird{ public Integer getNumberPaws() { return 2; } public Boolean hasTail() { return false; } public Boolean hasBeak() { return true; } public Boolean hasFeathers() { return true; } public boolean hasFur() { return false; } public Boolean hasHotBlood() { return false; } public String getName() { return name; } public void setName(String name) { this.name = name; } private String name;} AnimalAdvice containing just the log with the target class, the invoked method, and the result. package org.springaop.chapter.three.autoproxy;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;public class AnimalAdvice implements MethodInterceptor { public Object invoke(MethodInvocation invocation) throws Throwable { Logger log = Logger.getLogger(Constants.LOG_NAME); StringBuilder sb = new StringBuilder(); sb.append("Target Class:").append(invocation.getThis()).append("n").append(invocation.getMethod()).append("n"); Object retVal = invocation.proceed(); sb.append(" return value:").append(retVal).append("n"); log.info(sb.toString()); return retVal; }} The configuration file applicationContext.xml: <beans xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="tiger" class="org.springaop.chapter.three.autoproxy.domain.Cat"> <property name="species" value="tiger"/> <property name="colour" value="tear stripes"/></bean> <bean id="albatross" class="org.springaop.chapter.three.autoproxy.domain.Seabird"> <property name="name" value="albatross"/></bean> <!-- Pointcut --> <bean id="methodNamePointcut" class="org.springframework.aop.support.NameMatchMethodPointcut"> <property name="mappedNames"> <list> <value>has*</value> <value>get*</value> </list> </property> </bean> <!-- Advices --> <bean id="animalAdvice" class="org.springaop.chapter.three.autoproxy.AnimalAdvice"/> <!-- Advisor --> <bean id="animalAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="pointcut" ref="methodNamePointcut"/> <property name="advice" ref="animalAdvice"/> </bean> <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="proxyTargetClass" value="true"/> <property name="beanNames"> <list> <value>tiger</value> <value>albatross</value> </list> </property> <property name="interceptorNames"> <list> <value>animalAdvisor</value> </list> </property> </bean> </beans> Application context contains two beans, tiger and albatross. The methodNamePointcut acts on the methods starting with has and get. The animalAdvice (around advice) contains the logics to be executed, the animal advisor that links the animalAdvice to the methodNamePointcut, and the autoProxyCreator, where we declare just the beans' names and the list of interceptors' names. package org.springaop.chapter.three.autoproxy;public class AutoProxyTest { public static void main(String[] args) { String[] paths = { "org/springaop/chapter/three/autoautoproxy/applicationContext.xml" }; ApplicationContext ctx = new ClassPathXmlApplicationContext(paths); Cat tiger = (Cat)ctx.getBean("tiger"); tiger.hasHotBlood(); Bird albatross = (Bird)ctx.getBean("albatross"); albatros.hasBeak(); }} The test class invokes two methods on the beans tiger and albatross. Output:
Read more
  • 0
  • 0
  • 5917
article-image-design-spring-aop
Packt
14 Oct 2009
12 min read
Save for later

Design with Spring AOP

Packt
14 Oct 2009
12 min read
Designing and implementing an enterprise Java application means not only dealing with the application core business and architecture, but also with some typical enterprise requirements. We have to define how the application manages concurrency so that the application is robust and does not suffer too badly from an increase in the amount of requests. We have to define the caching strategies for the application because we don't want that CPU or data-intensive operations to be executed over and over. We have to define roles and profiles, applying security policies and restricting access to application parts, because different kind of users will probably have different rights and permissions. All these issues require writing additional code that clutters our application business code and reduces its modularity and maintainability. But we have a choice. We can design our enterprise Java application keeping AOP in mind. This will help us to concentrate on our actual business code, taking away all the infrastructure issues that can be otherwise expressed as crosscutting concerns. This article will introduce such issues, and will show how to design and implement them with Spring 2.5 AOP support. Concurrency with AOP For many developers, concurrency remains a mystery. Concurrency is the system's skill to act with several requests simultaneously, so that threads don't corrupt the state of the objects when they gain access at the same time. A number of good books have been written on this subject, such as Concurrent Programming in Java and Java Concurrency in Practice. They deserve much attention, since concurrency is an aspect that's hard to understand, and not immediately visible to developers. Problems in the area of concurrency are hard to reproduce. However, it's important to keep concurrency in mind to assure that the application is robust regardless of the number of users it will serve. If we don't take into account concurrency and document when and how the problems of concurrency are considered, we will build an application taking some risks by supposing that the CPU will never simultaneously schedule processes on parts of our application that are not thread-safe. To ensure the building of robust and scalable systems, we use proper patterns: There are JDK packages just for concurrency. They are in the java.util.concurrent package, a result of JSR-166. One of these patterns is the read-write lock pattern, of which there is the interface java.util.concurrent.locks.ReadWriteLock and implementations, one of which is ReentrantReadWriteLock. The goal of ReadWriteLock is to allow the reading of an object from virtually endless number of threads, while only one thread at a time can modify it. In this way, the state of the object can never be corrupted because threads to reading the object's state will always read up-to-date data, and the thread modifying the state of the object in question will be able to act without the possibility of the object's state being corrupted. Another necessary skill is that the result of a thread's action can be visible to the other threads. The behavior is the same as we could have achieved using synchronized, but when using a read-write lock we are explicitly synchronizing the actions, whereas with synchronized synchronization is implicit. Now let's see an example of ReadWriteLock on BankAccountThreadSafe object. Before the read operation, that needs to be safe, we set the read lock. After the read operation, we release the read lock. Before the write operation that needs to be safe, we set the write lock. After a state modification, we release the write lock. package org.springaop.chapter.five.concurrent; import java.util.Date; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public final class BankAccountThreadSafe { public BankAccountThreadSafe(Integer id) { this.id = id; balance = new Float(0); startDate = new Date(); } public BankAccountThreadSafe(Integer id, Float balance) { this.id = id; this.balance = balance; startDate = new Date(); } public BankAccountThreadSafe(Integer id, Float balance, Date start) { this.id = id; this.balance = balance; this.startDate = start; } public boolean debitOperation(Float debit) { wLock.lock(); try { float balance = getBalance(); if (balance < debit) { return false; } else { setBalance(balance - debit); return true; } } finally { wLock.unlock(); } } public void creditOperation(Float credit) { wLock.lock(); try { setBalance(getBalance() + credit); } finally { wLock.unlock(); } } private void setBalance(Float balance) { wLock.lock(); try { balance = balance; } finally { wLock.unlock(); } } public Float getBalance() { rLock.lock(); try { return balance; } finally { rLock.unlock(); } } public Integer getId() { return id; } public Date getStartDate() { return (Date) startDate.clone(); } ... private Float balance; private final Integer id; private final Date startDate; private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final Lock rLock = lock.readLock(); private final Lock wLock = lock.writeLock(); } BankAccountThreadSafeis a class that doesn't allow a bank account to be overdrawn (that is, have a negative balance), and it's an example of thread-safe class. The final fields are set in the constructors, hence implicitly thread-safe. The balance field, on the other hand, is managed in a thread-safe way by the setBalance,getBalance, creditOperation, and debitOperation methods. In other words, this class is correctly programmed, concurrency-wise. The problem is that wherever we would like to have those characteristics, we have to write the same code (especially the finally block containing the lock's release). We can solve that by writing an aspect that carries out that task for us. A state modification is execution(void com.mycompany.BankAccount.set*(*)) A safe read is execution(* com.mycompany.BankAccount.getBalance()) package org.springaop.chapter.five.concurrent; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class BankAccountAspect { /*pointcuts*/ @Pointcut("execution(* org.springaop.chapter.five.concurrent.BankAccount.getBalance())") public void safeRead(){} @Pointcut("execution(* org.springaop.chapter.five.concurrent.BankAccount.set*(*))") public void stateModification(){} @Pointcut( "execution(* org.springaop.chapter.five.concurrent.BankAccount.getId())") public void getId(){} @Pointcut("execution(* org.springaop.chapter.five.concurrent.BankAccount.getStartDate())) public void getStartDate(){} /*advices*/ @Before("safeRead()") public void beforeSafeRead() { rLock.lock(); } @After("safeRead()") public void afterSafeRead() { rLock.unlock(); } @Before("stateModification()") public void beforeSafeWrite() { wLock.lock(); } @After("stateModification()") public void afterSafeWrite() { wLock.unlock(); } private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final Lock rLock = lock.readLock(); private final Lock wLock = lock.writeLock(); } The BankAccountAspect class applies the crosscutting functionality. In this case, the functionality is calling the lock and unlock methods on the ReadLock and the WriteLock. The before methods apply the locks with the @Before annotation, while the after methods release the locks as if they were in the final block, with the @After annotation that is always executed (after-finally advice). In this way the BankAccount class can become much easier, clearer, and briefer. It wouldn't have any perception that it can be executed in a thread-safe manner. package org.springaop.chapter.five.concurrent; import java.util.Date; public class BankAccount { public BankAccount(Integer id) { this.id = id; this.balance = new Float(0); this.startDate = new Date(); } public BankAccount(Integer id, Float balance) { this.id = id; this.balance = balance; this.startDate = new Date(); } public BankAccount(Integer id, Float balance, Date start) { this.id = id; this.balance = balance; this.startDate = start; } public boolean debitOperation(Float debit) { float balance = getBalance(); if (balance < debit) { return false; } else { setBalance(balance - debit); return true; } } public void creditOperation(Float credit) { setBalance(getBalance() + credit); } private void setBalance(Float balance) { this.balance = balance; } public Float getBalance() { return balance; } public Integer getId() { return id; } public Date getStartDate() { return (Date) startDate.clone(); } private Float balance; private final Integer id; private final Date startDate; } Another good design choice, together with the use of ReadWriteLock when necessary, is: using objects that once built are immutable, and therefore, not corruptible and can be easily shared between threads. Transparent caching with AOP Often, the objects that compose applications perform the same operations with the same arguments and obtain the same results. Sometimes, these operations are costly in terms of CPU usage, or may be there is a lot of I/O going on while executing those operations. To get better results in terms of speed and resources used, it's suggested to use a cache. We can store in it the results corresponding to the methods' invocations as a key-value pair: method and arguments as key and return object as value. Once you decide to use a cache you're just halfway. In fact, you must decide which part of the application is going to use the cache. Let's think about a web application backed by a database. Such web application usually involves Data Access Objects (DAOs), which access the relational database. Such objects are usually a bottleneck in the application as there is a lot of I/O going on. In other words, a cache can be used there. The cache can also be used by the business layer that has already aggregated and elaborated data retrieved from repositories, or it can be used by the presentation layer putting formatted presentation templates in the cache, or even by the authentication system that keeps roles according to an authenticated username. There are almost no limits as to how you can optimize an application and make it faster. The only price you pay is having RAM to dedicate the objects that are to be kept in memory, besides paying attention to the rules on how to manage life of the objects in cache. After these preliminary remarks, using a cache could seem common and obvious. A cache essentially acts as a hash into which key-value pairs are put. The keys are useful to retrieve objects from the cache. Caching usually has configuration parameters that'll allow you to change its behavior. Now let's have a look at an example with ehcache (http://ehcache.sourceforge.net). First of all let's configure it with the name methodCache so that we have at the most 1000 objects. The objects are inactive for a maximum of five minutes, with a maximum life of 10 minutes. If the objects count is over 1000, ehcache saves them on the filesystem, in java.io.tmpdir. <ehcache> ... <diskStore path="java.io.tmpdir"/> ... <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" /> ... <cache name="methodCache" maxElementsInMemory="1000" eternal="false" overflowToDisk="false" timeToIdleSeconds="300" timeToLiveSeconds="600" /> </ehcache> Now let's create an CacheAspect . Let's define the cacheObject to which the ProceedingJoinPoint is passed. Let's recover an unambiguous key from the ProceedingJoinPoint with the method getCacheKey. We will use this key to put the objects in cache and to recover them. Once we have obtained the key, we ask to cache the Element with the instruction cache.get(cacheKey). The Element has to be evaluated because it may be null if the cache didn't find an Element with the passed cacheKey. If the Element is null, advice invokes the method proceed(), and puts in the cache the Element with the key corresponding to the invocation. Otherwise, if the Element recovered from the cache is not null, the method isn't invoked on the target class, and the value taken from the cache is given back to the caller. package org.springaop.chapter.five.cache; import it.springaop.utils.Constants; import net.sf.ehcache.Cache; import net.sf.ehcache.Element; import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; public class CacheAspect { public Object cacheObject(ProceedingJoinPoint pjp) throws Throwable { Object result; String cacheKey = getCacheKey(pjp); Element element = (Element) cache.get(cacheKey); logger.info(new StringBuilder("CacheAspect invoke:").append("n get:") .append(cacheKey).append(" value:").append(element).toString()); if (element == null) { result = pjp.proceed(); element = new Element(cacheKey, result); cache.put(element); logger.info(new StringBuilder("n put:").append(cacheKey).append( " value:").append(result).toString()); } return element.getValue(); } public void flush() { cache.flush(); } private String getCacheKey(ProceedingJoinPoint pjp) { String targetName = pjp.getTarget().getClass().getSimpleName(); String methodName = pjp.getSignature().getName(); Object[] arguments = pjp.getArgs(); StringBuilder sb = new StringBuilder(); sb.append(targetName).append(".").append(methodName); if ((arguments != null) && (arguments.length != 0)) { for (int i = 0; i < arguments.length; i++) { sb.append(".").append(arguments[i]); } } return sb.toString(); } public void setCache(Cache cache) { this.cache = cache; } private Cache cache; private Logger logger = Logger.getLogger(Constants.LOG_NAME); } Here is applicationContext.xml <beans xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> ... <bean id="rockerCacheAspect" class="org.springaop.chapter.five.cache.CacheAspect" > <property name="cache"> <bean id="bandCache" parent="cache"> <property name="cacheName" value="methodCache" /> </bean> </property> </bean> <!-- CACHE config --> <bean id="cache" abstract="true" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> <property name="cacheManager" ref="cacheManager" /> </bean> <bean id="cacheManager" class="org.springframework.cache.ehcache. EhCacheManagerFactoryBean"> <property name="configLocation" value="classpath:org/springaop/chapter/five/cache/ehcache.xml" /> </bean> ... </beans> The idea about the caching aspect is to avoid repetition in our code base and have a consistent strategy for identifying objects (for example using the hash code of an object) so as to avoid objects from ending up in the cache twice. Employing an around advice, we can use the cache to make the method invocations give back the cached result of a previous invocation of the same method in a totally transparent way. In fact, to the methods of the classes defined in the interception rules in pointcuts will be given back the return values drawn from the cache or, if they are not present, they will be invoked and inserted in the cache. In this way, the classes and methods don't have any cognition of obtaining values retrieved from the cache.
Read more
  • 0
  • 0
  • 18570

article-image-managing-users-and-their-profiles-drupal-6-social-networking
Packt
14 Oct 2009
10 min read
Save for later

Managing Users and their Profiles in Drupal 6 Social Networking

Packt
14 Oct 2009
10 min read
What are we going to do and why? Before we get started, let's have a closer look at what we will be doing, and why. Our users can interact with the web site, and they can have their own blog. Apart from this, there are very few provisions for the users to tell everyone else about themselves, and expand their profiles with something more personal. With a site like ours, it would be useful to know more about our users including: Their pet dinosaur's name Breed of dinosaur Their pet dinosaur's birthday The dinosaur's hobbies and so on Their web address (if they have one) Location / City / Area More information about the user themselves This can be added to user profiles using the Profile module, which is a core module within Drupal, and simply needs to be enabled and configured. Many web sites allow users to upload an image to be associated with their accounts, which could be either a small photo of themselves, or a small image known as an avatar. Drupal allows this, but it has some drawbacks which can be fixed using Gravatar. Gravatar is a social avatar service, whereby users set up their avatars, and other web sites automatically pick up their avatars by sending a request to the Gravatar service with the users' emails. This is convenient for our users, as it saves them having to upload their avatars to our site, and reduces the amount of data stored on our site as well as the data being sent and received from our site. This module needs to be downloaded, installed and configured for our users to make use of its features. With the upload module enabled, users can upload their own avatars directly to the site, if they choose to do so. This is because not all users would be members of Gravatar, nor would they all wish to sign up to a third-party service. With the rise in the number of web sites and social networks that users of the Internet are members of, having to log in to different web sites on a daily basis can put off users if they have to sign up to another web site. OpenID helps prevent this as users need to remember only one username and password. It works by allowing users to login by providing a web address, instead of their usernames and passwords. This web site is their identity with an OpenID provider (maybe it is their own web site or another social network—MySpace and other social networking web sites are OpenID providers). When they log in with these identities, they will be taken to these web sites to log in before being returned to our site. If they have already logged in into their OpenIDs, they will return to the web site as new users. More information on OpenID is available from http://openid.net/. This is a core module which just needs to be enabled. There are two important points to be noted about OpenID. Firstly, it is decentralized, which means log in details are not tied to a specific provider, and secondly, it is offered as an alternative log in method—users without an OpenID (or those who don't know they have an OpenID!) can still log in or sign up as normal. Users have their own blogs which they can use, but they are not personalized blogs. By installing the blog theme module, we can allow our users to select different themes for use in their blogs. This way, visitors to one particular user's blog (for example 'Bob') will see the theme that Bob chose. Once users get to know each other more, they become more interested in each other's posts and topics, and may wish to look up a specific user's posts and contributions. The Tracker module allows users to track one another's contributions to the site. This is a core module, which just needs to be enabled and set up. Now that we have a better idea of what we are going to do, let's get started! Install the modules To make things easier for us, let's install and enable all the relevant modules first. This saves us having to do this again and again at a later stage. The modules which we require are: Profile (a core module) Tracker (a core module) OpenID (a core module) Gravatars (http://drupal.org/project/gravatar) Blog Theme (http://drupal.org/project/blogtheme) We need to download the relevant modules (ensuring we download ones which are compatible with Drupal 6.x), and extract the ZIP files into the /sites/all/modules folder. As we have not downloaded and installed any new modules on our Drupal installation yet, we will need to create the folder modules within the /sites/all/ directory. The reason there are sites/all and a sites/default directories is because Drupal can support multiple web sites running off one installation, and this defines which modules are available to which of the installations. Core modules are located elsewhere, which is why we don't have a modules folder already in this location containing the core modules. Now all the modules just have to be enabled via the Site Building | Modules section of the Administration area. Users, roles, and permissions Let's have a more detailed look at users, roles, and permissions and also how they work. These are all areas of the administration area, within the User management section. The other options within this section (Access rules, Gravatar, Profiles and User settings) will be looked at later in this article. Users When a visitor signs up for our site, a user account is created for him/her. From the Users area, we can view a list of existing users, create new ones and edit them. Within the context of editing a user, not only can we edit their details, such as their usernames or passwords, but we can also suspend their user accounts or delete their user accounts permanently from our social network. We want our site to become popular, which means that we want to have lots of users. When we get lots of users, it will become more difficult to navigate through their list, and this is when searching, sorting, and filtering them come in handy—which is what we are going to look at now. For each user, the user list displays: The username The status of the user account (active or blocked) Roles associated with the account Length of time the user has been a member for The time passed since the user was last active on our site A link to edit the user Viewing / searching / sorting / filtering Clicking the username will take us to their user profile. We can sort the list of users by clicking the heading in any of the columns to sort the list by that column. One particular use of doing this is that we can see all blocked users, ????so we can quickly reactivate an account should we need to, or see who the newest members are. We can also filter the accounts displayed using the Show only users where panel. This allows us to filter the list based on whether the account is active or not, or against specific roles assigned to users. Creating a user At the top of the users page, we have the Add user link. This takes us to the new user page, where we are required to fill out the Username, E-mail address, Password, and Confirm Password again for the user. We can also opt to notify the users of their new accounts, which will send them an email informing them that they have a new account with the Dino Space social network. Editing To edit an account, we just need to click the edit link which corresponds to the account, which takes us to the edit page. We can edit the user's Username, E-mail address, Password, account Status and settings pertaining to modules, which give users additional settings too. Careful!If you edit these settings, the users may not be able to log in to their accounts. If you change a user's Username without his/her request, you should let him/her know through email. Suspending / blocking a user Within the edit page, we have an option entitled Status, which can be set to either Blocked or Active. This would allow us to block a user from accessing our site, for instance if they had been posting inappropriate material repeatedly, even after being contacted and asked to stop. Why block? Why not just delete?If we were to just delete a user who was posting inappropriate material, or doing something we didn't want, then he/she could just sign up again. Blocking the user prevents him/her from signing up with the same email address and username. Of course, he/she could sign up again with a different email address and a different username. But this helps us to keep things under control. Deleting a user At the bottom of the edit user screen, there are two buttons: Save and Delete. The Save button will confirm and save any changes made to the user's account, and the delete button will permanently remove the user from our social network. When to delete a userA user may request to be removed from the web site, in which case, we can use this feature. Roles Users are grouped into roles, which in turn have permissions assigned to them. By default, there are two roles within Drupal. These two roles are: anonymous users authenticated users These roles can be edited, but they can neither be renamed nor deleted. This is why the Operations column in the table below is locked. The anonymous user role is the role for any user who is not logged-in, and so the permissions associated with it are those which a guest user has. Whereas the role of an authenticated user suits all those users who are logged-in. Additional roles which are added can apply to any number of users. At this stage, we must select which users have which roles assigned to them. Users can change their roles and get more active within the network with features such as Organic Groups, but it is out of the scope of this article. Editing the permissions of a role allows us to select which permissions are granted to users who have that role assigned to their account. New roles are simply created by entering the name of a new role into the text box and then clicking the Add role button and selecting the permissions to be granted to those users. Permissions The Permissions section provides us with a grid view for roles and the permissions assigned to them. All the permissions which can be granted are listed down theside (for example, create blog entries) and the roles along the top. The use of this view, if we were to install a new module with new permissions related to it, is that we could easily update all of our roles to have the desired permissions directly from the grid view. The Save permissions link at the bottom of the page saves the changes made.
Read more
  • 0
  • 0
  • 3080

article-image-synchronous-communication-and-interaction-moodle-19-multimedia
Packt
14 Oct 2009
5 min read
Save for later

Synchronous Communication and Interaction with Moodle 1.9 Multimedia

Packt
14 Oct 2009
5 min read
These options can be helpful for distance education, providing new ways of communicating and interacting with our students (and between them) when we are not all in the same physical space. Because Moodle does not provide effective synchronous communication tools (the chat activity could overload the server), the aforementioned tools are presented as extensions that can support our courses, giving them a new level of interaction. In distance courses with considerable duration, such communication can be a motivation and a way of providing support to students when we are online at the same time. Communicating in real-time using text, audio, and video Google Chat is a service from Google that allows text, audio, and video chat amongst Google Mail users meaning, we'll need a Google account. The audio conversation is usually called Voice over IP (VoIP), but as bandwidth allowances increase, the use of video is becoming common. With this tool we can: Meet with colleagues or students, individually or in groups Participate in a distant event (for example, attend a conference) Conduct interviews Teach how to play an instrument (by using the webcam) Teach gestural language (by using the webcam) I find it really useful to use VoIP in distance courses, not only to give feedback to students and get to know them better, but also to create opportunities for students to interact with each other during group tasks outside of these tutor-students meeting times. A good time to use this application is in Module 10 – What's good music—a theme that fits well with an online debate about how to define quality criteria for music. Students will be required to work in groups and debate on what they think is good music and how it can be assessed. This discussion will be facilitated by using this tool. Chat and group chat The chat option is available in Google Mail, on the sidebar on the left. For a start, we can configure some settings, especially privacy settings, by going to Options | Chat settings…: In the section Auto-add suggested contacts, we should select the option Only allow people that I've explicitly approved to chat with me and see when I'm online option, as shown in the screenshot below: We can also disable chat history if we don't want to keep a record of our chat. There is another option during a chat to go "off record", meaning that if the chat history is on, this portion of the conversation (that takes place whilst this option is selected) will not be archived. We are now ready to start a chat. We can search for contacts in the same Google Mail Chat sidebar, using the search form that is available (Search, add or invite) and double-click on the name of the contact that is displayed, or in the Chat link of the pop-up window that is displayed: Because the chat is synchronous, it's obvious that the (two or more) people chatting must be online. We can check if a person is online or not by looking at the small icon next to the people we've located, or in our chat list. If they have a grey, round icon on the left of their name, they are offline (or invisible and don't want to be bothered). If the color is green (available), yellow (idle), or red (busy) it's possible to chat to them. In the pop-up, we can also add the person to the chat list below the search form. After starting the chat, a window similar to the one shown below opens in the lower-right corner of the Google Mail account, and we can start talking: When we are chatting with someone, we can click on the Video & More | Group Chat option to invite one or more friends to join the conversation: A new window will appear, in which we can chat with the participants. Note that if we click on the arrow in the blue bar at the top of our chat window, the window will pop-up from its position in the Google Mail window and we can access it as an independent window. If we paste a URL from a YouTube video into the chat window, a preview of the video will be integrated directly into our conversation, as shown in the screenshot below: Transferring files The easiest way to send files to participants for reading, or supporting discussion or commenting upon is either by using Google Mail, or by uploading them to Moodle or Google Docs and sharing these with the chat participants. This can be useful in many online discussions. Voice and video chat Chat, as we saw, is available by default in Google Mail, on the leftmost sidebar. To add audio and voice capabilities to this chat, we have to install a plug-in that is available at http://mail.google.com/videochat, for Windows and Mac users (again, sorry to Linux users). After installing this plug-in, we can start an audio or video conversation (only one-to-one). If our contacts have a camera or microphone, we can click on the Video & more option again, and the following two options will be available: In the case of voice chat, a call will be started, and we will also keep the text chat functionality: In the case of video chat, the same applies. In the upper area, a video of the person that we are chatting with will be displayed, and in the lower corner, if we have a webcam, our video will be displayed: Image source: Scmoewes (2005). Jimi. Retrieved March 30, 2009,from http://www.flickr.com/photos/cmoewes/30989105/ For distance courses or even in e-learning, Google chat is an option. But if we need more complex functionality, including audio conferencing and desktop sharing, there are other tools that are available. We will now look at one in particular, called Dimdim.
Read more
  • 0
  • 0
  • 1843
article-image-data-modeling-erwin
Packt
14 Oct 2009
3 min read
Save for later

Data Modeling with ERWin

Packt
14 Oct 2009
3 min read
Depending on your data modeling need and what you already have, there are two other ways to create a data model: Derive from an existing model and Reverse Engineer an existing database. Let’s start with creating a new model by clicking the Create model button. We’d like to create both logical and physical models, so select Logical/Physical. You can see in the Model Explorer that our new model gets Model_1 name, ERWin’s default name. Let’s rename our model to Packt Model. Confirm by looking at the Model Explorer that our model is renamed correctly. Next, we need to choose the ER notation. ERWin offers two notations: IDEF1X and IE. We’ll use IE for our logical and physical models. It’s a good practice during model development to save our work from time to time. Our model is still empty, so let’s next create a logical model in it. Logical Model Logical model in ERWin is basically ER model. An ER model consists of entities and their attributes, and their relationships. Let’s start by creating our first entity: CUSTOMER and its attributes. To add an entity, load (click) the Entity button on the toolbar, and drop it on the diagramming canvas by clicking your mouse on the canvas. Rename the entity’s default E/1 name to CUSTOMER by clicking on the name (E/1) and typing its new name over it. To add an attribute to an entity, right-click the entity and select Attributes. Click the New button. Type in our first attribute name (CUSTOMER_NO) over its name, and select Number as its data type, and then click OK. We want this attribute as the entity’s primary key, so check the Primary Key box. In the same way, add an attribute: CUSTOMER_NAME with a String data type. Our CUSTOMER entity now has two attributes as seen in its ER diagram. Notice that the CUSTOMER_NO attribute is at the key area, the upper part of the entity box; while the CUSTOMER_NAME is in the common attribute area, the bottom part. Similarly, add the rest of the entities and their attributes in our model. When you’re done, we’ll have six entities in our ER diagram. Our entities are not related yet. To rearrange the entities in the diagram, you can move around the entities by clicking and dragging them.
Read more
  • 0
  • 0
  • 4017

article-image-building-friend-networks-django-10
Packt
14 Oct 2009
6 min read
Save for later

Building Friend Networks with Django 1.0

Packt
14 Oct 2009
6 min read
An important aspect of socializing in our application is letting users to maintain their friend lists and browse through the bookmarks of their friends. So, in this section we will build a data model to maintain user relationships, and then program two views to enable users to manage their friends and browse their friends' bookmarks. Creating the friendship data model Let's start with the data model for the friends feature. When a user adds another user as a friend, we need to maintain both users in one object. Therefore, the Friendship data model will consist of two references to the User objects involved in the friendship. Create this model by opening the bookmarks/models.py file and inserting the following code in it: class Friendship(models.Model): from_friend = models.ForeignKey( User, related_name='friend_set' ) to_friend = models.ForeignKey( User, related_name='to_friend_set' ) def __unicode__(self): return u'%s, %s' % ( self.from_friend.username, self.to_friend.username ) class Meta: unique_together = (('to_friend', 'from_friend'), ) The Friendship data model starts with defining two fields that are User objects: from_friend and to_friend. from_friend is the user who added to_friend as a friend. As you can see, we passed a keyword argument called related_name to both the fields. The reason for this is that both fields are foreign keys that refer back to the User data model. This will cause Django to try to create two attributes called friendship_set in each User object, which would result in a name conflict. To avoid this problem, we provide a specific name for each attribute. Consequently, each User object will contain two new attributes: user.friend_set, which contains the friends of this user and user.to_friend_set, which contains the users who added this user as a friend. Throughout this article, we will only use the friend_set attribute, but the other one is there in case you need it . Next, we defined a __unicode__ method in our data model. This method is useful for debugging. Finally, we defined a class called Meta. This class may be used to specify various options related to the data model. Some of the commonly used options are: db_table: This is the name of the table to use for the model. This is useful when the table name generated by Django is a reserved keyword in SQL, or when you want to avoid conflicts if a table with the same name already exists in the database. ordering: This is a list of field names. It declares how objects are ordered when retrieving a list of objects. A column name may be preceded by a minus sign to change the sorting order from ascending to descending. permissions: This lets you declare custom permissions for the data model in addition to add, change, and delete permissions. Permissions should be a list of two-tuples, where each two-tuple should consist of a permission codename and a human-readable name for that permission. For example, you can define a new permission for listing friend bookmarks by using the following Meta class: class Meta: permissions = ( ('can_list_friend_bookmarks', 'Can list friend bookmarks'), ) unique_together: A list of field names that must be unique together. We used the unique_together option here to ensure that a Friendship object is added only once for a particular relationship. There cannot be two Friendship objects with equal to_friend and from_friend fields. This is equivalent to the following SQL declaration: UNIQUE ("from_friend", "to_friend") If you check the SQL generated by Django for this model, you will find something similar to this in the code. After entering the data model code into the bookmarks/models.py file, run the following command to create its corresponding table in the database: $ python manage.py syncdb Now let's experiment with the new model and see how to store and retrieve relations of friendship. Run the interactive console using the following command: $ python manage.py shell Next, retrieve some User objects and build relationships between them (but make sure that you have at least three users in the database): >>> from bookmarks.models import *>>> from django.contrib.auth.models import User>>> user1 = User.objects.get(id=1)>>> user2 = User.objects.get(id=2)>>> user3 = User.objects.get(id=3)>>> friendship1 = Friendship(from_friend=user1, to_friend=user2)>>> friendship1.save()>>> friendship2 = Friendship(from_friend=user1, to_friend=user3)>>> friendship2.save() Now, user2 and user3 are both friends of user1. To retrieve the list of Friendship objects associated with user1, use: >>> user1.friend_set.all()[<Friendship: user1, user2>, <Friendship: user1, user3>] (The actual usernames in output were replaced with user1, user2, and user3 for clarity.) As you may have already noticed, the attribute is named friend_set because we called it so using the related_name option when we created the Friendship model. Next, let's see one way to retrieve the User objects of user1's friends: >>> [friendship.to_friend for friendship in user1.friend_set.all()][<User: user2>, <User: user3>] The last line of code uses a Python feature called "list" comprehension to build the list of User objects. This feature allows us to build a list by iterating through another list. Here, we built the User list by iterating over a list of Friendship objects. If this syntax looks unfamiliar, please refer to the List Comprehension section in the Python tutorial. Notice that user1 has user2 as a friend, but the opposite is not true. >>> user2.friend_set.all() [] In other words, the Friendship model works only in one direction. To add user1 as a friend of user2, we need to construct another Friendship object. >>> friendship3 = Friendship(from_friend=user2, to_friend=user1)>>> friendship3.save()>>> user2.friend_set.all() [<Friendship: user2, user1>] By reversing the arguments passed to the Friendship constructor, we built a relationship in the other way. Now user1 is a friend of user2 and vice-versa. Experiment more with the model to make sure that you understand how it works. Once you feel comfortable with it, move to the next section, where we will write views to utilize the data model. Things will only get more exciting from now on!
Read more
  • 0
  • 0
  • 9485
Modal Close icon
Modal Close icon