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

How-To Tutorials

7018 Articles
article-image-metadata-oracle-universal-content-management
Packt
09 Aug 2010
5 min read
Save for later

Metadata in Oracle Universal Content Management

Packt
09 Aug 2010
5 min read
Let's begin by looking in the metadata. Exploring metadata In case you forgot, metadata fields are there to describe the actual data such as the file name, shooting date, and camera name for a digital picture. There're two types of metadata fields: Standard and Extended or Custom. Let's take a closer look at what they can do for us. Standard metadata Standard metadata is essential for the system to function. These are fields like content ID, revision ID, check-in date, and author. Let's take a quick look at all of them so you have a full picture. Lab 2: Exploring standard metadata Click on the Quick Search button on the top right. Yes, leave the search box blank. If you do that, you'll get all content in the repository. In the last column on the Search Results page click on the i icon on any of the result rows. That brings up a Content Info screen. From this screen there is no way to tell which fields are Standard and which are Extended. So how do you tell? Explore the database That's right. A Content Server uses a relational database, like Oracle or SQL Server to store its metadata, so let's look there. If you are using SQL Server 2005 as your database, then open SQL Server Management Studio, and if not then bring up your SQL tool of choice. Check the list of columns in the table called Revisions (as shown in the following screenshot): Most of the column names in Revisions are the standard metadata fields. Here's a list of the fields you will be using most often: dID: ID of the document revision. This number is globally unique. If you have a project plan with three revisions—each of the three will have unique dID and all of them will have the same Content ID. dDocName: this is the actual Content ID. dDocType: content type of the document. dDocName or Content ID is the unique identifier for a content revision set. dID is the unique identifier of each individual content revision within a set. Being able to identify a content revision set is very useful, as it shows and tracks (makes auditable) the changes of content items over time. Being able to identify each individual revision with dID is also very useful, so we can work with specific content revisions. This is one of the great advantages of the Content Server over other systems, which only store the changes between revisions. Full revision sets as well as individual revisions are managed objects and each one can be accessed by its own unique URL. Now run this SQL statement: select * from Revisions; This shows the actual documents in the system and their values for standard meta fields (as shown in the following screenshot): And now let's look at the all-important Content Types. Content Types Content Type is a special kind of meta field. That's all. UCM puts a special emphasis on it as this is the value that differentiates a project plan from a web page and a team photo from a vendor invoice. You may even choose to change the way your check-in and content info form looks —based on the type of the document. Let's look how UCM handles Content Types. Lab 3: Exploring content types In Content Server go to Administration | Admin Applets. Launch the Configuration Manager. Select Options| Content Types... (as shown in the following screenshot): The Content Types dialog opens. As you see, out of the box, Content Server has seven types—one for each imaginary department. This is a good way of segregating content. You can also go by the actual type of content. For instance, you can have one Content Type for Invoice and one for Project Plan. They will also have different meta fields. For instance, an Invoice will have a Contract Number and a Total Amount. A Project Plan will have a project name and manager's name. Now let me show you how to add content types. How to add a Content Type It's easy to add a new Content Type. Just click on Add..., fill in the type name and the description. You can also select an icon for the new type. What if you need to upload a new icon? Just make it into an 8-bit GIF file, 30x37 px, 96 dpi and upload it to: C:oracleucmserverweblayoutimagesdocgifs If your install path is different or you're not running on Windows then make appropriate corrections. How to edit or delete a Content Type The only thing to know about editing is that you can not really change the type name. All you can update is the icon or description. If you're ready to delete a type then make sure there is no content in the repository that's using it. Either update it all or delete. How would you go about doing a mass-update? I'll show you one of the ways in on using Archiver(Ways on archiever is out of the scope of this article). And now let's proceed to Custom Metadata.
Read more
  • 0
  • 0
  • 2497

article-image-oracle-universal-content-management-how-set-and-change-workflows
Packt
09 Aug 2010
4 min read
Save for later

Oracle Universal Content Management: How to Set Up and Change Workflows

Packt
09 Aug 2010
4 min read
(For more resources on Oracle, see here.) How to set up and change workflows First thing's first. Let's start by looking at the tools that you will be using to set up and configure your workflows. Discover the Workflow Admin application Go to Administration Admin Applets| and launch Workflow Admin. The Workflow Admin application comes up (as shown in the following screenshot): There are three tabs: Workflows: This tab is used for administering Basic or Manual Workflows. Criteria: This tab deals with Automatic or Criteria Workflows—the type we will be using most often. Templates: This is the place where you can pre-assemble Workflow Templates—reusable pieces that you can use to create new basic workflows. Let's create a simple automatic workflow. I call it automatic because content enters the workflow automatically when it is modified or created. If you will be using e-mail notifications then be sure to check your Internet Configuration screen in Admin Server. I'll walk you through the steps in using automatic workflows. Lab 7: Using automatic workflows Here's the process for creating a criteria workflow: Creating a criteria workflow Follow these steps: Go to the Criteria tab and click on Add. The New Criteria Workflow dialog comes up (as shown in the following screenshot): Fill in Workflow Name and Description. Pick the Security Group. Only items with the same security group as the workflow can enter it. Let's use the security group we've created. Select accounting. We're creating a Criteria Workflow, so let's check the Has Criteria Definition box. Now you can specify criteria that content must match to enter the workflow.For the sake of this lab, let's pick Account for the Field, and accounting/payable/current for the Value. Please note that a content item must match at least two conditions to enter the workflow: it must belong to the same security group as the workflow, and it must match the criteria of the workflow. As soon as a new content item is created with Security Group of accounting and Content Account value is set to accounting/payable/current, it will enter our workflow. It will not enter the workflow if its metadata is simply updated to these values. It takes a new check-in for an item to enter a criteria workflow. If you need it to enter a workflow after a metadata update then consider custom components available from the Fishbowl Solutions (www.fishbowlsolutions.com). You can use any metadata field and value pair as criteria for entering the workflow. But you can only have one condition. What if that's not enough? If you need to perform additional checks before you can accept the item in a workflow then keep your criteria really open, and do your checks in the workflow itself. I'll show you how, later in this article. The diagram next illustrates how a content item flows through a criteria workflow. You may find it useful to refer back to it as you follow the steps in this lab. OK. We have a workflow created but there're two problems with it: it has no steps in it and it is disabled. Let's begin by seeing how to add workflow steps. Adding workflow steps Here's how you add workflow steps: Click on the Add button in the Steps section on the right (as shown in the following screenshot): The Add New Step dialog opens. Fill in the step name and description (as shown in the following screenshot): Click on the Add User button on the right and select approvers for this step. Also add yourself to the list of approvers so you can test the workflow. Switch to the Exit Conditions tab (as shown in the following screenshot): You can change the number of approvers required to move the item to the next step. You can make all approvers required to advance a step or just any one as shown on the screenshot. And if you put zero in the text box, no approvers will be required at all. They will still receive notification, but the item will go immediately to the next step. And when the current step is the last the workflow will end and the new revision will be released into the system. What do I mean by that? Until workflow is complete, revisions that are currently in a workflow will not come up in searchers and will not show on the Web. You will still see them in the content info screen but that's it. OK the dialog. You now have a workflow with one step. Let's test it. But first, you need to enable the workflow.
Read more
  • 0
  • 0
  • 2803

article-image-more-things-you-can-do-oracle-content-server-workflows
Packt
09 Aug 2010
5 min read
Save for later

More Things you can do with Oracle Content Server workflows

Packt
09 Aug 2010
5 min read
(For more resources on Oracle, see here.) The top three things As we've just seen, the most common things you can do are these: Get content approved: This is the most obvious use of the workflow we've just seen. Get people notified: Remember when we were adding workflow steps there was a number of required approvers on the Exit Conditions tab in the Add New Step dialog. If we set that to zero we accomplish one important thing: Approvers will get notified, but no action is required of them. It's a great way to "subscribe" a select group of people to an event of your choice. Perform custom actions: And if that's not enough you can easily add custom scripts to any step of a workflow. You can change metadata, release items, and send them to other workflows. You can even invoke your custom Java code. And here's another really powerful thing you can do with custom workflow actions. You can integrate with other systems and move from the local workflow to process orchestration. You can use a Content Server workflow to trigger external processes. UCM 10gR3 has an Oracle BPEL integration built in. This means that a UCM workflow can be initiated by (or can itself initiate) a BPEL workflow that spans many systems, not just the UCM. This makes ERP systems such as Siebel, PeopleSoft, SAP, and Oracle e-Business Suite easily accessible to the UCM, and content inside the UCM can be easily made available to these systems. So let's look at the jumps and scripting. Jumps and scripting Here's how to add scripting to a workflow: In Workflow Admin select a step of a workflow we've just created. Click on the Edit button on the right. The Edit Step dialog comes up. Go to the Events tab (as shown in the following screenshot): There are three events that you can add custom handlers for: Entry: This event triggers when an item arrives at the step. Update: This happens when an item or its metadata is updated. It's also initiated every hour by a timer event, Workflow Update Cycle. Use it for sending reminders to approvers or escalating the item to an alternative person after your approval period has expired. Exit: This event is triggered when an item has been approved and is about to exit the step. If you have defined Additional Exit Conditions on the Exit Conditions tab then those will be satisfied before this event fires. The following diagram illustrates the sequence of states and corresponding events that are fired when a content item arrives at a workflow step: Great! But how do we can actually add the jumps and custom scripts to a workflow step? How to add a jump to a workflow step Let's add an exception where content submitted by sysadmin will bypass our Manager Approval workflow. We will use a jump—a construct that causes an item to skip the normal workflow sequence and follow an alternative path. Here's how to do it: Add a jump to an Entry event of our very first step. On the Events tab of the Edit Step dialog, click on the Edit button—the one next to the Entry event. The Edit Script dialog displays (as shown in the following screenshot): Click on the Add button. The Add Jump dialog comes up (as shown in the following screenshot): Let's call the jump Sysadmin WF bypass. You don't need to change anything else at this point. Click on OK to get back to the Edit Script dialog. In the Field drop-down box pick Author. Click on the Select… button next to the Value box. Pick sysadmin (if you have trouble locating sysadmin in the list of users, make sure that the filter check-box is un-checked). Click the Add button below the Value field. Make sure that your clause appears in the Script Clauses box below. In the Target Step dropdown pick Next Step. Once you have done so the value will change to its script equivalent, @wfCurrentStep(1). If you have more than one step in the workflow, change 1 to the number of steps you have. This will make sure that you jump past the last step and exit the workflow. Here's how the completed dialog will look (as shown in the following screenshot): Click on OK to close. You're now back to the Events tab on the Edit Step dialog. Notice a few lines of script being added to the box next to the Entry event (as shown in the following screenshot): OK the dialog. It's time to test your changes. Check in a new document. Make sure you set the Author field to sysadmin. Set your Security Group to accounting, and Account to accounting/payable/current. If you don't, the item will not enter our workflow in the first place (as shown in the following screenshot): Complete your check-in and follow the link to go to the Content Info page. See the status of the item. It should be set to Released. That's right. The item got right out of the workflow. Check in a new document again, but use some other author. Notice how your item will enter the workflow and stay there. As you've seen, the dialog we used for creating a jump is simply a code generator. It created a few lines of script we needed to add the handler for the Entry event. Click on the Edit button next to that code and pick Edit Current to study it. You can find all the script function definitions in iDoc Reference Guide. Perfect! And we're still not done. What if you have a few common steps that you'd like to reuse in a bunch of workflows? Would you just have to manually recreate them? Nope. There are several solutions that allow you to reuse parts of the workflow. The one I find to be most useful is sub workflows.
Read more
  • 0
  • 0
  • 3809

article-image-managing-user-accounts-oracle-siebel-crm-8
Packt
06 Aug 2010
5 min read
Save for later

Managing User Accounts in Oracle Siebel CRM 8

Packt
06 Aug 2010
5 min read
Understanding divisions and organizations Mapping real world entities to technical concepts is one of the key factors for successful software products. It is therefore quite interesting to see how the Siebel design team faced the challenge of bringing the complex hierarchical relationships of large corporations into the Siebel data model. Early in the analysis phase of a Siebel CRM implementation project, the divisional or departmental hierarchy of the customer is analyzed and documented. The typical diagram type to document the divisions of a company is an organization chart. The following is the organization chart for an example company: The Sales, Service, and Marketing divisions are subordinate to the Headquarter division. The Sales department has subdivisions, which define the territories (North and South) that the sales force operates in. Setting up divisions Once the divisional hierarchy of a company is documented, it must be translated to Siebel administrative data. An administrator uses the Administration - Group screen, Internal Divisions view—shown in the following screenshot—to enter and manage the division information: This view allows administrators to enter and maintain information about a company's divisions. The example company visible in the screenshot (Vision Corporation) is part of the Siebel sample database and has four subordinate divisions. In order to create a new divisional hierarchy, we can follow the steps in the task list below: Log in to the Siebel application using an administrative user account. Navigate to the Administration - Group screen, Internal Divisions view. Create a new record for the top-level division first. Enter address and other information if required. Save the division record. Create a new division for each subordinate division and use the Parent Division field to select the appropriate parent division. Use the explorer applet to verify that the divisional hierarchy represents the organization chart. The following screenshot shows the explorer applet in the Internal Divisions view after the entry of the data from the example organization chart: In order to distinguish the example company from other divisions in the database, the acronym "AHA " was used. From an administrative perspective, we must be aware of the fact that organizational changes might occur frequently. These changes can include one department becoming subordinate of another, or other departments being detached from the hierarchy in order to become separate companies. Siebel administrators must be informed of these changes in order to be able to adjust the division data in a timely manner. In your demonstration environment, use the instructions in the above section to create a division hierarchy. You might want to use the example or create your own divisions. Setting up organizations When a division or an entire partner company wants to use the Siebel CRM infrastructure, this is typically accompanied by the requirement to associate data with the division or partner company in order to provide data security. Siebel administrators can declare a division as an organization. This is done by simply checking the Organization Flag of a division. However, this change cannot be undone. Once the division is flagged as an organization and the record is saved, the flag becomes read only, as shown in the following screenshot: We can decide which divisions within the organization chart should be flagged as organizations depending on the data security requirements defined by the project team. The result is typically a second hierarchy of organizations within the division hierarchy. Once an organization is created, Siebel data such as customer accounts, service requests, and so on can be associated with the organization. The following diagram shows how the divisions named Headquarter and Sales have been flagged as organizations. They are now part of the organization hierarchy. By default, each new organization becomes subordinate to the "Default Organization", which the position of the Siebel Administrator (SADMIN) is assigned to. If data security policies mandate, we must set the Parent Organization field to an empty value in the Organizations view of the Administration - Group screen. Even if a division cannot be associated to Siebel data, employees who have a position within that division are automatically associated with the nearest organization that can be located upwards in the division hierarchy. In the above example, an employee who has a position in the AHA Sales North division will be associated with the Sales organization. The following screenshot shows the AHA Sales North division (note that the Organization Flag is unchecked) in the Internal Divisions view: The Organization Name field displays the name of the nearest organization (AHA Sales) above the AHA Sales North division. Employees who are associated with a position in the AHA Sales North division will automatically be associated with the AHA Sales organization. They will therefore be able to see data associated with the AHA Sales organization and each record they create will be automatically associated with the AHA Sales organization. Similar to divisions, organizations cannot be deleted. When organizational changes require it, a Siebel administrator must detach the non-existing organization or division from all parent records by emptying the parent division field and change the name to indicate the state of the organization or division. For example, the name can be prefixed with "NOT USED" to indicate that the division or organization no longer exists. Furthermore, records that are associated with an organization that no longer exists must be re-assigned to other organizations. This is typically achieved by using the Siebel Assignment Manager. Mark at least one of the sample divisions you created earlier as an organization by setting the Organization Flag and saving the record.
Read more
  • 0
  • 0
  • 4149

article-image-building-consumer-review-website-using-wordpress-3
Packt
06 Aug 2010
15 min read
Save for later

Building a Consumer Review Website using WordPress 3

Packt
06 Aug 2010
15 min read
(For more resources on Wordpress, see here.) Building a consumer review website will allow you to supply consumers with the information that they seek and then, once they've decided to make a purchase, your site can direct them to a source for the product or service. This process can ultimately allow you to earn some nice commission checks because it's only logical that you would affiliate yourself with a number of the sites to which you will be directing consumers. The great thing about using the WP Review Site plugin to build your consumer review website is that you can provide people with an unbiased source of public opinions on any product or service that you can imagine. You will never have to resort to the hard sell in order to drive traffic to the companies that you've affiliated yourself with. Instead, consumers can research the reviews posted on your website and,ultimately, make a purchase feeling confident that they're making the right decision. In this article, you will learn about the following: Present reviews in the most convenient way possible for visitors browsing your site Specify the ratings criteria that site visitors will use when reviewing the products or services included on your website Display informational comparison tables on your site's index and category pages Provide visitors with the location of local businesses using Google Maps Perform the additional steps required when writing a post now that the WP Review Site plugin has been introduced into the process Perform either automatic and manual integration so that you can use a theme of your own rather than either of the ones provided with this plugin Once this project is complete, you will have succeeded in creating a site that's similar to the one shown in the following screenshot:   Introducing WP Review Site With the WP Review Site plugin you will be able to build a consumer review site where visitors can share their opinions about the products or services of your choosing. The plugin, which can be found at WP Review Site, can be used to build a dedicated review site or, if you would like consumer reviews to make up only a subsection of your website, then you can specify certain categories where they should appear. This plugin gives you complete control over where ratings appear and where they don't since you can choose to include or exclude them on any category, page, or post. The WP Review Site plugin seamlessly integrates with WordPress by, among other things, altering the normal appearance and functionality of the comments submission form. This plugin provides visitors with a way to write a review and assign stars to the ratings categories that you previously defined. They can also write a review and opt to provide no stars without harming the overall rating presented on your site, since no stars is interpreted as though no rating was given. WP Review Site plugin makes it easy for you to present your visitors with concise information. Using the features available with this plugin, you can build comparison tables based upon your posts and user reviews. In order to accomplish this, you will need to configure a few settings and then the plugin will take care of the rest. Typically, WordPress displays posts in chronological order, but that doesn't make much sense on a consumer review site where visitors want to view posts based upon other factors such as the number of positive reviews that a particular product or service has received. The developer behind WP Site Review took that into consideration and has included two alternative sorting methods for your site's posts. The developer has even included a Bayesian weighting feature so that reviews are ordered in the most logical way possible. Right about now, you're probably wondering what Bayesian weighting is and how it works. What it does is provide a way to mathematically calculate the rating of products and/or services based upon the credibility of the votes that have been cast. If an item receives only a few votes, then it can't be said with any certainty that that's how the general public feels. If an item receives several votes, then it can be safely assumed that many others hold the same opinion. So, with Bayesian weighting, a product that has received only one five star review won't outrank another that has received fifteen four star reviews. As the product that received one five star review garners more ratings, its reviews will grow in credibility and, if it continues to receive high ratings, it will eventually become credible enough to outrank the other reviews. If you're planning to create a website where visitors can come and review local businesses, then you might consider this plugins ability to automatically embed Google Maps quite handy. After configuring the settings on the plugin's Google Maps screen you will be able to type the address for a business into a custom field when writing a post and then the plugin will take care of the rest. The WP Review Site plugin also includes two sidebar widgets that can used with any widget-ready theme. These widgets will allow you to display a list of top rated items and a list of recent reviews. Lastly, the themes provided with this plugin include built-in support for the hReview microformat. This means that Google will easily be able to extract and highlight reviews from your website. That feature will prove to be very beneficial for driving search engine traffic to your site. Installing WP Review Site Once you've installed WordPress you can then concentrate on the installation of the WP Review Site plugin and its accompanying themes. First, extract the wpreviewsite.zip archive. Inside you will find a plugins folder and a themes folder. Within the plugins folder is another folder named review-site. Since none of these folders are zipped, you will need to upload them using either an FTP program or the file manager provided by your web host. So, upload the review-site folder to the wp-content/plugins directory on your server. If you plan to use one of the themes provided with this plugin, then you will next need to upload the contents of the themes folder to the wp-content/themes directory. Setting up and configuring WP Review Site With the installation process complete, you will now need to activate the WP Review Site plugin. Once that's finished, a Review Site menu will appear on the left side of your screen. This menu contains links to the settings screens for this plugin. Before you delve into the configuration process you must first activate the theme that you plan to use on your consumer review website. Using one of the provided themes is a bit easier. That's because using any other theme will mean that you must integrate the functionality of WP Review Site into it. Now that you know the benefits offered by the themes that are bundled with this plugin, click on Appearance | Themes. Once there, activate either Award Winning Hosts, Bonus Black, or a theme of your choice. General Settings Navigate to Review Site | General Settings to be taken to the first of the WP Review Site settings screens. On this screen, Sort Posts By is the first setting that you will encounter. Rather than displaying reviews in the normal chronological order used by WordPress you should, instead, select either the Average User Rating (Weighted) or the Number of Reviews/Comments option. Either of these settings will provide a much more user-friendly experience for your visitors. If you want to make it impossible for site visitors to submit a comment without also choosing a rating, tick the checkbox next to Require Ratings with All Comments. If you don't want to make this a requirement, then you can leave this setting as is. This setting will, of course, only apply to posts that you would like your visitors to rate. On normal posts, that don't include rating stars in the comment form area, it will still be possible for your visitors to submit a comment. When using one of the themes provided with the plugin, none of the other settings on this screen need to be configured. If you would like to integrate this plugin into a different theme, then, depending upon the method that you choose, you may need to revisit this screen later on. No matter how you're handling the theme issue, you can, for now, just click Save Settings before proceeding to the next screen. Rating Categories To access the next settings screen, click on Review Site | Rating Categories. Here you can add categories for people to rate when submitting reviews. These categories shouldn't be confused with the categories used in WordPress for organizational purposes. These WP Review Site categories are more like ratings criteria. By default, WP Review Site includes a category called Overall Rating, but you can click the remove link to delete it if you like. To add your first rating category, simply enter its title into the Add a Category textbox and then click Save Settings. The screen will then refresh and your newly created rating category will now appear under the Edit Rating Categories section of the screen. To add additional rating categories, simply repeat the process that you previously completed. Once you've finished adding rating categories, you will next need to turn your attention to the Bulk Apply Rating Categories section of the screen. In the Edit Rating Categories area you will see all of the rating categories that you just finished adding to your site. If you want to simplify matters, and apply these rating categories to all of the posts on your site, tick the checkbox next to each of the available rating categories. Then, from the Apply to Posts in Category drop-down menu, select All Categories. This is most likely the configuration that you will use if you're building a website entirely dedicated to providing consumer reviews. Once you've finished, click Save Settings. If you, instead, want your newly added rating categories to only appear on certain categories, then bypass the Edit Rating Categories area for now and first look to the Apply to Posts in Category settings area. Currently this will only show All Categories and Uncategorized. The lack of categories in this menu is being caused by two things. First, you haven't added any WordPress categories to your site yet. Secondly, categories won't be included in this menu until they contain at least one post. To solve part of this problem, open a new browser window and then, navigate to Posts | Categories. Then, add the categories that you would like to include on your website. Now, click on Posts | Edit to visit the Edit Posts screen. At the moment, the Hello world! post is the only one published on your site and you can use it to force your site's categories to appear in the Apply to Posts in Category drop-down menu. So, hover over the title of this post and then, from the now visible set of links, click Quick Edit. In the Categories section of the Quick Edit configuration area, tick the checkbox next to each of the categories found on your site. Then, click Update Post. After content has been added to each of your site's categories, you can delete the Hello world! post, since you will no longer need to use it to force the categories to appear in the Apply to Posts in Category drop-down menu. Now, return to the Rating Categories screen and then select the first category that you want to configure from the Apply to Posts in Category drop-down menu. With that selected, in the Edit Rating Categories area, tick the checkbox next to each rating category that you want to appear within that WordPress category. Then, click Save Settings. Repeat this process for each of the WordPress categories to which you would like rating categories to be added. Comparison Tables If you wish, you can add a comparison table to either the home page or the category pages on your site. To do this, you need to visit the Comparison Tables screen, so click on Review Site | Comparison Tables. If you want to display a comparison table on your home page, then tick the checkbox next to Display a Comparison Table on Home Page. If you would like to include all of your site's categories in the comparison table that will be displayed on the home page, then leave the Categories To Display On Home Page textbox as is. However, if you would prefer to include only certain categories, then enter their category IDs, separated by commas, into the textbox instead. You can learn the ID numbers that have been assigned to each of your site's categories by opening a new browser window and then navigating to Posts | Categories. Once there, hover over the title of each of the categories found on the right hand side of your screen. As you do, look at the URL that appears in your browser's status bar and make a note of the number that appears directly after tag_ID=. That's the number that you will need to enter in the Comparison Table screen. If you want to display a comparison table in one or more categories, then tick the checkbox next to Display a Comparison Table on Category Page(s). Now, return to the Comparison Table screen. If you want a comparison table to be displayed on each of your category pages, leave the Categories To Display Comparison Table On textbox at its default. Otherwise, enter a list of comma separated category IDs into the textbox for the categories where you want to display comparison tables. The Number of Posts in the Table setting is currently set to 5, but you can enter another value if you would like a different number of posts to be included in each comparison table. When writing posts, you might use custom fields to include additional information. If you would like that information to be displayed in your comparison tables you will need to enter the names of those fields, separated by commas, into the Custom Fields to Display textbox. Lastly, you can change the text that appears in the Text for the Visit Site link in the Table if you wish or you may leave it at its default. With these configurations complete, click Save Settings. In this screenshot, you can see what a populated comparison table will look like on your website: Google Maps If you plan on featuring reviews centered around local businesses, then you might want to consider adding Google Maps to your site. This will make it easy for visitors to see exactly where each business is located. You can access this settings screen by clicking on Review Site | Google Maps. To activate this feature, tick the checkbox next to Display a Google Map on Posts/Pages with mapaddress Custom Field. Next, you need to use the Map Position setting to specify where these Google Maps will appear in relation to the content. You can choose to use either the Top of Post or Bottom of Post position. The Your Google Maps API Key textbox is next. Here you will need to enter a Google Maps API key. If you don't have a Google Maps API key for this domain, then you will need to visit Google to generate one. To do this, right-click on the link provided on the Google Maps screen and then open that link in a new browser window. You will then be taken to the Google Maps API sign up screen, which can be found at Google Maps API sign up. If you've ever signed up to use any of Google's services, then you can use that username and password to log in. If you don't have an account with Google, create one now. Take a moment to read the information and terms presented on the Google Maps API sign up page. After you've finished reviewing this text, if it's acceptable to you, enter the URL for your website into the My web site URL textbox and then click Generate API Key. You will then be taken to a thank you screen where your API key will be displayed. Copy the API key and then return to the Google Maps screen on your website. Once there, paste your API key into the textbox for Your Google Maps API Key. The Map Width and Map Height settings are next. By default, these are configured to 400px and 300px. If you would prefer that the maps be displayed at a different size, then enter new values into each of these textboxes. The last setting is Map Zoom Level (1-5), which is currently set to 3. This setting should be fine, but you may change it if you wish. Finally, click Save Settings. When you publish a post that includes the mappadress custom field, this is what the Google Map will look like on your site.
Read more
  • 0
  • 0
  • 8538

article-image-coldfusion-9-power-cfcs-and-web-forms
Packt
05 Aug 2010
13 min read
Save for later

ColdFusion 9: Power CFCs and Web Forms

Packt
05 Aug 2010
13 min read
(For more resources on ColdFusion, see here.) There used to be long pages of what we called "spaghetti code" because the page would go on and on. You had to follow the conditional logic by going through the page up and down, and then had to understand how things worked. This made writing, updating, and debugging a diffcult task even for highly-skilled developers CFCs allow you to encapsulate some part of the logic of a page inside an object. Encapsulation simply means packaged for reuse inside something. CFCs are the object-packaging method used in ColdFusion. The practice of protecting access In CFC methods, there is an attribute called "access".Some methods within a CFC are more examples of reuse. The sample code for _product.cfc is shown here. It is an example of a power CFC. There is a method inside the CFC called setDefaults(). The variable variables.field.names comes from another location in our CFC: <cffunction name="setDefaults" access="private" output="false"> <cfset var iAttr = 0> <cfloop list="#listLen(variables.field.names)#" index="iAttr"> <cfscript> variables.attribute[#listGetAt(variables.field.names,iAttr)#] = setDefault(variables.field.names,iAttr); </cfscript> </cfloop></cffunction> The logic for this would actually be used in more than one place inside the object. When the object is created during the first run, it would call the setDefaults() method and set the defaults. When you use the load method to insert another record inside the CFC, it will run this method. This will become simpler as you use CFCs and methods more often. This is a concept called refactoring, where we take common features and wrap them for reuse. This takes place even inside a CFC. Again, the setDefaults() function is just another method inside the same CFC. Now, we look at the access attribute in the code example and note that it is set to private. This means that only this object can call the method. One of the benefits to CFCs is making code simpler. The interface to the outside world of the CFC is its methods. We can hide a method from the outside world, and also protect access to the method by setting the access attribute to private. If you want to make sure that only CFCs in the same directory can access these CFC's methods, then you will have to set the attribute to package. This is a value that is rarely used. The default value for the access attribute is public. This means that any code running on the web server can access the CFC. (Shared hosting companies block one account from being able to see the other accounts on the same server. If you are concerned about your hosting company, then you should either ask them about this issue or move to a dedicated or virtual hosting server.) The last value for the access attribute is remote. This is actually how you create a number of "cool power" uses of the CFC. There is a technology on the Web called web services. Setting the CFC to remote allows access to the CFC as a web service. You can also connect to this CFC through Flash applications, Flex, or AIR, using the remote access value. This method also allows the CFC to respond to AJAX calls. Now, we will learn to use more of the local power features. Web forms introduction Here, we will discuss web forms along with CFCs. Let us view our web form page. Web forms are the same in ColdFusion as they are in any other HTML scenario. You might even note that there is very little use for web forms until you have a server-side technology such as ColdFusion. This is because when the form is posted, you need some sort of program to handle the data posted back to the server. <!--- Example: 3_1.cfm ---><!--- Processing ---><!--- Content ---><form action="3_1.cfm" method="post"> <table> <tr> <td>Name:</td> <td><input type="text" name="name" id="idName" value="" /></td> </tr> <tr> <td>Description:</td> <td><input type="text" name="description" id="idDescription" value="" /></td> </tr> <tr> <td>Price:</td> <td><input type="text" name="price" id="idPrice" value="" /></td> </tr> <tr> <td>&nbsp;</td> <td><input type="submit" name="submit" value="submit" /></td> </tr> </table></form> First, notice that all of the information on the page is in the content section. Anything that goes from the server to the browser is considered as content. You can fll in and submit the form, and you will observe that all of the form fields get cleared out. This is because this form posts back to the same page. Self-posting forms are a valid method of handling page fow on websites. The reason why nothing seems to be happening is because the server is not doing anything with the data being sent back from the browser. Let us now add <cfdump var="#form#"/> to the bottom of the content, below the form tag, and observe what we get when we post the form: Now we see another common structure in ColdFusion. It is known as the form structure. There are two types of common structures that send data to the server. The first one is called get and the second one is called post. If you see the code, you will notice that the method of the form is post. The form post setting is the same as coding with the form variable in ColdFusion. You should also observe that there is one extra field in the form structure that is not shown in the URL structure variable. It is the FIELDNAMES variable. It returns a simple list of the field names that were returned with the form. Let us edit the code and change the form tag attribute to get. Then, refresh the page and click on the submit button: From the previous screenshot, it is evident that the browser looks at the get or post value of the form, and sends a get or post back to the server. Post is a "form method" belonging to the past and this is why ColdFusion translates posted variables to the form structure. Now change the dump tag to "URL" and observe the results. Fill out the form and submit it again with the new change. This displays the values in our structure as we would expect. This means you can either send URL-type data back to the server, or form-type data with forms. The advantage of sending form data is that form data can handle a larger volume of data being sent back to the server as compared to a get or URL request. Also, it is worth noting that this style of return prevents the form field values from being exposed in the URL. They can still be accessed, but are just not visible in the URL any more. So the method of choice for forms is post. Change both the method of the form attribute and the value of the cfdump var to form again. The Description box is not ideal for entering product descriptions. So, we are going to use a text area in its place. Use the following code to accommodate a text area box. You can change the size of form's objects using attributes and styles: <tr> <td>Description:</td> <td> <textArea name="description" id="idDescription"></textArea> </td></tr> Here, we see our form looking different. If you fill up the description with more content than the box can hold, it shows the scroll bars appropriately. Managing our product data Currently, we have a form that can be used for two purposes. It can be used to enter a new product as well as to edit existing ones. We are going to reuse this form. Reuse is the fastest path to make things easier. However, we must not think that it is the only way to do things. What we should think is that not reusing something requires a reason for doing it differently. In order to edit an existing product, we will have to create a page that shows the existing product records. Let us create the page: <!--- Example: product_list.cfm ---><!--- Processing ---><cfscript> objProduct = createObject("component","product").init(dsn="cfb"); rsProducts = objProduct.getRecordset();</cfscript><!--- Content ---><h3>Select a product to edit.</h3><ul> <cfoutput query="rsProducts"> <li> <a href="product_edit.cfm?id=#rsProducts.id#">#rsProducts.name# </li> </cfoutput></ul> There is no new code here. This is the browser view that we get when we run this page. Here, we will post our edit page. Before you run the code, take the code from 3_1.cfm that we wrote at the beginning of the article and save a copy as product_edit.cfm to make the page work correctly when someone clicks on any of the products: Now, we will click on a product. Let us manage the Watermelon Plant for now and observe what happens on the next page: This is our edit page, and we will modify it so that it can get the data when we click through from our list page. Getting data to our edit page The current page looks similar to the page where we put the form. To get the data from our database onto the page, we need to do a few things here. First, let us change the action of the form tag to product_edit.cfm. We can modify the processing section of the page frst, which will make things simpler. Add the following code to your product_edit.cfm page: <!--- Processing ---><cfparam name="url.id" default="0"><cfscript> objProduct = createObject("component","product").init(dsn="cfb"); objProduct.load(url.id);</cfscript> We need the default value set so that we do not receive an error message if the page is called without an id. After we set our default, we will see that we have created an object from our CFC object class. This time, we are passing the Data Source Name dsn into the object through the constructor method. This makes our code more portable, and ready for reuse. Once we have an instance, we set the current record using the load method and passing the id of the data record to the method. Let us look at the minor changes that we will make to the content section. We will add the values of the object's protected attributes. <!--- Content ---><cfoutput> <form action="product_edit.cfm" method="post"> <table> <tr> <td>Name:</td> <td> <input type="text" name="name" id="idName" value="#objProduct.get('name')#" /> </td> </tr> <tr> <td>Description:</td> <td> <textArea name="description" id="idDescription"> #objProduct.get('description')#</textArea> </td> </tr> <tr> <td>Price:</td> <td> <input type="text" name="price" id="idPrice" value="#objProduct.get('price')#" /> </td> </tr> <tr> <td>&nbsp;</td> <td> <input type="submit" name="submit" value="submit" /> </td> </tr> </table> </form></cfoutput> Now, we will refresh the form and see how the results differ: Doesn't this look better? We can go back to the list page and retrieve an existing product from the edit form. If we submit back the same form, browsers tend to empty out the form. It should not do that, but the form is not posting the ID of the record back to the server. This can lead to a problem because, if we do not send the ID of the record back, the database will have no idea as to which record's details should be changed. Let us solve these issues first, and then we will learn to use a new tag called the <cfinclude> tag along the way. The first problem that we are going to solve is where we are calling the page with the ID value in the URL structure; then, if we post the page we will be calling the page with the ID in the form structure. We are going to use a technique that has been widely used for years in the ColdFusion community. We are going to combine the two scopes into a new common structure. We will create a structure called attributes. First we will check if it exists. If it does not, then we will create the structure. After that, we will merge the URL structure, and then the FORM structure into the attributes structure. We will put that code in a common page called request_attributes.cfm, so we can include it on any page we want, reusing the code. Do remember that the form and URL scope always exist. <!--- request_attributes.cfm ---><cfscript> if(NOT isDefined("attributes")) { attributes = structNew(); } structAppend(attributes,url); structAppend(attributes,form);</cfscript> Let us modify our edit page in order to take care of a couple of issues. We need to include the script that we have just created. We will modify the processing section of our edit page as highlighted here: <!--- Processing ---><cfinclude template="request_attributes.cfm"><cfparam name="attributes.id" default="0"><cfscript> objProduct = createObject("component","product").init(dsn="cfb"); objProduct.load(attributes.id);</cfscript> There is only one more thing we need now: We need our form to store the id value of the record that is being managed. We could just put it in a textbox like the other fields, but the user does not need to know that information. Let us use a hidden input field and add it after our form tag: <!--- Content ---><cfoutput> <form action="product_edit.cfm" method="post"> <input type="hidden" name="id" value="#objProduct.get('id')#"> Refresh the screen, and it will work when we use the form, or when we choose an item from the product list page. We have now created our edit/add page.
Read more
  • 0
  • 0
  • 3331
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-agile-yii-11-and-php5-trackstar-application
Packt
05 Aug 2010
13 min read
Save for later

Agile with Yii 1.1 and PHP5: The TrackStar Application

Packt
05 Aug 2010
13 min read
(For more resources on Agile, see here.) Introducing TrackStar TrackStar is a Software Development Life Cycle (SDLC) issue management application. Its main goal is to help keep track of all the many issues that arise throughout the course of building software applications. It is a user-based application that allows the creation of user accounts and grants access to the application features, once a user has been authenticated and authorized. It allows a user to add and manage projects. Projects can have users associated with them (typically the team members working on the project) as well as issues. The project issues will be things such as development tasks and application bugs. The issues can be assigned to members of the project and will have a status such as not yet started, started, and finished. This way, the tracking tool can give an accurate depiction of projects with regard to what has been accomplished, what is currently in progress, and what is yet to be started. Creating user stories Simple user stories are a great way to identify the required features of your application. User stories, in their simplest form, state what a user can do with a piece of software. They should start simple, and grow in complexity as you dive into more and more of the details around each feature. Our goal here is to begin with just enough complexity to allow us to get started. If needed, we'll add more detail and complexity later. We briefly touched on the three main entities that play a large role in this application: users, projects, and issues. These are our primary domain objects, and are extremely important items in this application. So, let's start with them. Users TrackStar is a user-based web application. There will be two high-level user types: Anonymous Authenticated An anonymous user is any user of the application that has not been authenticated through the login process. Anonymous users will only have access to register for a new account or to log in. All other functionality will be restricted to authenticated users. An authenticated user is any user that has provided valid authentication credentials through the login process. In other words, authenticated users are logged-in users. They will have access to the main features of the application such as creating and managing projects, and project issues. Projects Managing the project is the primary purpose of the TrackStar application. A project represents a general, high-level goal to be achieved by one or more users of the application. The project is typically broken down into more granular tasks (or issues) that represent the smaller steps that need to be taken to achieve the overall goal. As an example, let's take what we are going to be doing throughout this book, that is, building a project and issue tracking management application. Unfortunately, we can't use our yet-to-be-created application as a tool to help us track its own development. However, if we were using a similar tool to help track what we are building, we might create a project called Build The TrackStar Project/Issue Management Tool. This project would be broken down into more granular project issues such as 'Create the login screen' or 'Design database schema for issues', and so on. Authenticated users can create new projects. The creator of the project within an account has a special role within that project, called the project owner. Project owners have the ability to edit and delete these projects as well as add new members to the project. Other users associated with the project—besides the project owner—are referred to simply as project members. They have the ability to add new issues, as well as edit existing ones. Issues Project issues can be classified into one of the following three categories: Features: Items that represent real features to be added to the application. For example, 'Implement the login functionality' Tasks: Items that represent work that needs to be done, but is not an actual feature of the software. For example, 'Set up the build and integration server' Bugs: Items that represent application behaviors that are not working as expected. For example, 'The account registration form does not validate the format of input e-mail addresses' Issues can have one of the following three statuses: Not yet started Started Finished Project members can add new issues to a project, as well as edit and delete them. They can assign issues to themselves or other project members. For now, this is enough information on these three main entities. We could go into a lot more detail about what exactly account registration entails' and how exactly one adds a new task to a project', but we have outlined enough specifications to begin on these basic features. We'll nail down the more granular details as we proceed with the implementation. However, before we start, we should jot down some basic navigation and application workflow. This will help everyone to better understand the general layout and flow of the application we are building. Navigation and page flow It is always good to outline the main pages within an application, and how they fit together. This will help us quickly identify some needed Yii controllers, actions and views as well as help to set everyone's expectations as to what we'll be building towards at the onset of our development. The following figure shows the basic idea of the application flow from logging in, through the project details listing: When users first come to the application, they must log in to authenticate themselves before accessing any functionality. Once successfully logged-in, they will be presented with a list of his current projects along with the option to create a new project. Choosing a specific project will take them to the project details page. The project details page will present a list of the issues by type. There will also be the option to add a new issue as well as edit any of the listed issues. This is all pretty basic functionality, but the figure gives us a little more information on how the application is stitched together and allows us to better identify our needed models, views, and controllers. It also allows something visual to be shared with others so that everyone involved has the same 'picture' of what we are working towards. In my experience, almost everyone prefers pictures over written specifications when first thinking through a new application. Defining a data scheme We still need to think a little more about the data we will be working with as we begin to build toward these specifications. If we pick out all the main nouns from our system, we may end up with a pretty good list of domain objects and, by extension of using Active Record, the data we want to model. Our previously outlined user stories seem to dictate the following: A User A Project An Issue Based on this and the other details provided in the user stories and application workflow diagram, a first attempt at the needed data is shown in the following figure. This is a basic object model that outlines our primary data entities, their respective attributes, and some of the relationships between them. The 1..* on either side of the line between the Project and User objects represents a many-to-many relationship between them. A user can be associated with one or more projects, and a project has one or more users. Similarly we have represented the fact that a project can have zero or more issues associated with it, whereas an issue belongs to just one specific project. Also, a user can be the owner of (or requester of) many issues, but an issue has just one owner (and also just one requester). We have kept the attributes as simple as possible at this state. A User is going to need a username and a password in order to get past the login screen. The Project has only a name Issues have the most associated information based on what we currently know about them. As discussed briefly in the user stories above, they will have a type attribute to distinguish the general category (bug, feature, or task). They will also have a status attribute to indicate the progress of the issue being worked on. A user in the system will initially create the issue, this is the requester. Once a user in the system has been assigned to work on the issue, they will be the owner of the issue. We have also defined the description attribute to allow for some descriptive text of the issue to be entered. Notice that we have not explicitly talked about schemas or databases yet. The fact is, until we think through what is really needed from a data perspective, we won't know the right tool to use to house this data. Would flat files on the filesystem work just as well as a relational database? Do we need a persistent data at all?   The answers to these questions are not needed in this early planning state. It is better to focus more on the features that we want and the type of data needed to support these features. We can turn to the explicit technology implementation details after we have had a chance to discuss these ideas with other project stakeholders to ensure we are on the right track. Other project stakeholders include anyone and everyone involved in this development project. This can include the client, if building an application for someone else, as well as other development team members, product/project managers, and so on. It is always a good idea to get some feedback from "the team" to help validate the approach and any assumptions being made. However, before we dive right into building our application, we need to cover our development approach. We will be employing some specific development methodologies and principles, and it makes sense to go over these prior to getting started with coding. Defining our development methodology We will be employing an agile inspired process of iterative and incremental development as we build this application. 'Agile' is certainly a loaded term in modern software development and can have varied meanings among developers. Our process will focus on the aspects of an agile methodology that embrace transparent and open collaboration, constant feedback loops, and a strong ability to respond quickly to changing requirements. We will work incrementally in that we won't wait until every detail of the application has been specified before we start coding. Once the details of a particular feature have been finalized, we can begin work on implementing that feature, even though other features or application details are still in the design/planning stage. The process surrounding this feature implementation will follow an iterative model. We will do some initial iteration planning, engage in analysis and design, write the code to try out these ideas, test the code, and gather feedback. We then repeat this cycle of design->code->test->evaluation, until everyone is happy. Once everyone is happy, we can deploy the application with the new feature, and then start gathering the specifications on the next feature(s) to be implemented in the next iteration. Automated software testing Gathering feedback is of fundamental importance to agile development. Feedback from the users of the application and other project stakeholders, feedback from the development team members, and feedback directly from the software itself. Developing software in a manner that will allow it to tell you when something is broken can turn the fear associated with integrating and deploying applications into boredom. The method by which you empower your software with this feedback mechanism is writing unit and functional tests, and then executing them repeatedly and often. Unit and functional testing Unit tests are written to provide the developer with verification that the code is doing the right things. Functional tests are written to provide the developer, as well as other project stakeholders, that the application, as a whole, is doing things the right way. Unit tests Unit tests are tests that focus on the smallest units within a software application. In an object-oriented application, (such as a Yii web application) the smallest units are the public methods that make up the interfaces to classes. Unit tests should focus on one single class, and not require other classes or objects to run. Their purpose is to validate that a single unit of code is working as expected. Functional tests Functional tests focus on testing the end-to-end feature functionality of the application. These tests exist at a higher level than the unit tests and typically do require multiple classes or objects to run. Their purpose is to validate that a given feature of the application is working as expected. Benefits of testing There are many benefits to writing unit and functional tests. For one, they are a great way to provide documentation. Unit tests can quickly tell the exact story of why a block of code exists. Similarly, functional tests document what features are implemented within an application. If you stay diligent in writing these tests, then the documentation continues to evolve naturally as the application evolves. They are also invaluable as a feedback mechanism to constantly reassure the developer and other project stakeholders that the code and application is working as expected. You run your tests every time you make changes to the code and get immediate feedback on whether or not something you altered inadvertently changed the behavior of the system. You then address these issues immediately. This really increases the confidence that developers have in the application's behavior and translates to fewer bugs and more successful projects. This immediate feedback also helps to facilitate change and improving the design of the code base. A developer is more likely to make improvements to existing code if a suite of tests are in place to immediately provide feedback as to whether the changes made altered the application behavior. The confidence provided by a suite of unit and functional tests allows developers to write better software, release a more stable application, and ship quality products. Test-driven development Test-driven development (TDD) is a software development methodology that helps to create an environment of comfort and confidence by ensuring your test suite grows organically with your application, and is always up-to-date. It does this by stipulating that you begin your coding by first writing a test for the code you are about to write. The following steps sum up the process: Begin by writing a test that will quickly fail. Run the test to ensure it does, indeed, fail. Quickly add just enough code to the class you are testing to get the test to pass. Run the test again to ensure it does, indeed, pass. Refactor the code to remove any repetitive logic or improve any corners cut while you were just trying to get the test to pass. These steps are then repeated throughout the entire development process. Even with the best intentions, if you wait to write your tests until after the code is completed, you probably won't. Writing your tests first and injecting the test writing process directly into the coding process will ensure the best test coverage. This depth of coverage will help minimize the stress and fear that can accompany complex software applications and build confidence by constantly providing positive feedback as additions and changes are made. In order to embrace a TDD process, we need to understand how to test within a Yii application.
Read more
  • 0
  • 0
  • 4935

article-image-freeswitch-utilizing-built-ivr-engine
Packt
05 Aug 2010
10 min read
Save for later

FreeSWITCH: Utilizing the Built-in IVR Engine

Packt
05 Aug 2010
10 min read
IVR engine overview Unlike many applications within FreeSWITCH which are built as modules, IVR is considered the core functionality of FreeSWITCH. It is used anytime a prompt is played and digits are collected. Even if you are not using the IVR application itself from your Dialplan, you will see IVR-related functions being utilized from various other applications. As an example, the voicemail application makes heavy use of IVR functionality when playing messages, while awaiting digits to control deleting, saving, and otherwise managing voicemails. In this section, we will only be reviewing the IVR functionality that is exposed from within the ivr Dialplan application. This functionality is typically used to build an auto-attendant menu, although other functions are possible as well. IVR XML configuration file FreeSWITCH ships with a sample IVR menu are typically invoked by dialing 5000 from the sample Dialplan. When you dial 500, you will hear a greeting welcoming you to FreeSWITCH, and presenting your menu options. The menu options consist of calling the FreeSWITCH conference, calling the echo extension, hearing music on hold, going to a sub menu, or listening to screaming monkeys. We will start off reviewing the XML that powers this example. Open conf/autoload_configs/ivr.xml which contains the following XML: <configuration name="ivr.conf" description="IVR menus"> <menus> <!-- demo IVR, Main Menu --> <menu name="demo_ivr" greet-long="phrase:demo_ivr_main_menu" greet-short="phrase:demo_ivr_main_menu_short" invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav" exit-sound="voicemail/vm-goodbye.wav" timeout="10000" inter-digit-timeout="2000" max-failures="3" max-timeouts="3" digit-len="4"> <entry action="menu-exec-app" digits="1" param="bridge sofia/$${domain}/888@conference.freeswitch.org"/> <entry action="menu-exec-app" digits="2" param="transfer 9196 XML default"/> <entry action="menu-exec-app" digits="3" param="transfer 9664 XML default"/> <entry action="menu-exec-app" digits="4" param="transfer 9191 XML default"/> <entry action="menu-exec-app" digits="5" param="transfer 1234*256 enum"/> <entry action="menu-exec-app" digits="/^(10[01][0-9])$/" param="transfer $1 XML features"/> <entry action="menu-sub" digits="6" param="demo_ivr_submenu"/> <entry action="menu-top" digits="9"/> </menu> <!-- Demo IVR, Sub Menu --> <menu name="demo_ivr_submenu" greet-long="phrase:demo_ivr_sub_menu" greet-short="phrase:demo_ivr_sub_menu_short" invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav" exit-sound="voicemail/vm-goodbye.wav" timeout="15000" max-failures="3" max-timeouts="3"> <entry action="menu-top" digits="*"/> </menu> </menus> </configuration> In the preceding example, there are two IVR menus defined. Let's break apart the first one and examine it, starting with the IVR menu definition itself. IVR menu definitions The following XML defines an IVR menu named "demo_ivr". <menu name="demo_ivr" greet-long="phrase:demo_ivr_main_menu" greet-short="phrase:demo_ivr_main_menu_short" invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav" exit-sound="voicemail/vm-goodbye.wav" timeout="10000" inter-digit-timeout="2000" max-failures="3" max-timeouts="3" digit-len="4"> We'll use this menu's name later when we route calls to the IVR from the Dialplan. Following the name, various XML attributes specify how the IVR will behave. The following options are available when defining an IVR's options: greet-long The greet-long attribute specifies the initial greeting that is played when a caller reaches the IVR. This is different from the greet-short sound file which allows for introductions to be played, such as "Thank you for calling XYZ Company". In the sample IVR, the greet-long attribute is a Phrase Macro that plays an introductory message to the caller ("Welcome to FreeSWITCH...") followed by the menu options the caller may choose from. Argument syntax: Sound file name (or path + name), TTS, or Phrase Macro Examples: greet-long="my_greeting" greet-long="phrase:my_greeting_phrase" greet-long="say:Welcome to our company. Press 1 for sales, 2 for support." greet-short The greet-short attribute specifies the greeting that is re-played if the caller enters invalid information, or no information at all. This is typically the same sound file as greet-long without the introduction. In the sample IVR, the greet-short attribute is a Phrase Macro that simply plays the menu options to the caller, and does not play the lengthy introduction found in greet-long. Argument syntax: Sound file name (or path + name), TTS, or Phrase Macro Examples: greet-short="my_greeting_retry" greet-long="phrase:my_greeting_retry_phrase" greet-long="say:Press 1 for sales, 2 for support." invalid-sound The invalid-sound attribute specifies the sound that is played when a caller makes an invalid entry. Argument syntax: Sound file name (or path + name), TTS, or Phrase Macro Examples invalid-sound="invalid_entry.wav" invalid-sound="phrase:my_invalid_entry_phrase" invalid-sound="say:That was not a valid entry" exit-sound The exit-sound attribute specifies the sound, which is played when a caller makes too many invalid entries or too many timeouts occur. This file is played before disconnecting the caller. Argument syntax: Any number, in milliseconds Examples: exit-sound="too_many_bad_entries.wav" exit-sound="phrase:my_too_many_bad_entries_phrase" exit-sound="say:Hasta la vista, baby." timeout The timeout attribute specifies the maximum amount of time to wait for the user to begin entering digits after the greeting has played. If this time limit is exceeded, the menu is repeated until the value in the max-timeouts attribute has been reached. Argument syntax: Any number, in milliseconds Examples: timeout="10000" timeout="20000" inter-digit-timeout The inter-digit-timeout attribute specifies the maximum amount of time to wait in-between each digit the caller presses. This is different from the overall timeout.It is useful to allow enough time to enter as many digits as necessary, without frustrating the caller by pausing too long after they are done making their entry. For example, if both 1000 and 1 are valid IVR entries, the system will continue waiting for the inter-digit-timeout length of time after 1 is entered, before determining that it is the final entry. Argument syntax: Any number, in milliseconds Examples: inter-digit-timeout="2000" max-failures The max-failures attribute specifies how many failures, due to invalid entries, to tolerate before disconnecting. Argument syntax: Any number Examples: xx-xx="too_many_bad_entries.wav" xx-xx="phrase:my_too_many_bad_entries_phrase" max-timeouts The max-timeouts attribute specifes how many timeouts to tolerate before disconnecting. Argument syntax: Any number Examples: max-timeouts="3" digit-len The digit-len attribute specifes the maximum number of digits that the user can enter before determining the entry is complete. Argument syntax: Any number greater than 1. Examples: digit-len="4" tts-voice The tts-voice attribute specifes the specifc text-to-speech voice that should be used. Argument syntax: Any valid text-to-speech engine. Examples: tts-voice="Mary" tts-engine The tts-engine attribute specifies the specific text-to-speech engine that should be used. Argument syntax: Any valid text-to-speech engine. Examples: tts-engine="flite" confirm-key The confirm-key attribute specifes the key which the user can press to signify that they are done entering information. Argument syntax: Any valid DTMF digit. Examples: confirm-key="#" These attributes dictate the general behavior of the IVR. IVR menu destinations After defining the global attributes of the IVR, you need to specify what specific destinations (or options) are available for the caller to press. You do this with <entry > XML elements. Let's review the first five XML options used by this IVR: <entry action="menu-exec-app" digits="1" param="bridge sofia/$${domain}/888@conference.freeswitch.org"/> <entry action="menu-exec-app" digits="2" param="transfer 9196 XML default"/> <entry action="menu-exec-app" digits="3" param="transfer 9664 XML default"/> <entry action="menu-exec-app" digits="4" param="transfer 9191 XML default"/> <entry action="menu-exec-app" digits="5" param="transfer 1234*256 enum"/> <entry action="menu-exec-app" digits="/^(10[01][0-9])$/" param="transfer $1 XML features"/> Each preceding entry defines three parameters—an action to be taken, the digits the caller must press to activate that action, and the parameters that are passed to the action. In most cases you will probably use the menu-exec-app action, which simply allows you to specify an action and parameters to call just as you would from the regular Dialplan (bridge, transfer, hangup, and so on.). These options are all pretty simple—they define a single digit which, when pressed, either bridges a call or transfers the call to an extension. There is one entry that is a bit different from the rest, which is the fnal IVR entry. It deserves a closer look.   <entry action="menu-exec-app" digits="/^(10[01][0-9])$/" param="transfer $1 XML features"/> This entry definition specifes a regular expression for the digits feld. This regular expression feld is identical to the expressions you would use in the Dialplan. In this example, the IVR is looking for any four-digit extension number from 1000 through 1019 (which is the default extension number range for the predefined users in the directory). As the regular expression is wrapped in parenthesis, the result of the entry will be passed to the transfer application as the $1 channel variable. This effectively allows the IVR to accept 1000-1019 as entries, and transfer the caller directly to those extensions when they are entered into the IVR. The remaining IVR entry actions are a bit different. They introduce menu-sub as an action, which transfers the caller to an IVR sub-menu, and menu-top, which restarts the current IVR and replays the menu. <entry action="menu-sub" digits="6" param="demo_ivr_submenu"/> <entry action="menu-top" digits="9"/> Several other actions exist that can be used within an IVR. The complete list of actions you can use from within the IVR include the following: menu-exec-app The menu-exec-app action, combined with a param field, executes the specified application and passes the parameterslisted to that application. This is equivalent to using <action application="app" data="data"> in your Dialplan. The most common use of menu-exec-app is to transfer a caller to another extension in the Dialplan. Argument syntax: application <params> Examples: <entry digits="1" action="menu-exec-app" param="application param1 param2 param3 ..."> <entry digits="2" action="menu-exec-app" param="transfer 9664 XML default"> menu-exec-api The menu-exec-api action, combined with a param feld, executes the specifed API command and passes the parameters listed to that command. This is equivalent to entering API commands at the CLI or from the event socket. Argument syntax: api_command <params> Examples: <entry digits="1" action="menu-exec-api" param="eval Caller Pressed 1!"> menu-play-sound The menu-play-sound action, combined with a param field, plays a specified sound file. Argument syntax: valid sound file <entry digits="1" action="menu-play-sound" param="screaming_monkeys.wav"> menu-back The menu-back action returns to the previous IVR menu, if any. Argument syntax: none Examples: <entry digits="1" action="menu-back"> menu-top The menu-top action restarts this IVR's menu. Argument syntax: None. Examples: <entry digits="1" action="menu-top"> Take a look at the XML for the sample sub-menu IVR and see if you can fgure out what it does. Also note how it is called above, when clicking 6 from the main menu. <menu name="demo_ivr_submenu" greet-long="phrase:demo_ivr_sub_menu" greet-short="phrase:demo_ivr_sub_menu_short" invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav" exit-sound="voicemail/vm-goodbye.wav" timeout="15000" max-failures="3" max-timeouts="3"> <entry action="menu-top" digits="*"/> </menu>
Read more
  • 0
  • 0
  • 10276

article-image-freeswitch-106-sip-and-user-directory
Packt
05 Aug 2010
7 min read
Save for later

FreeSWITCH 1.0.6: SIP and the User Directory

Packt
05 Aug 2010
7 min read
(For more resources on Telephony, see here.) Understanding the FreeSWITCH user directory The FreeSWITCH user directory is based on a centralized XML document, comprised of one or more <domain> elements. Each <domain> can contain either <user> elements or <groups> elements. A <groups> element contains one or more <groups> elements, each of which contains one or more <user> elements. A small, simple example would look like the following: <section name="directory"> <domain name="example.com"> <groups> <group name="default"> <user id="1001"> <params> <param name="password" value="1234"/> </params> </user> </group> </groups> </domain></section> Some more basic configurations may not have a need to organize the users in groups so it is possible to omit the <groups> element completely, and just insert several <user> elements into the top <domain> element. The important thing is that each user@domain derived from this directory is available to all components in the system—it's a single centralized directory for storing all of your user information. If you register as a user with a SIP phone or if you try to leave a voicemail message for a user, FreeSWITCH looks in the same place for user data. This is important because it limits duplication of data, and makes it more efficient than it would be if each component kept track of its users separately. This system should work well for a small system with a few users in it, but what about a large system with thousands of users? What if a user wants to connect his existing database to FreeSWITCH to provide the user directory? Well, using mod_xml_curl (download here-ch:1,ch:3), we can create a web service that gets the request for the entries in the user directory, in the same way a web page sends the results of a form submission. In turn, that web service can query an existing database of users formatted any way possible, and construct the XML records in the format that FreeSWITCH registry expects. mod_xml_curl returns the data to the module requesting the lookup. This means that instant, seamless integration with your existing setup is possible; your data is still kept in its original, central location. The user directory can be accessed by any subsystem within FreeSWITCH. This includes modules, scripts, and the FSAPI interface among others. In this article, we are going to learn how the Sofia SIP module employs the user directory to authenticate your softphone or hardware SIP phone. If you are a developer you may appreciate some nifty things you can do with your user directory, such as adding a <variables> element to either the <domain>, the <groups>, or the <user> element. In this element you can set many <variable> elements, allowing you to set channel variables that will apply to every call made by a particular authenticated user. This can come in very handy in the Dialplan because it allows you to make user-specific routing decisions. It is also possible to define IP address ranges using CIDR notation, which can be used to authenticate particular users based on what remote network address they connect from. This removes the need for a login and password, if your user always logs in from the same remote IP address. The directory is implemented in pure XML. This is advantageous for several reasons, not the least of which is the "X" in XML: Extensible. Since XML is, by definition, extensible, the directory structure is also extensible. If we need to add a new element into the directory, we can do so simply by adding to the existing XML structure. Authentication versus authorizationAuthentication is the process of identifying a user. Authorization is the process of determining the level of access of a user. Authentication answers the question, "Is this person really who he says he is?" Authorization answers the question, "What is this person allowed to do here?" When you see expressions such as "IP Auth" and "Digest Auth", remember that they are referring to the two primary ways of identifying (that is, authenticating) a user. IP authorization is based upon the user's IP address. Digest authentication is based upon the user supplying a username and password. SIP (and FreeSWITCH) can use either method. Visit http://en.wikipedia.org/wiki/Digest_access_authentication for a discussion of how digest authentication works Working with the FreeSWITCH user directory The default configuration has one domain with a directory of 20 users. Users can be added or removed very easily. There is no set limit to how many users can be defined on the system. The list of users is collectively referred to as the directory. Users can belong to one or more groups. Finally, all the users belong to a single domain. By default, the domain is the IP address of the FreeSWITCH server. In the following sections we will discuss these topics: User features Adding a user Testing voicemail Groups of users User features Let's begin by looking at the XML file that defines a user. Locate the file conf/directory/default/1000.xml and open it in an editor. You should see a file like the following: <include> <user id="1000"> <params> <param name="password" value="$${default_password}"/> <param name="vm-password" value="1000"/> </params> <variables> <variable name="toll_allow" value="domestic,international,local"/> <variable name="accountcode" value="1000"/> <variable name="user_context" value="default"/> <variable name="effective_caller_id_name" value="Extension 1000"/> <variable name="effective_caller_id_number" value="1000"/> <variable name="outbound_caller_id_name" value="$${outbound_caller_name}"/> <variable name="outbound_caller_id_number" value="$${outbound_caller_id}"/> <variable name="callgroup" value="techsupport"/> </variables> </user></include> The XML structure of a user is simple. Within the <include> tags the user has the following: The user element with the id attribute The params element, wherein parameters are specified The variables element, wherein channel variables are defined Even before we know what much of the specifics mean, we can glean from this file that the user id is 1000 and that there is both a password and a vm-password. In this case, the password parameter refers to the SIP authorization password. The expression $${default_password} refers to the value contained in the global variable default_password which is defined in the conf/vars.xml file. If you surmised that vm-password means "voicemail password" then you are correct. This value refers to the digits that the user needs to dial when logging in to check his or her voicemail messages. The value of id is used both as the authorization username and the SIP username. Additionally, there are a number of channel variables that are defined for this user. Most of these are directly related to the default Dialplan. The following table lists each variable and what it is used for: Variable Purpose toll_allow Specifies which types of calls this user can make accountcode Arbitrary value that shows up in CDR data user_context The Dialplan context that is used when this person makes a phone call effective_caller_id_name Caller ID name displayed on called party's phone when calling another registered user effective_caller_id_number Caller ID number displayed on called party's phone when calling another registered user outbound_caller_id_name Caller ID name sent to provider on outbound calls outbound_caller_id_number Caller ID number sent to provider on outbound calls callgroup Arbitrary value that can be used in Dialplan or CDR In summary, a user in the default configuration has the following: A username for SIP and for authorization A voicemail password A means of allowing/restricting dialling A means of handling caller ID being sent out Several arbitrary variables that can be used or ignored as needed Let's now add a new user to our directory.
Read more
  • 0
  • 0
  • 5596

article-image-managing-voip-solution-active-directory-depends-your-needs
Packt
05 Aug 2010
3 min read
Save for later

Managing a VoIP Solution with Active Directory Depends On Your Needs

Packt
05 Aug 2010
3 min read
(For more resources on Telephony, see here.) Some smaller businesses might be able to get away with just using Skype. As a software client, Skype can be easily installed on individual computers. Since most workstations these days have a microphone built in to the monitor, a simple headset should suffice in getting up and running with Skype, along with a nominal fee per month to set up an account with privileges to call regular telephones. One problem with this method, however, is the way that Skype can hog your bandwidth. Skype is a peer-to-peer application that not only uses your system’s bandwidth in order to make phone calls; it also acts as a node for other phone calls across its own distributed network. Essentially, Skype also has the capability in its peer-to-peer system that can cause it to inadvertently hog bandwidth, which could cause your office to experience traffic problems. There are a series of useful Active Directory group policies you can enact to try to such as using ListenPortPolicy to try to lock down ports as well as using DisableApiPolicy to block bandwidth-eating third party APIs, but having to manage this system may be a bit too tumultuous, especially if you have a large amount of machines on your system. In a network that has larger scale, using Skype is probably not feasible. Technology titans such as Cisco and HP have systems complete with phones and special switches that can be easily implemented into a network; although this option requires a lot more upfront expense and time, if your system is at such a scale for such a service the long-term cost savings will be immense. Because IP phones are just like devices that use Organizational Units in Active Directory, you’ll be able to better place policies on them. You’ll inevitably have bandwidth issues using VoIP, but the difference between an application like Skype and IP telephone hardware is that you’re dealing with separate devices that disparately use bandwidth instead of trying to use group policies to manage software that is on a workstation. That means using your network performance management system to be able to control things like jitter and packet loss by placing a priority on your VoIP traffic. Bottom line: depending on the size of your network, you have options on leveraging VoIP and Active Directory for your infrastructure. Either way you look at it, you’ll be able to save cash on phone calls by switching to an IP-based solution. Further resources on this subject: Setting Up OpenVPN with X509 Certificates [Article] Installing OpenVPN on Linux and Unix Systems [Article] Networking with OpenVPN [Article] Installation of OpenSIPS 1.6 [Article] Configuring sipXecs Server Features [Article]
Read more
  • 0
  • 0
  • 6460
article-image-author-podcast-ronald-rood-discusses-birth-oracle-scheduler
Packt
05 Aug 2010
1 min read
Save for later

Author Podcast - Ronald Rood discusses the birth of Oracle Scheduler

Packt
05 Aug 2010
1 min read
You can listen to the podcast here, or hit play in the media player below.
Read more
  • 0
  • 0
  • 1174

article-image-using-spring-jmx-within-java-applications
Packt
04 Aug 2010
6 min read
Save for later

Using Spring JMX within Java Applications

Packt
04 Aug 2010
6 min read
(For more resources on Java, see here.) Yet for all its powerful capabilities, JMX is greatly underutilized and few developers seem to take advantage of its power. I attribute this underutilization to two factors: the scope of the Java universe as well as JMX's complex development model. As a deep and wide universe composed of a seemingly infinite number of tools, frameworks, design patterns and a never ending stream of new thoughts and ideas, I believe that JMX rarely finds itself on the list of the next technologies a developer plans to explore. While other shiny objects steal the Java community spotlight, the benefits of JMX patiently wait to be discovered and seem to largely be the playing field of only seasoned Java veterans who have had the time or industry longevity to have already encountered it. In regard to its complex development model, JMX itself has an extremely low level, clumsy, and obtrusive API and that has directly hindered its adoption. While this complex development model is a fact of JMX life, the Spring framework, as with numerous other aspects of Java development, offers excellent JMX support that greatly simplifies and radically reduces the learning curve and time investment required to incorporate JXM into your application. Spring's JMX support transforms JMX from an obscure API into what could become a central component of your application's architecture. While all of this sounds great, a tangible example of how easy it is to incorporate Spring JMX (and therefore JMX itself) into your application will make things more concrete. The following code and configuration sample presents a classic example of the benefits of JMX and is a piece of functionality which has proven its usefulness dozens upon dozens of times within my career: the ability to dynamically change an application's Log4j log level at runtime. Example 1: package com.spiegssoftware.common.util.management.logging; import org.apache.log4j.Category; import org.apache.log4j.Level; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.springframework.jmx.export.annotation.ManagedOperation; /** * MBean exposing Log4j management operations. * <p> * This code is based on an example provided from http://uri.jteam.nl/?p=4 . */ public class Log4jJmxService { /** Logger for this class. */ private final Logger logger = Logger.getLogger(Log4jJmxService.class); @ManagedOperation(description = "Set this Logger to the DEBUG level") public boolean activateDebug(final String category) { return adjustLogLevel(category, Level.DEBUG); } @ManagedOperation(description = "Set this Logger to the INFO level") public boolean activateInfo(final String category) { return adjustLogLevel(category, Level.INFO); } @ManagedOperation(description = "Set this Logger to the WARN level") public boolean activateWarn(final String category) { return adjustLogLevel(category, Level.WARN); } @ManagedOperation(description = "Set this Logger to the ERROR level") public boolean activateError(final String category) { return adjustLogLevel(category, Level.ERROR); } @ManagedOperation(description = "Set this Logger to the FATAL level") public boolean activateFatal(final String category) { return adjustLogLevel(category, Level.FATAL); } protected boolean adjustLogLevel(final String category, final Level level) { boolean result = false; Category cat = LogManager.exists(category); if (cat == null) { logger.error("Logger '" + category + "' does not exist"); } else { logger.info("Activating " + level + " for category: " + category); cat.setLevel(level); result = true; } return result; } }   Example 2: <?xml version="1.0" encoding="UTF-8"?> <beans xsi_schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <bean id="log4jJmxService" class="com.spiegssoftware.common.util.management.logging.Log4jJmxService" /> <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter"> <property name="beans"> <util:map id="beans"> <entry key="com.spiegssoftware.common.util.management.logging:name=Log4jJmxService" value="log4jJmxService"/> </util:map> </property> </bean> </beans>   Based on code publicly available from Dev Thoughts, the class in Example 1 was decorated with Spring JMX annotations and the necessary Spring configuration was created in Example 2. To incorporate this functionality into your application, you will need to include this class (along with Spring JMX's dependencies) and the configuration into your project, rebuild, and deploy. Before starting your application server, you may need to enable its support for JMX; see the documentation for your specific application server for details. After your application server has started with JMX support enabled, any JMX console, such as the jConsole tool that ships with all recent JDK's, can be used to connect to the JVM the application is running within and the application's logging level can be adjusted without requiring a restart. The details of how to use jConsole are best left to its documentation, but for the impatient, jConsole can by be launched by opening a command window and issuing a "jconsole" command just as you would issue a "java -version". From there, select which JVM you wish to connect to; most likely you will want to connect to a local process. After selecting the MBeans tab, use the left hand navigation and find the Log4jJmxService under the key name you registered it under within your Spring configuration file; in Example 2 we chose to use a value of "log4jJmxService". After selecting the Log4jJmxService from the jConsole tree navigation and drilling down, you are presented with a screen that represents all of the public methods available on the Log4jJmxService. Simply clicking the invoke button next to each available public method results in the specified method on the Log4jJmxService being invoked just as if the bean's method had been invoked through traditional application user input; the application is unaware and indifferent as to the source of the invocation request and the normal execution flow takes place. You now have the ability to dynamically change the log level of your application at runtime. This JMX stuff is great, hu? With your toe now in the JMX waters, you're undoubtedly thinking of the numerous ways JMX can be incorporated within your applications: to inspect or alter application configuration, to access statistical data held within an application memory, or to manage an application by invoking application logic – all at runtime! JMX's uses are limited only by your creativity to incorporate it. JMX is so powerful and exposing your Spring based components through Spring JMX is so easy and convenient that it's likely you'll quickly find yourself wanting to expose every Spring bean throughout your entire application. While the two configuration strategies provided by Spring JMX (annotating classes or configuring beans in XML) are suitable for configuring a relatively low number of beans, when applied on a large scale each strategy has the disadvantage that it becomes tedious, verbose, and is the epitome of boilerplate; few would dispute that very quickly either your code or configuration becomes cluttered with JMX metadata. Having previously fallen into this advantageous trap of wanting to expose all Spring beans within an application multiple times before myself, it was time to take a step back and determine if this could accomplished in a better way.
Read more
  • 0
  • 0
  • 3813

article-image-using-content-type-effectively-plone-intranet
Packt
04 Aug 2010
4 min read
Save for later

Using Content Type Effectively with Plone Intranet

Packt
04 Aug 2010
4 min read
(For more resources on Plone, see here.) Designing our intranet information architecture No one uses a knowledge system (such as our intranet) if the information stored in it is hard to find or consume. We will have to specially emphasize on thinking about not only a good navigation schema, but also a successful one for our intranet. The definition of success is different for every interested group, organization, enterprise, or any kind of entity our intranet will serve. There are a lot of navigation schemas we may want to implement, but it is our task to find out what will be more suitable for our organization. To achieve this, we will have to use both hierarchy and metadata taxonomy wisely. Obviously, the use of folders and collections will help achieve this endeavor. The first-level folders or sections are very important and we will have to keep an eye on them when designing our intranet. Also, we should not forget the next levels of folders, because they have a key role in a success navigation schema. The use of metadata, and specifically categorization of content, will also play an important role in our intranet. The continuous content cataloging is crucial to achieve a good content search and the users should be made aware of it. An intranet where the search of content is inefficient and difficult is an unsuccessful intranet, and with time, the users will abandon it. At this point, we should analyze the navigation needs of our intranet. Think about how the people will use it, how will they contribute contents to it, and how will they find things stored in it. In this analysis, it is very important to think about security. Navigation and security are closely related because most probably we define security by containers. There are some standard schemas: by organization structure, by process, by product, and so on. By organization is the most usual case. Everybody has a very clear idea of the organizational schema of an enterprise or organization, and this factor makes it easier to implement this type of schema. In this kind of schema, the first-level sections are divided into departments, teams, or main groups of interest. If our intranet is small and dedicated to one or few points of interest, then these must take precedence over the first level section folders. Keep the following things in mind: Our intranet will be more usable if we can keep our intranet sections clean and clear Fight against those people who believe that his (or her) department is more important than others and want to assault our intranet sections Let them know that maintaining a good intranet structure will be more useful and will help contribute to its success Second levels are also very important. They should be perdurable in time, interesting to users of all sections, and they should divide information and contents clearly. Two subsections shouldn't contain elements of the same subject or kind. For example, these might be a typical second level: Documentation Meetings Events News Forums, tracker, or some application specific to the current section All of these are very commonly seen in an intranet. It is a good practice to create these second-level sections in advance, so that people can adapt to them. Teach people to categorize content. This will help intranet searches incredibly and will help create collections and manage contents more effectively. If needed, make a well-known set of categories publicly available for people to use. This would prevent the repetition of categories and the rational use of them. Notice that there can be several types of categories: Subject: Terms that describe the subject of the content Process: Terms that identify the content with the organizational process Flags: Flags such as Strongly Recommended Products: Terms from the products, standards, and technology names that describe the subject matter of the resource Labels: Terms used to ensure that the resource is listed under the appropriate label Keywords: Terms used to describe the resource Events: Terms used to identify events which are recurrent with the content There are other metadata also which influence the improvement of the navigation and search abilities of the intranet such as: Title Description URL, the ID of each content Don't forget to teach your users about content contribution best practices before deploying the intranet. We and our intranet users will appreciate it a lot. Once we have settled down on some practices which are best for information architecture, we should know how to use some interesting Plone features that will help us build navigation and sort the information on our intranet.
Read more
  • 0
  • 0
  • 2946
article-image-article-agile-yii-php-creating-theme
Packt
04 Aug 2010
8 min read
Save for later

Agile with Yii 1.1 and PHP5: Creating themes

Packt
04 Aug 2010
8 min read
(For more resources on Agile, see here.) Building themes in Yii In Yii, each theme is represented as a folder consisting of view files, layout files, and relevant resource files such as images, CSS files, JavaScript files, and so on. The name of a theme is the same as its folder name. By default, all themes reside under the same folder WebRoot/themes. Of course, as is the case with all other application settings, this default folder can be configured to be a different one. To do so, simply alter the basePath and the baseUrl properties of the themeManager application component. Contents under a theme folder should be organized in the same way as those under the application base path. For example, all view files must be located under views/, layout view files under views/layouts/, and system view files under views/ system/. For example, if we have created a new theme, called custom, and we want to replace the update view of our ProjectController with a new view under this theme, we need to create a new update.php view file and save it in our application project as themes/custom/views/project/update.php. Creating a Yii theme Let's take this for a spin to give our TrackStar application a little facelift. We need to name our new theme and create a folder under the Webroot/themes folder with this same name. We'll exercise our extreme creativity and call our new theme, new. Create a new folder to hold this new theme located at Webroot/themes/new. Also under this newly created folder, create two other new folders called css/ and views/. The former is not required by the theming system, but helps us keep our CSS organized. The latter is required if we are going to make any alterations to our default view files, which we are. As we are going to change the main.php layout file just a little, we need yet another folder under this newly created views/ folder called layouts/ (remember the folder structure needs to mirror that in the default Webroot/protected/views/ folder). Now let's make some changes. As our view file markup is already referencing CSS class and ID names currently defined in the Webroot/css/main.css file, the fastest path to a new face on the application is to use this as a starting point, and make changes to it as needed to implement a new design. Of course, this is not a requirement, as we could re-create every single view file of our application in the new theme. However, to keep things simple, we'll create our new theme by making a few changes to the main.css file that was auto-generated for us when we created the application, as well as the primary layout file, main.php. To begin with, let's make a copy of these two files and place them in our new theme folder. Copy Webroot/css/main.css to Webroot/themes/new/css/main.css and also copy Webroot/protected/views/layouts/main.php to Webroot/themes/new/views/layouts/main.php. Now, open the newly copied version of the main.css file remove the contents and then add all of the following: body{ margin: 0; padding: 0; color: #555; font: normal 10pt Arial,Helvetica,sans-serif; background: #d6d6d6 url(background.gif) repeat-y center top;}#page{ margin-bottom: 20px; background: white; border: 1px solid #898989; border-top:none; border-bottom:none;}#header{ margin: 0; padding: 0; height:100px; background:white url(header.jpg) no-repeat left top; border-bottom: 1px solid #898989;}#content{ padding: 20px;}#sidebar{ padding: 20px 20px 20px 0;}#footer{ padding: 10px; margin: 10px 20px; font-size: 0.8em; text-align: center; border-top: 1px solid #C9E0ED;}#logo{ padding: 10px 20px; font-size: 200%; /* HIDES LOGO TEXT */ text-indent:-5000px;}#mainmenu{ background:white url(bg2.gif) repeat-x left top; border-top:1px solid #CCC; border-bottom: 1px solid #7d7d7d;}#mainmenu ul{ padding:6px 20px 5px 20px; margin:0px;}#mainmenu ul li{ display: inline;}#mainmenu ul li a{ color:#333; background-color:transparent; font-size:12px; font-weight:bold; text-decoration:none; padding:5px 8px;}#mainmenu ul li a:hover, #mainmenu ul li a.active{ color: #d11e1e; background-color:#ccc; text-decoration:none;}div.flash-error, div.flash-notice, div.flash-success{ padding:.8em; margin-bottom:1em; border:2px solid #ddd;}div.flash-error{ background:#FBE3E4; color:#8a1f11; border-color:#FBC2C4;}div.flash-notice{ background:#FFF6BF; color:#514721; border-color:#FFD324;}div.flash-success{ background:#E6EFC2; color:#264409; border-color:#C6D880;}div.flash-error a{ color:#8a1f11;}div.flash-notice a{ color:#514721;}div.flash-success a{ color:#264409;}div.form .rememberMe label{ display: inline;}div.view{ padding: 10px; margin: 10px 0; border: 1px solid #C9E0ED;}div.breadcrumbs{ font-size: 0.9em; padding: 10px 20px;}div.breadcrumbs span{ font-weight: bold;}div.search-form{ padding: 10px; margin: 10px 0; background: #eee;}.portlet{}.portlet-decoration{ padding: 3px 8px; background:white url(bg2.gif) repeat-x left top;}.portlet-title{ font-size: 12px; font-weight: bold; padding: 0; margin: 0; color: #fff;}.portlet-content{ font-size:0.9em; margin: 0 0 15px 0; padding: 5px 8px; background:#ccc;}.operations li a{ font: bold 12px Arial; color: #d11e1e; display: block; padding: 2px 0 2px 8px; line-height: 15px; text-decoration: none;}.portlet-content ul{ list-style-image:none; list-style-position:outside; list-style-type:none; margin: 0; padding: 0;}.portlet-content li{ padding: 2px 0 4px 0px;}.operations{ list-style-type: none; margin: 0; padding: 0;}.operations li{ padding-bottom: 2px;}.operations li a{ font: bold 12px Arial; color: #0066A4; display: block; padding: 2px 0 2px 8px; line-height: 15px; text-decoration: none;}.operations li a:visited{ color: #d11e1e;}.operations li a:hover{ background: #fff;} You may have noticed that some of these changes are referencing image files that do not yet exist in our project. We have added a background.gif image reference in the body declaration, a new bg2.gif image referenced in the #mainmenu ID declaration and a new header.jpg image in the #header ID declaration. These can be viewed, downloaded and used by viewing the site online or accessing the images directly from http://www.yippyii.com/trackstar/themes/new/css/background.gif, http://www.yippyii.com/trackstar/themes/new/css/bg2.gif, and http://www.yippyii.com/trackstar/themes/new/css/header.jpg. We need to place these new images into the same CSS folder we are using for this theme, namely Webroot/themes/new/css/. After these changes are in place, we need to make a couple of small adjustments to our main.php layout file in this new theme. For one, we need to alter the markup in the <head> element to properly reference our new main.css file. Currently the main.css file is being pulled in via this line: <link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/main.css" /> This is referencing the application request baseUrl property to construct the relative path to the CSS file. However, we want to use our new main.css file located in our new theme. For this, we can lean on the theme manager application component, defined by default to use the Yii built-in CThemeManager.php class. We access the theme manager in the same way as we access other application components. So, rather than use the request base URL, we should use the one defined by the theme manager, which knows what theme the application is using at any given time. So, we need to alter the above line in /themes/new/views/layouts/main.php as follows: <link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->theme->baseUrl; ?>/css/main.css" /> Once we configure our application to use our new theme (something we have not yet done), this baseUrl will resolve to a relative path to where our theme folder resides. The other small change we need to make is to remove the display of the application title from the header. As we altered our CSS to use a new image file to provide our header and logo information, we don't need to display the application name in this section. So, again in /themes/new/views/layouts/main.php, we simply need to change this: <div id="header"><div id="logo"><?php echo CHtml::encode(Yii::app()->name); ?></div></div><!-- header --> To the following: <div id="header"></div><!-- header image is embeded into the #headerdeclaration in main.css --> We have put in a comment to remind us where our header image is defined. One final change we need to make is to the other two layout files used in the application that we are not copying over to our new theme folder, namely protected/views/layouts/column1.php and protected/views/layouts/column2.php. These two layout files also use the main layout file via explicit calls to the beginContent() and endContent(). These files were auto-generated by the Gii code generation tool, and are explicitly referencing the main layout file in protected/views/layouts/ folder. We need to change the input specified to the beginContent() method so that, if available, our new theme layout will be used. Open both the column1.php and column2.php files and change the following line of code: $this->beginContent('application.views.layouts.main'); To be the following: $this->beginContent('/layouts/main'); Now, once we configure the application to use our new theme, it will first look for a main.php layout in the themes folder and use that file.
Read more
  • 0
  • 0
  • 1626

article-image-interacting-data-sharepoint-server
Packt
02 Aug 2010
10 min read
Save for later

Interacting with Data on the SharePoint Server

Packt
02 Aug 2010
10 min read
Managing data in a Silverlight RIA included in a SharePoint solution So far, we have been able to create, deploy, and debug a Silverlight RIA that read data from a list in the SharePoint server. It is also possible to insert, update, and remove items from these lists. In fact, the typical LOB (Line-Of-Business) RIA performs CRUD (Create, Read, Update, and Delete) operations. Therefore, we can create a Silverlight RIA to perform some of the CRUD operations with the existing list of tasks, by using more features provided by the SharePoint 2010 Silverlight Client OM. We could improve our existing Silverlight RIA that displays data from the existing list in a grid. However, we are going to create a new Silverlight RIA and then, we will improve both applications to work together to offer a complex LOB solution. We will analyze diverse alternatives to simplify the deployment process and show how to debug a Silverlight RIA that queries data from a SharePoint server. Working with the SharePoint 2010 Silverlight Client Object Model to insert items Now, we are going to create a new solution in Visual Studio. It will include two new projects: A Silverlight application project, SLTasksCRUD An empty SharePoint 2010 project with a module, SPTasksCRUD Follow these steps to create the new Silverlight RIA that allows a user to insert a new item into the list in the SharePoint server: This example requires the ProjectsList2010 list created in SharePoint Start Visual Studio as a system administrator user. Select File New | Project...| or press Ctrl+Shift+N. Select Other Project Types Visual Studio Solutions under Installed Templates in the New Project dialog box. Then, select Blank Solution and enter TasksCRUD as the project's name and click OK. Visual Studio will create a blank solution with no projects. Right-click on the solution's name in Solution Explorer and select Add New Project from the context menu that appears. Select Visual C# Silverlight under Installed Templates in the New Project dialog box. Then, select Silverlight Application, enter SLTasksCRUD as the project's name and click OK. Deactivate the Host the Silverlight application in a new Web site checkbox in the New Silverlight Application dialog box and select Silverlight 4 in Silverlight Version. Then, click OK. Visual Studio will add the new Silverlight application project to the existing solution. Follow the necessary steps to add the following two references to access the new SharePoint 2010 Silverlight Client OM: Microsoft.SharePoint.Client.Silverlight.dll Microsoft.SharePoint.Client.Silverlight.Runtime.dll Open App.xaml.cs and add the following using statement: using Microsoft.SharePoint.Client; Add the following code in the StartUp event handler to initialize the Microsoft.SharePoint.Client.ApplicationContext with the same initialization parameters and the synchronization context for the current thread (the UI thread). private void Application_Startup(object sender, StartupEventArgs e){ this.RootVisual = new MainPage(); // Initialize the ApplicationContext ApplicationContext.Init(e.InitParams, System.Threading.SynchronizationContext.Current);} Open MainPage.xaml, define a new width and height for the Grid, 800 and 600, add the following controls, and align them as shown in the following screenshot: Six Label controls aligned at the left with the following values for their Content properties. They are Title, Priority, Status, % Complete, Start Date and Due Date. One Label control, located at the bottom, lblStatus. One TextBox control, txtTitle. One ComboBox control, cboPriority. One ComboBox control, cboStatus. One Slider control, sldPercentComplete. Set LargeChange to 10, Maximum to 100, and Minimum to 0. This slider will allow the user to set the percentage of the total work that has been completed. One DatePicker control, dtStartDate. One DatePicker control, dtDueDate. One Button control, butInsert. Set its Title property to Insert Select the Grid, LayoutRoot. Click on the Categorized button to arrange the properties by category. Then, click on Brushes Background| and a color palette with many buttons located at the top and the bottom will appear. Click on the Gradient Brush button, located at the top and then on the Vertical Gradient one, located at the bottom. Define both the start and the stop colors. The rectangle that defines the background Grid will display a nice linear gradient, as shown in the previous screenshot. Open MainPage.xaml.cs and add the following using statements to include the Microsoft.SharePoint.Client namespace: using Microsoft.SharePoint.Client;using SP = Microsoft.SharePoint.Client;Add the following two private variablesprivate SP.ClientContext _context;private SP.List _projects; Add the following method to fill the drop-down lists that will display the different options for the priority and the status: private void FillComboBoxes(){ cboPriority.Items.Add("(1) High"); cboPriority.Items.Add("(2) Normal"); cboPriority.Items.Add("(3) Low"); cboStatus.Items.Add("Not Started"); cboStatus.Items.Add("In Progress"); cboStatus.Items.Add("Completed"); cboStatus.Items.Add("Deferred"); cboStatus.Items.Add("Waiting on someone else");} It is possible to retrieve the possible choices for both the Priority and Status fields.In this case, we add the possible values in this method and then we will learn how to retrieve the choices through queries to the SharePoint server. Add the following line to the page MainPage constructor: public MainPage(){ InitializeComponent(); FillComboBoxes();} Now, it is necessary to add code to execute the following tasks: Connect to the SharePoint server and load the current user that logged on the server, ConnectAndAddItemToList method. Add a new item to the ProjectsList2010 list, considering the values entered by the user in the controls, AddItemToList method. private void ConnectAndAddItemToList(){ // Runs in the UI Thread lblStatus.Content = "Started"; _context = new SP.ClientContext(SP.ApplicationContext.Current.Url); _context.Load(_context.Web); // Load the current user _context.Load(_context.Web.CurrentUser); _context.ExecuteQueryAsync(OnConnectSucceeded, null);}private void AddItemToList(){ // Runs in the UI Thread lblStatus.Content = "Web Connected. Adding new item to List..."; _projects = _context.Web.Lists.GetByTitle("ProjectsList2010"); ListItem listItem = _projects.AddItem(new ListItemCreationInformation()); listItem["Title"] = txtTitle.Text; listItem["StartDate"] = Convert.ToString(dtStartDate.SelectedDate); listItem["DueDate"] = Convert.ToString(dtDueDate.SelectedDate); listItem["Status"] = "Not Started"; var fieldUserValue = new FieldUserValue(); // Assign the current user to the Id fieldUserValue.LookupId = _context.Web.CurrentUser.Id; listItem["AssignedTo"] = fieldUserValue; listItem["Priority"] = "(2) Normal"; listItem["PercentComplete"] = Convert.ToString(Math.Round(sldPercentComplete.Value, 0)/100); listItem.Update(); // Just load the list Title proprty _context.Load(_projects, list => list.Title); _context.ExecuteQueryAsync(OnAddItemToListSucceeded, OnAddItemToListFailed);} All the previously added methods are going to run in the UI thread. The following methods, which are going to be fired as asynchronous callbacks, schedule the execution of other methods to continue with the necessary program flow in the UI thread: When the connection to the SharePoint server, requested by the ConnectAndAddItemToList method, is successful, the OnConnectSucceeded method schedules the execution of the AddItemToList method in the UI thread. If the ConnectAndAddItemToList method fails, the OnConnectFailed method schedules the execution of the ShowErrorInformation method in the UI thread, sending the ClientRequestFailedEventArgs args instance as a parameter to the delegate. When the insert operation performed on the list available in the SharePoint server, requested by the AddItemToList method, is successful, the OnAddItemToListSucceeded method schedules the execution of the ShowInsertResult method in the UI thread. If the AddItemToList method fails, the OnAddItemToList method schedules the execution of the ShowErrorInformation method in the UI thread, sending the ClientRequestFailedEventArgs args instance as a parameter to the delegate. private void ShowErrorInformation(ClientRequestFailedEventArgsargs){ System.Windows.Browser.HtmlPage.Window.Alert( "Request failed. " + args.Message + "n" + args.StackTrace + "n" + args.ErrorDetails + "n" + args.ErrorValue);}private void ShowInsertResult(){ lblStatus.Content = "New item added to " + _projects.Title;}private void OnConnectSucceeded(Object sender, SP.ClientRequestSucceededEventArgs args){ // This callback isn't called on the UI thread Dispatcher.BeginInvoke(AddItemToList);}private void OnConnectFailed(object sender,ClientRequestFailedEventArgs args){ // This callback isn't called on the UI thread // Invoke a delegate and send the args instance as a parameter Dispatcher.BeginInvoke(() => ShowErrorInformation(args));}private void OnAddItemToListSucceeded(Object sender, SP.ClientRequestSucceededEventArgs args){ // This callback isn't called on the UI thread //Dispatcher.BeginInvoke(GetListData); Dispatcher.BeginInvoke(ShowInsertResult);}private void OnAddItemToListFailed(object sender,ClientRequestFailedEventArgs args){ // This callback isn't called on the UI thread // Invoke a delegate and send the args instance as a parameter Dispatcher.BeginInvoke(() => ShowErrorInformation(args));} Add the following line to the Click event for the butInsert Button. This way, when the user clicks on this button, the application will connect to the SharePoint server and will insert the new item. private void butInsert_Click(object sender, RoutedEventArgs e){ ConnectAndAddItemToList();} Now, follow these steps to create a new SharePoint module and link it to the previously created Silverlight RIA, SLTasksCRUD. Stay in Visual Studio as a system administrator user. Right-click on the solution's name in Solution Explorer and select Add | New Project… from the context menu that appears. Select Visual C# SharePoint | 2010| under Installed Templates in the New Project dialog box. Then, select Empty SharePoint Project, enter SPTasksCRUD as the project's name, and click OK. The SharePoint Customization Wizard dialog box will appear. Enter the URL for the SharePoint server and site in What local site do you want to use for debugging? Click on Deploy as a sandboxed solution. Then, click on Finish and the new SPTasksCRUD empty SharePoint 2010 project will be added to the solution. Add a new item to the project, that is a SharePoint 2010 module, Module1. Expand the new SharePoint 2010 module, Module1, in the Solution Explorer and delete the Sample.txt file. Now, right-click on Module1 and select Properties in the context menu that appears. In the Properties palette, click the ellipsis (...) button for the Project Output References property. The Project Output References dialog box will appear. Click on Add, below the Members list. The empty SharePoint 2010 project's name, SPTasksCRUD, will appear as a new member. Go to its properties, shown in the list, located at the right. Select the Silverlight application project's name, SLTasksCRUD, in the Project Name drop-down list. Select ElementFile in the Deployment Type drop-down list. The following value will appear in Deployment Location: {SharePointRoot}TemplateFeatures{FeatureName}Module1, as shown in the next screenshot: Click OK and the SharePoint project now includes the Silverlight application project, SLTasksCRUD. Now, right-click on the SharePoint 2010 project, SPTasksCRUD, and select Properties in the context menu that appears. Click on the SharePoint tab in the properties panel and different options for the SharePoint deployment configuration will be shown. Activate the Enable Silverlight debugging (instead of Script debugging) checkbox. Remember that this option will allow us to debug code in the Silverlight application that adds items to the list in the SharePoint server. Right-click on the solution's name in Solution Explorer and select Properties from the context menu that appears. Select Startup Project in the list on the left, activate Single startup project, and choose the SharePoint project's name in the drop-down list below it, SPTasksCRUD. Then, click OK. Build and deploy the solution. Now that the WSP package has been deployed to the SharePoint site, follow the necessary steps to create a new web page, add the Silverlight Web Part, and include the Silverlight RIA in it. Remember that in this case, it is not necessary to upload the .xap file because it was already deployed with the WSP package.
Read more
  • 0
  • 0
  • 1593
Modal Close icon
Modal Close icon