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

How-To Tutorials

7019 Articles
article-image-controlling-which-class-sees-our-resources-moodle-19
Packt
18 Nov 2009
4 min read
Save for later

Controlling Which Class Sees Our Resources in Moodle 1.9

Packt
18 Nov 2009
4 min read
While for the most part, teachers on the same course would want to cover the same material, it can sometimes be the case that one teacher might only want their own class to see a particular item but keep it hidden from others. I myself am doing this currently on a Certificate course whereby the students who have finished are able to view some extension activities that other students still working on the qualification do not have access to. Hiding resources from some students and showing them to others can be done by using "groupings" in Moodle. Groupings – a way to hide resources from some and display to others In order for this to work we need to check certain features: We are using Moodle 1.9. Groups and groupings have been enabled by our Moodle admin (in Site Admin > Experimental as below). We have the students on our Moodle course set up in different teacher groups. Ok – let us assume, we want group French 1 only to see our forum and wiki and we want group French 2 only to see our assignment. If we click on groups in the course administration block we see: If we look to the top of the Groups screen we see three tabs. The one to select next is Groupings. Having clicked on it, we get presented with a screen asking us to create a new grouping. A grouping is like an invisibility cloak (think: Harry Potter!) whereby any people in the grouping can be made invisible to others on the course. If we click on Create grouping we are then asked to give a name (and optional description) for our grouping. Note that we have not yet added any people to the grouping; we are merely setting it up. Once we have scrolled down and saved the changes we are returned to the above screen where we see the grouping has been created – but it has no people and it has no activities assigned to it: The next action to take is to click on the people icon in the Edit box. This sends us to a screen where we can choose which groups to put into this grouping "invisibility cloak": By clicking on a group on the right and moving it across with the arrow to the left we can assign a group to a grouping. You cannot assign individuals to a grouping; you can only assign groups. However –there is nothing preventing you making a group of one single person and then assigning that group! You can also have more than one group in a grouping, should you wish to. We now have our group French 1 in a grouping. The next step is to repeat the process for the group French 2. When that is done, it is important to check in the course settings (in the course admin block) that groups and groupings are enabled. Finally, we go to the activities we have set up – in this instance, a forum, wiki and assignment. We need to assign the tasks to the appropriate groupings. If the tasks have already been set up, as here, we click on the pen/hand icon to go into the editing area. If we are setting them up from scratch we assign the grouping at the time of creation. Scroll down to the section Common Module Settings and choose the appropriate grouping for that task, also checking Available for group members only: The same process must be gone through with the other tasks we want to control access to (in this instance, the wiki and assignment). And then – it’s done! If we the teacher look at the course we see that each activity has the name of the grouping greyed out next to it: Summary A student in one of those groupings, however, would only see their own activities and have no idea the others existed! A simple but effective way to control access to your Moodle tasks on a shared course. If you have read this article you may be interested to view : Setting up your Moodle Grade Book Adding Worksheets and Resources with Moodle Interacting with the Students using Moodle 1.9 (part 1)
Read more
  • 0
  • 0
  • 1505

article-image-create-quick-application-cakephp-part-2
Packt
18 Nov 2009
7 min read
Save for later

Create a Quick Application in CakePHP: Part 2

Packt
18 Nov 2009
7 min read
Editing a Task Now that we can add tasks to CakeTooDoo, the next thing that we will be doing is to have the ability to edit tasks. This is necessary because the users should be able to tick on a task when it has been completed. Also, if the users are not happy with the title of the task, they can change it. To have these features in CakeTooDoo, we will need to add another action to our Tasks Controller and also add a view for this action. Time for Action: Creating the Edit Task Form Open the file tasks_controller.php and add a new action named edit as shown in the following code: function edit($id = null) { if (!$id) { $this->Session->setFlash('Invalid Task'); $this->redirect(array('action'=>'index'), null, true); } if (empty($this->data)) { $this->data = $this->Task->find(array('id' => $id)); } else { if ($this->Task->save($this->data)) { $this->Session->setFlash('The Task has been saved'); $this->redirect(array('action'=>'index'), null, true); } else { $this->Session->setFlash('The Task could not be saved. Please, try again.'); } } } Inside the directory /CakeTooDoo/app/views/tasks, create a new file named edit.ctp and add the following code to it: <?php echo $form->create('Task');?> <fieldset> <legend>Edit Task</legend> <?php echo $form->hidden('id'); echo $form->input('title'); echo $form->input('done'); ?> </fieldset> <?php echo $form->end('Save');?> We will be accessing the Task Edit Form from the List All Task page. So, let's add a link from the List All Tasks page to the Edit Task page. Open the index.ctp file in /CakeTooDoo/app/views directory, and replace the HTML comment <!-- different actions on tasks will be added here later --> with the following code: <?php echo $html->link('Edit', array('action'=>'edit', $task['Task']['id'])); ?> Now open the List All Tasks page in the browser by pointing it to http://localhost/CakeTooDoo/tasks/index and we will see an edit link beside all the tasks. Click on the edit link of the task you want to edit, and this will take you to do the Edit Task form, as shown below: Now let us add links in the Edit Task Form page to the List All Tasks and Add New Task page. Add the following code to the end of edit.ctp in /CakeTooDoo/app/views: <?php echo $html->link('List All Tasks', array('action'=>'index')); ?><br /> <?php echo $html->link('Add Task', array('action'=>'add')); ?> What Just Happened? We added a new action named edit in the Tasks controller. Then we went on to add the view file edit.ctp for this action. Lastly, we linked the other pages to the Edit Task page using the HTML helper. When accessing this page, we need to tell the action which task we are interested to edit. This is done by passing the task id in the URL. So, if we want to edit the task with the id of 2, we need to point our browser to http://localhost/CakeTooDoo/tasks/edit/2. When such a request is made, Cake forwards this request to the Tasks controller's edit action, and passes the value of the id to the first parameter of the edit action. If we check the edit action, we will notice that it accepts a parameter named $id. The task id passed in the URL is stored in this parameter. When a request is made to the edit action, the first thing that it does is to check if any id has been supplied or not. To let users edit a task, it needs to know which task the user wants to edit. It cannot continue if there is no id supplied. So, if $id is undefined, it stores an error message to the session and redirects to the index action that will show the list of current tasks along with the error message. If $id is defined, the edit action then checks whether there is any data stored in $this->data. If no data is stored in $this->data, it means that the user has not yet edited. And so, the desired task is fetched from the Task model, and stored in $this->data in the line: $this->data = $this->Task->find(array('id' => $id)); Once that is done, the view of the edit action is then rendered, displaying the task information. The view fetches the task information to be displayed from $this->data. The view of the edit action is very similar to that of the add action with a single difference. It has an extra line with echo $form->hidden('id');. This creates an HTML hidden input with the value of the task id that is being edited. Once the user edits the task and clicks on the Save button, the edited data is resent to the edit action and saved in $this->data. Having data in $this->data confirms that the user has edited and submitted the changed data. Thus, if $this->data is not empty, the edit action then tries to save the data by calling the Task Model's save() function: $this->Task->save($this->data). This is the same function that we used to add a new task in the add action. You may ask how does the save() function of model knows when to add a new record and when to edit an existing one? If the form data has a hidden id field, the function knows that it needs to edit an existing record with that id. If no id field is found, the function adds a new record. Once the data has been successfully updated, a success message is stored in the session and it redirects to the index action. Of course the index page will show the success message. Adding Data Validation If you have come this far, by now you should have a working CakeTooDoo. It has the ability to add a task, list all the tasks with their statuses, and edit a task to change its status and title. But, we are still not happy with it. We want the CakeTooDoo to be a quality application, and making a quality application with CakePHP is as easy as eating a cake. A very important aspect of any web application (or software in general), is to make sure that the users do not enter inputs that are invalid. For example, suppose a user mistakenly adds a task with an empty title, this is not desirable because without a title we cannot identify a task. We would want our application to check whether the user enters title. If they do not enter a title, CakeTooDoo should not allow the user to add or edit a task, and should show the user a message stating the problem. Adding these checks is what we call Data Validation. No matter how big or small our applications are, it is very important that we have proper data validation in place. But adding data validation can be a painful and time consuming task. This is especially true, if we have a complex application with lots of forms. Thankfully, CakePHP comes with a built-in data validation feature that can really make our lives much easier. Time for Action: Adding Data Validation to Check for Empty Title In the Task model that we created in /CakeTooDoo/app/models, add the following code inside the Task Model class. The Task Model will look like this: <?php class Task extends AppModel { var $name = 'Task'; var $validate = array( 'title' => array( 'rule' => VALID_NOT_EMPTY, 'message' => 'Title of a task cannot be empty' ) ); } ?> Now open the Add Task form in the browser by pointing it to http://localhost/CakeTooDoo/tasks/add, and try to add a task with an empty title. It will show the following error message:
Read more
  • 0
  • 0
  • 2328

article-image-applying-special-effects-3d-game-development-microsoft-silverlight-3-part-1
Packt
18 Nov 2009
7 min read
Save for later

Applying Special Effects in 3D Game Development with Microsoft Silverlight 3: Part 1

Packt
18 Nov 2009
7 min read
  A 3D game must be attractive. It has to offer amazing effects for the main characters and in the background. A spaceship has to fly through a meteor shower. An asteroid belt has to draw waves while a UFO pursues a spaceship. A missile should make a plane explode. The real world shows us things moving everywhere. Most of these scenes, however, aren't repetitive sequences. Hence, we have to combine great designs, artificial intelligence (AI), and advanced physics to create special effects. Working with 3D characters in the background So far, we have added physics, collision detection capabilities, life, and action to our 3D scenes. We were able to simulate real-life effects for the collision of two 3D characters by adding some artificial intelligence. However, we need to combine this action with additional effects to create a realistic 3D world. Players want to move the camera while playing so that they can watch amazing effects. They want to be part of each 3D scene as if it were a real life situation. How can we create complex and realistic backgrounds capable of adding realistic behavior to the game? We can do this combining everything we have learned so far with a good object-oriented design. We have to create random situations combined with more advanced physics. We have to add more 3D characters with movement to the scenes. We must add complexity to the backgrounds. We can work with many independent physics engines to work with parallel worlds. In real-life, there are concurrent and parallel words. We have to reproduce this behavior in our 3D scenes. Time for action – adding a transition to start the game Your project manager does not want the game to start immediately. He wants you to add a butt on in order to allow the player to start the game by clicking on it. As you are using Balder, adding a butt on is not as simple as expected. We are going to add a butt on to the main page, and we are going to change Balder's default game initialization: Stay in the 3DInvadersSilverlight project. Expand App.xaml in the Solution Explorer and open App.xaml.cs––the C# code for App.xaml. Comment the following line of code (we are not going to use Balder's services in this class):  //using Balder.Silverlight.Services; Comment the following line of code in the event handler for the Application_Startup event, after the line this.RootVisual = new MainPage();: //TargetDevice.Initialize<InvadersGame>(); Open the XAML code for MainPage.xaml and add the following lines of code after the line (You will see a butt on with the ti tle Start the game.): <!-- A button to start the game --><Button x_Name="btnStartGame" Content="Start the game!" Canvas.Left="200" Canvas.Top="20" Width="200" Height="30" Click="btnStartGame_Click"></Button> Now, expand MainPage.xaml in the Solution Explorer and open MainPage.xaml.cs––the C# code for MainPage.xaml. Add the following line of code at the beginning (As we are going to use many of Balder's classes and interfaces.): using Balder.Silverlight.Services; Add the following lines of code to program the event handler for the button's Click event (this code will initialize the game using Balder's services): private void btnStartGame_Click(object sender, RoutedEventArgs e){ btnStartGame.Visibility = Visibility.Collapsed; TargetDevice.Initialize<InvadersGame>();} Build and run the solution. Click on the Start the game! butt on and the UFOs will begin their chase game. The butt on will make a transition to start the game, as shown in the following screenshots:   What just happened? You could use a Start the game! butt on to start a game using Balder's services. Now, you will be able to offer the player more control over some parameters before starting the game. We commented the code that started the game during the application start-up. Then, we added a button on the main page (MainPage). The code programmed in its Click event handler initializes the desired Balder.Core.Game subclass (InvadersGame) using just one line: TargetDevice.Initialize<InvadersGame>(); This initialization adds a new specific Canvas as another layout root's child, controlled by Balder to render the 3D scenes. Thus, we had to make some changes to add a simple butt on to control this initialization. Time for action – creating a low polygon count meteor model The 3D digital artists are creating models for many aliens. They do not have the time to create simple models. Hence, they teach you to use Blender and 3D Studio Max to create simple models with low polygon count. Your project manager wants you to add dozens of meteors, to the existing chase game. A gravitational force must attract these meteors and they have to appear in random initial positions in the 3D world. First, we are going to create a low polygon count meteor using 3D Studio Max. Then, we are going to add a texture based on a PNG image and export the 3D model to the ASE format, compatible with Balder. As previously explained, we have to do this in order to export the ASE format with a bitmap texture definition enveloping the meshes. We can also use Blender or any other 3D DCC tool to create this model. We have already learned how to export an ASE format from Blender. Thus, this time, we are going to learn the necessary steps to do it using 3D Studio Max. Start 3D Studio Max and create a new scene. Add a sphere with six segments. Locate the sphere in the scene's center. Use the Uniform Scale tool to resize the low polygon count sphere to 11.329 in the three axis, as shown in the following screenshot: Click on the Material Editor button. Click on the first material sphere, on the Material Editor window's upper-left corner. Click on the small square at the right side of the Diffuse color rectangle, as shown in the following screenshot: Select Bitmap from the list shown in the Material/Map Browser window that pops up and click on OK. Select the PNG file to be used as a texture to envelope the sphere. You can use Bricks.PNG, previously downloaded from http://www.freefoto.com/. You just need to add a reference to a bitmap file. Then, click on Open. The Material Editor preview panel will show a small sphere thumbnail enveloped by the selected bitmap, as shown in the following screenshot: Drag the new material and drop it on the sphere. If you are facing problems, remember that the 3D digital artist created a similar sphere a few days ago and he left the meteor.max file in the following folder (C:Silverlight3DInvaders3D3DModelsMETEOR). Save the file using the name meteor.max in the previously mentioned folder. Now, you have to export the model to the ASE format with the reference to the texture. Therefore, select File | Export and choose ASCII Scene Export (*.ASE) on the Type combo box. Select the aforementioned folder, enter the file name meteor.ase and click on Save. Check the following options in the ASCII Export dialog box. (They are unchecked by default): Mesh Normals Mapping Coordinates Vertex Colors The dialog box should be similar to the one shown in the following screenshot: Click on OK. Now, the model is available as an ASE 3D model with reference to the texture. You will have to change the absolute path for the bitmap that defines the texture in order to allow Balder to load the model in a Silverlight application.
Read more
  • 0
  • 0
  • 2844

article-image-formatting-and-enhancing-your-moodle-materials-part-1
Packt
18 Nov 2009
7 min read
Save for later

Formatting and Enhancing Your Moodle Materials: Part 1

Packt
18 Nov 2009
7 min read
There are three main types of Moodle pages to consider when it comes to design: Moodle front pages Moodle course pages Moodle activities Before we go into detail about design considerations, let's look at examples of each of these to see how we can improve them with a few basic steps. Moodle front page If we take Moodle straight out of the box, set up some blocks for the main menu, provide some useful links, and set the front page settings to show a list of courses, we could have something like this: BEFORE It's functional enough, but not very engaging. Just by making a few changes, we can make the front page much more interesting and readable: AFTER What's changed? There's a new theme (Moodle speak for the color scheme and automatic font choices). As we'll see in a bit, some themes also include tabs and drop-down menus. There's an appropriate image in the top-center of the screen to draw users in. The About this site block has a photo of the administrator, which provides a personal touch. There's an easily-identifiable "start here icon"—another helpful feature that guides your users in the right direction. Moodle course page Like the Moodle front page, a standard course page automatically creates three columns for us to fill with text. If we choose a topics format from the Settings menu and write out a list of activities and links for our course, it could look something like this: BEFORE The problem here is that it's difficult to distinguish important information from unimportant information. There's a lot of scrolling to be done, and there are no visual clues as to what the course page is about. Here's one way of transforming the page: AFTER What's changed? There's a new theme. The theme includes tabs with links to key parts of the site. There's an image related to the course topic (teaching) at the top of the course page. The long list in the previous version has been reduced to a more manageable size. Important information is at the top of the page, and is in a larger font size. It contrasts with less important information, which has a smaller font size. Lines are used to separate different sorts of information. There is more color harmony—at attempt to get the colors to blend. There's an avatar introduction in the left block for new users. Moodle activity When we're pushed for time, it's all too tempting just to set out a list of references without paying due attention to instructions and a helpful hierarchy of information, as in the following example: BEFORE There's a lot of information here. We can use the Book module to organize the information, and make the page more readable, as in the following transformation: AFTER What's changed? The previous list has been divided into sections in the Book module There's a "how-to" section at the beginning of the Table of Contents Graphics from the target websites have been included as visual clues The Tool labels such as Audacity and Findsounds are in a larger font size to make them stand out An action girl icon indicates task instructions Task instructions are in bold blue to make them stand out A grid is used to separate sections As we can see, by enhancing the visual design of our sites we can make our materials more engaging and effective. We can also make them more attractive by improving the quality of the audio, images, and video that we use. Here are some principles we could take on board: Contrast Consider hierarchies of importance in your materials. The default font size on HTML pages is 12 points, similar to what you're reading now. Vary the size to make more important information stand out. You can also use images, buttons, and navigation signs to help users see the function of pages and content more quickly and remember it. Consistency Being consistent in your use of fonts for certain sorts of information, font sizes for ranking information, and navigation links will make it easier for users to understand the site and will make it more aesthetically pleasing. It's also better not to use too many different fonts or make your site too fancy or you will end up with a dog's breakfast. As a rule, it'll look better if you use different sizes of a limited number of fonts, rather than including lots of different fonts. To promote design consistency on your Moodle site, consider setting up a style guide so that all teachers use the same design framework. Alignment A basic principle of graphic design is to make sure that the objects on your page are aligned with each other. Imagine a grid that they stick to. Aligned objects look more professional and enhance contrast within pages. Moodle organizes that automatically for us with front pages and course pages, but when we set up instruction pages for activities, we need to keep alignment principles in mind, as we have more design freedom. Quality Aim for the best quality audio recordings and images. It is likely to make a big difference to language learners if they can listen to clear recordings and easily identify the content of images. This article Each of the following sections in this article contributes to the above principles by demonstrating some of the tools available in Moodle that help you with your design. You'll find a consideration of these and other website design issues at http://www.asktog.com/basics/firstPrinciples.html. Here are the main topics covered in this article: Text Images Videos Sound Navigation Blocks Layout Style guide Accessibility Feedback Text There are two main ways of entering text in Moodle: Adding text pages Adding web pages using the HTML editor The most common way is by using the HTML editor. Most of this section on text will look at formatting options using that. Adding text pages When you select Add a resource... and then Compose a text page, you get a choice of formatting options for your page. You might find it useful to use the Moodle auto-format, as it automatically creates emoticons, paragraphs, and hyperlinks for you if you write in web addresses. Creating hyperlinks is a little more time-consuming if you choose the HTML format, as you have to create all hyperlinks manually. Markdown format is also useful if you want to create a structured document with lists and emphasis. You can, of course, produce all these in the HTML format, using the editing menu. The following options are available when you select Add a resource... and then Compose a text page. Formatting options Details Moodle auto-format This has limited formatting options, but will automatically turn URLs like http://moodle.org into hyperlinks and will include emoticons like J when you type :). It keeps line breaks and converts blank lines into new paragraphs. HTML format This does not automatically format text, but gives you a wide range of possibilities for editing your text. It allows you to change font faces, font sizes, and color, as well as embed graphic images, sound, and video. Note that if you select Compose a text page and then the HTML format option, you will need to enter pure HTML-that's the code that produces web pages. If you are not familiar with HTML, you'll be better off choosing Compose a web page and then using the HTML graphic editor. Plain text format This format keeps spaces and new lines, but no other formatting is available. Markdown format Markdown allows you to easily add emphasis (bold, italics), structure (bullet points and headings), and links (to images or other web resources). You can use Markdown in many places in Moodle. Simply select it from the formatting drop-down list, which is found below the text entry area, wherever you have the choice.  
Read more
  • 0
  • 0
  • 3679

article-image-joomla-flash-flashy-templates-headers-banners-and-tickers-part-2
Packt
18 Nov 2009
4 min read
Save for later

Joomla! with Flash: Flashy Templates, Headers, Banners, and Tickers: Part 2

Packt
18 Nov 2009
4 min read
Using Flash headers We have seen that one of the uses of Flash in Joomla! templates is as a header. By using a Flash animation in a site's header you can create some stunning effects. As we have already seen, while designing the template, we may embed Flash animation in the header region and control the layout using an appropriate CSS stylesheet. To embed such Flash animations like these, you can use the <object> </object> XHTML tag. We have seen its use in the previous section. An alternative to this is showing the Flash header at some module position. There are several extensions that can be used for showing Flash objects at a module position. We will be looking at some of them next. Using Flexheader3 Flexheader3 is a Joomla! 1.5-compatible extension for using Flash as headers in Joomla! sites. This is available for download for free at http://flexheader2.andrehotzler.de/en/download/folder/208-flexheader3.html. After downloading the package, install it from the Extensions | Install/Uninstall screen in Joomla! administration. Then click on Extensions | Module Manager. In the Module Manager screen, you will find the module named Flexheader3. Click on it and that shows the Module: [Edit] screen for the Flexheader3 module, as shown in the following screenshot: The Details section is similar to other modules from where you enable the module, select the module position to display this, select the order of display, and assign menus for which this module will be displayed. The module-specific settings are in the Parameters section. As you see, selecting the module position is crucial for this module. Most of the templates don't have a position to display the header using a module. Therefore, you may need to create a module position for displaying a Flash header. The following section shows you how to create a module position displaying a header. Creating a module position To create a module position in your template you need to edit at least two files. Browse to the /templates directory, and click on the name of the template that you want to modify. You need to edit two files in the template folder: index.php and templateDetails.xml. First, open the templateDetails.xml file in your text editor and find the <positions> tag. Under this, type the line highlighted in the following code so that the file looks like the following: <positions> <position>flexheader</position> <position>left</position> <position>user1</position> ... <position>right</position> <position>debug</position> </positions> Remember to type <position>flexheader</position> before ending </positions> tag. Placing it outside the <positions> </positions> block will make the template unusable. After modifying the templateDetails.xml file, open the index.php file in your text editor. Find out the code for including a header image in that template. Generally, this is done by inserting an image using the <img src=... /> tag. If you don't find such a tag, then look for <div id="header" ... > or something like that. In such cases, CSS is used to display the background image to the div element. Once you have found the code for showing the header image, replace it with the following code: <jdoc:include type="modules" name="flexheader" style="RAW" /> This line of code means that you are instructing to include modules designated for the flexheader position. When we assign the Flexheader3 module to this position, the contents of that module will be displayed in this position. Generally, this module will produce a code like the following in this position: <img src="/images/header.png" title="My header image" alt="Header image" style="width: 528px; height: 70px;" /> When changes to index.php are made, save those changes. We will be configuring the module to display a Flash header in this module position.
Read more
  • 0
  • 0
  • 5859

article-image-user-interaction-and-email-automation-symfony-13-part2
Packt
18 Nov 2009
8 min read
Save for later

User Interaction and Email Automation in Symfony 1.3: Part2

Packt
18 Nov 2009
8 min read
Automated email responses Symfony comes with a default mailer library that is based on Swift Mailer 4, the detailed documentation is available from their web site at http://swiftmailer.org. After a user has signed up to our mailing list, we would like an email verification to be sent to the user's email address. This will inform the user that he/she has signed up, and will also ask him or her to activate their subscription. To use the library, we have to complete the following three steps: Store the mailing settings in the application settings file. Add the application logic to the action. Create the email template. Adding the mailer settings to the application Just like all the previous settings, we should add all the settings for sending emails to the module.yml file for the signup module. This will make it easier to implement any modifications required later. Initially, we should set variables like the email subject, the from name, the from address, and whether we want to send out emails within the dev environment. I have added the following items to our signup module's setting file, apps/frontend/config/module.yml: dev: mailer_deliver: true all: mailer_deliver: true mailer_subject: Milkshake Newsletter mailer_from_name: Tim mailer_from_email: no-reply@milkshake All of the settings can be contained under the all label. However, you can see that I have introduced a new label called dev. These labels represent the environments, and we have just added a specific variable to the dev environment. This setting will allow us to eventually turn off the sending of emails while in the dev environment. Creating the application logic Triggering the email should occur after the user's details have been saved to the database. To demonstrate this, I have added the highlighted amends to the submit action in the apps/frontend/modules/signup/actions/actions.class.php file, as shown in the following code: public function executeSubmit(sfWebRequest $request) { $this->form = new NewsletterSignupForm(); if ($request->isMethod('post') && $this->form-> bindAndSave($request->getParameter($this->form-> getName()))) { //Include the swift lib require_once('lib/vendor/swift-mailer/lib/swift_init.php'); try{ //Sendmail $transport = Swift_SendmailTransport::newInstance(); $mailBody = $this->getPartial('activationEmail', array('name' => $this->form->getValue('first_name'))); $mailer = Swift_Mailer::newInstance($transport); $message = Swift_Message::newInstance(); $message->setSubject(sfConfig::get('app_mailer_subject')); $message->setFrom(array(sfConfig:: get('app_mailer_from_email') => sfConfig::get('app_mailer_from_name'))); $message->setTo(array($this->form->getValue('email')=> $this-> form->getValue('first_name'))); $message->setBody($mailBody, 'text/html'); if(sfConfig::get('app_mailer_deliver')) { $result = $mailer->send($message); } } catch(Exception $e) { var_dump($e); exit; } $this->redirect('@signup'); } //Use the index template as it contains the form $this->setTemplate('index'); } Symfony comes with a sfMailer class that extends Swift_Mailer. To send mails you could simply implement the following Symfony method: $this->getMailer()->composeAndSend('from@example.com', 'to@example.com', 'Subject', 'Body'); Let's walk through the process: Instantiate the Swift Mailer. Retrieve the email template (which we will create next) using the $this->getPartial('activationEmail', array('name' => $this->form->getValue('first_name'))) method. Breaking this down, the function itself retrieves a partial template. The first argument is the name of the template to retrieve (that is activationEmail in our example) which, if you remember, means that the template will be called _activationEmail.php. The next argument is an array that contains variables related to the partial template. Here, I have set a name variable. The value for the name is important. Notice how I have used the value within the form object to retrieve the first_name value. This is because we know that these values have been cleaned and are safe to use. Set the subject, from, to, and the body items. These functions are Swift Mailer specific: setSubject(): It takes a string as an argument for the subject setFrom(): It takes the name and the mailing address setTo(): It takes the name and the mailing address setBody(): It takes the email body and mime type. Here we passed in our template and set the email to text/html Finally we send the email. There are more methods in Swift Mailer. Check out the documentation on the Swift Mailer web site (http://swiftmailer.org/). The partial email template Lastly, we need to create a partial template that will be used in the email body. In the templates folder of the signup module, create a file called _activationEmail.php and add the following code to it: Hi <?php echo $name; ?>, <br /><br /> Thank you for signing up to our newsletter. <br /><br /> Thank you, <br /> <strong>The Team</strong> The partial is no different from a regular template. We could have opted to pass on the body as a string, but using the template keeps our code uniform. Our signup process now incorporates the functionality to send an email. The purpose of this example is to show you how to send an automated email using a third-party library. For a real application, you should most certainly implement a two-phase option wherein the user must verify his or her action. Flashing temporary values Sometimes it is necessary to set a temporary variable for one request, or make a variable available to another action after forwarding but before having to delete the variable. Symfony provides this level of functionality within the sfUser object known as a flash variable. Once a flash variable has been set, it lasts until the end of the overall request before it is automatically destroyed. Setting and getting a flash attribute is managed through two of the sfUser methods. Also, you can test for a flash variable's existence using the third method of the methods listed here: $this->getUser()->setFlash($name, $value, $persist = true) $this->getUser()->getFlash($name) $this->getUser()->hasFlash($name) Although a flash variable will be available by default when a request is forwarded to another action, setting the argument to false will delete the flash variable before it is forwarded. To demonstrate how useful flash variables can be, let's readdress the signup form. After a user submits the signup form, the form is redisplayed. I further mentioned that you could create another action to handle a 'thank you' template. However, by using a flash variable we will not have to do so. As a part of the application logic for the form submission, we can set a flash variable. Then after the action redirects the request, the template can test whether there is a flash variable set. If there is one, the template should show a message rather than the form. Let's add the $this->getUser()->setFlash() function to the submit action in the apps/frontend/modules/signup/actions/actions.class.php file: //Include the swift lib require_once('lib/vendor/swift-mailer/lib/swift_init.php'); //set Flash $this->getUser()->setFlash('Form', 'completed'); try{ I have added the flash variable just under the require_once() statement. After the user has submitted a valid form, this flash variable will be set with the name of the Form and have a value completed. Next, we need to address the template logic. The template needs to check whether a flash variable called Form is set. If it is not set, the template shows the form. Otherwise it shows a thank you message. This is implemented using the following code: <?php if(!$sf_user->hasFlash('Form')): ?> <form action="<?php echo url_for('@signup_submit') ?>" method="post" name="Newsletter"> <div style="height: 30px;"> <div style="width: 150px; float: left"> <?php echo $form['first_name']->renderLabel() ?></div> <?php echo $form['first_name']->render(($form['first_name']-> hasError())? array('class'=>'boxError'): array ('class'=>'box')) ?> <?php echo ($form['first_name']->hasError())? ' <span class="errorMessage">* '.$form['first_name']->getError(). '</span>': '' ?> <div style="clear: both"></div> </div> .... </form> <?php else: ?><h1>Thank you</h1>You are now signed up.<?php endif ?> The form is now wrapped inside an if/else block. Accessing the flash variables from a template is done through $sf_user. To test if the variable has been set, I have used the hasFlash() method, $sf_user->hasFlash('Form'). The else part of the statement contains the text rather than the form. Now if you submit your form, you will see the result as shown in the following screenshot: We have now implemented an entire module for a user to sign up for our newsletter. Wouldn't it be really good if we could add this module to another application without all the copying, pasting, and fixing?
Read more
  • 0
  • 0
  • 8654
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 $19.99/month. Cancel anytime
article-image-archiva-team-part-1
Packt
18 Nov 2009
11 min read
Save for later

Archiva in a Team: Part 1

Packt
18 Nov 2009
11 min read
Roles and permissions In preparation for the latter sections of this article, let's familiarize ourselves with the user roles and permissions available in Archiva. The list of available roles can be seen by clicking a user account in User Management and then clicking on the Edit Roles link. Some of the roles in Archiva are resource-based with each repository treated as a resource. This means that access is controlled at the repository level. There are eight types of roles available in Archiva. They are: System Administrator: Provides access to Manage and Administration sections, user administration privileges, and read and write permissions to all repositories. User Administrator: Provides access to User Management and User Roles pages. Global Repository Manager: Provides read and write permissions to all repositories. Global Repository Observer: Provides read permission to all repositories. Repository Manager (resource level): Provides read and write permissions to a given repository. Repository Observer (resource level): Provides read permission to a given repository. Registered User: The default role assigned to a user who has registered in Archiva. Guest: Provides the same permissions that are enabled for the built-in guest user account, which we will discuss later on. A user assigned with a Global Repository Manager or resource level Repository Manager role automatically gains the Global Repository Observer or resource level Repository Observer role respectively. Users assigned with a Repository Manager role should be able to access the Find section as well as Upload Artifact and Delete Artifact menu in the web application. On the other hand, users with a Repository Observer role should only be able to access the Find section. Repository-level security applies to each corresponding operation. This means that a user will only be able to search, browse, and upload to or delete artifacts from those repositories that they have permission to access. When managing roles and permissions, another thing to take note of is the guest account. To enable access without authentication for a specific resource or operation, just assign the guest user the appropriate role. By default, the guest user is already assigned the Repository Observer role for internal and snapshots repositories. This allows anyone to be able to browse and search for artifacts from these repositories. If you edit the guest user account, you should be able to see the following configuration: As you can see the guest user doesn't yet have read access to the releases repository. In our examples, we will assume that the repository will be available to everyone that can access Archiva. So to make this consistent with the snapshots repository, check the Repository Observer box for releases and submit the form. You can see for yourself how the guest account works by logging out of Archiva and clicking Browse on the navigation menu. The artifacts that were requested and were downloaded to our proxy repository should be visible in the Browse page, similar to what is seen in the following screenshot: As we work through the rest of the article, we will cover a few more things about access control in Archiva. Now that we are familiar with the security basics, we are ready to tackle some of the more advanced features of Archiva. In the next section, we will learn techniques for configuring our Archiva repositories. Introducing repository groups In Archiva 1.1, the concept of repository groups (also known as virtual repositories) was introduced. Taking the meaning of the term virtual literally, these repositories are physically non-existent repositories. A virtual repository is simply a URL which gives a single interface to a group of managed repositories. Let's visualize this with a simple scenario. For example, we have a Maven 2 project which has dependencies on artifacts that reside in multiple repositories. In this case, we will assume that we have a nearby proxy cache configured in Archiva for each of them. Given this scenario, it would mean that we have to configure each of these repositories in our settings.xml (or POM), in order for us to get the needed artifacts and to be able to build our project. If these repositories are secured, we also need to configure our credentials for each. This leaves us with a long (and possibly messy) settings.xml. Remember, a messy configuration is an attraction for errors. To avoid this problem, we can make use of repository groups in Archiva. We can create a repository group and configure or add multiple repositories under that group. So when an artifact request is made (for example, by Maven) using the repository group URL, the repositories underneath it will be searched until the requested artifact is found and returned to the client. The following section teaches us how to configure repository groups and experience their strength first-hand. Configuring and using repository groups Before jumping into configuration, it is good to see how it will be without the aid of repository groups. As the Centrepoint project refers to the released version—POM Apache Maven 2: Effective Implementations Book, anyone who builds that project must be able to get the organization POM from the releases repository. This is a perfect setup for using repository groups. Let's begin by wiping out our local repository again and building the Centrepoint project. centrepoint$ mvn clean install The build should fail with the following error: [INFO] Scanning for projects...Downloading: http://localhost:8081/archiva/repository/internal/com/effectivemaven/effectivemaven-parent/1/effectivemaven-parent-1.pom[INFO] ----------------------------------------------------------[ERROR] FATAL ERROR[INFO] ----------------------------------------------------------[INFO] Failed to resolve artifact.GroupId: com.effectivemavenArtifactId: effectivemaven-parentVersion: 1Reason: Unable to download the artifact from any repository com.effectivemaven:effectivemaven-parent:pom:1from the specified remote repositories: internal (http://localhost:8081/archiva/repository/internal)   Our organization POM cannot be found because it resides in the Archiva releases repository, and we don't have it configured in our settings.xml. The version in ../effectivemaven-parent/pom.xml is also not used because the versions now differ. To get past this problem, we must add the following configuration in the settings.xml: <profiles> <profile> <id>repositories</id> <activation> <activeByDefault>true</activeByDefault> </activation> <repositories> <repository> <id>releases</id> <name>Archiva Managed Releases Repository</name> <url> http://localhost:8081/archiva/repository/releases </url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </profile> </profiles> We already configured the <server> credentials for the releases repository when we tried deploying to Archiva using Maven so we no longer need to configure that. If you try building Centrepoint again, the build will still fail. Notice that Maven didn't even seem to try looking for the artifact from the releases repository we added previously. This is because we have locked down Maven to use only the local mirror repository internal. This is the effect of the <mirrorOf>*</mirrorOf> configuration in our settings.xml, Staying in Control with Archiva. Just change it to <mirrorOf>*,!releases</mirrorOf> so that Maven would respect the additional repositories. Execute the build again. This time we should be able to get a successful build. However, for every member of the team working on the Centrepoint project, the settings.xml (now over 40 lines long) is needed at the minimum. As the project grows bigger, more artifacts are added. Also, if these new artifacts are located in other repositories, you would need to add this repository to your settings.xml and so on and so forth. We already learned at the start of this section that in situations such as this, a repository group can make things easier for us developers. Let us see how we can create one. Let's go back to our running Archiva instance. Click Repository Groups, then type public in the Identifier field on the upper right-hand corner of the page and click Add Group. We now have a virtual repository named public with the following URL: http://localhost:8081/archiva/repository/public. You may change the name of the repository group to a more appropriate one if the repositories are not really for public consumption. To add managed repositories under the group, just select the repository you would like to add from the list under the created group and click Add Repository. Add the releases and internal repositories (this order is used so that requests for the organization's artifacts are never made on external proxied repositories). Note that we don't want to add the snapshots repository to the group as that might change the behavior of the repository. One example of this is when dealing with version ranges. You might end up getting a snapshot version instead of a released version. Now, with this configuration, we are telling Archiva that if an artifact request is made on the repository group public, it should look for the artifact in these two repositories (based on the order they are listed) and return the first matching artifact it sees. You can change the ordering of the repositories to be searched by moving a repository up or down the repository group configuration via the Up and Down icons. After configuration, the page should look similar to the following: Now that we have a repository group that we can use, let's configure it in our settings.xml. Remove the profile we added previously, and adjust the mirror section as follows: <mirrors> <mirror> <id>public</id> <url>http://localhost:8081/archiva/repository/public</url> <mirrorOf>*</mirrorOf> </mirror> </mirrors> Notice how much shorter and simpler our settings.xml is now. Group credentials The guest user has access to all of the repositories in the group so we don't need a corresponding <server> for the mirror. However, if read access control applies to any repositories in the group, make sure to add a <server> for the ID of the mirror (not the underlying repositories that are no longer visible to Maven). The existing <server> definitions continue to be used for deployment, as deployment cannot be done to a group. Let's try building Centrepoint again, but this time with a clean local repository, using the new settings.xml. We should be able to see both com.effectivemaven: effectivemaven-parent:pom:1 and the other dependencies from the central repository being retrieved from our public repository group, ending with a successful build as follows: [INFO] Scanning for projects...Downloading: http://localhost:8081/archiva/repository/public//com/effectivemaven/effectivemaven-parent/1/effectivemaven-parent-1.pom1K downloaded[INFO] Reactor build order:...[INFO] ----------------------------------------------------------[INFO] Building Centrepoint[INFO] task-segment: [clean, install][INFO] ----------------------------------------------------------Downloading: http://localhost:8081/archiva/repository/public//org/apache/maven/plugins/maven-clean-plugin/2.2/maven-clean-plugin-2.2.pom3K downloadedDownloading: http://localhost:8081/archiva/repository/public//org/apache/maven/plugins/maven-plugins/10/maven-plugins-10.pom What else can we do with repository groups? Consider, for example, that we added new dependencies to our Centrepoint project and these dependencies are projects being worked on by another team within the company. Let's say the other team have their own deployment repository (separate from ours) managed by Archiva as well. We no longer have need to make any changes in our settings.xml (or POM). The repository just needs to be added in the public repository group and the appropriate permissions assigned to the Centrepoint project developers' accounts. Configuration is much simpler now and is concentrated in Archiva itself. Developers and team members won't have to configure their settings.xml each time a new repository is needed.   RSS feeds—discovering new artifacts in your repository RSS has become the de facto standard with regard to news feeds and updates on the web. The Archiva community has seen how the project can take advantage of this current trend by providing RSS feeds for new artifacts in the repository. Projects that use or depend on specific libraries would be able to know when a new release is available or when there is a new build. This is especially useful when a project is dependent on a fix that would be available in the next release or in the next build. A Repository Observer role is required at least in order to subscribe to a feed in Archiva. There are two levels of RSS feeds available in Archiva: repository level and artifact level. In the following sections, we will be using Thunderbird's RSS feed reader for demonstration purposes. You can get Thunderbird from http://www.mozillamessaging.com/en-US/thunderbird/ and can set it up using the installation guides at http://www.mozillamessaging.com/en-US/support/. You can also use other RSS feed readers such as Google Reader. If access to your repositories require authentication, your feed reader must support authentication. If security is lenient, you can just disable authentication for read operations to your repository by granting the guest account the Repository Observer role.
Read more
  • 0
  • 0
  • 1856

article-image-version-management-upk-35-part-1
Packt
18 Nov 2009
12 min read
Save for later

Version Management with UPK 3.5: Part 1

Packt
18 Nov 2009
12 min read
Though this implies multi-user environment client/server setup, this article could still be of use to a single user. If you are a lone developer working in a stand-alone environment (sometimes referred to as a single-user environment), you may want to just skip straight to the section Exporting and importing content, at the end of this article. Sorry, but version management in a stand-alone environment is almost nonexistent, so you're largely on your own. In a client/server environment, all content objects are stored on a central server. Developers create and edit content on their own workstation (typically, a PC), and then send this content to a database on the central server for storage when they have finished with it. This is referred to as checking in a content object. If they subsequently want to change a content object that is on the server, they need to check out the content object, change it, and then check it back in. Checking in a content object When you create a content object in a client/server environment, the content object is stored in your local repository (that is, on the client side of the client/server set-up). It is important to understand that your local repository is located on your local workstation. This means that if you have a content object in your local repository, and then move to another workstation, you will not see your local version of this content object on the new workstation. This is because they are located on the workstation on which you created them or checked them out. You should, therefore, always use the same workstation, or check in all of your content objects before moving to a new workstation. Version Difference In UPK 3.5.1 client/server edition, it is possible to choose a specific location for your local repository. Documents that are checked out to your local repository are identified by a green check-mark () to the left of the object details in the Library. You will need to check these objects in if you want them to be stored in the central library so they will be accessible to other developers. Generally, you should do this whenever you have finished working on a content object. However, there are good reasons for checking in objects more frequently. Your local repository is (typically) in the C: drive of your computer, whereas the central library is on a central server. Unless you are very fastidious about backing up your PC, the chances are that the server is backed up more often than your PC, and is usually backed up automatically. Placing your files in the central library will, therefore, provide greater security in terms of having a backup that you can revert to in the event of a disaster. In addition to this, whenever you check in a content object, a back-up of the previous version is taken. Should you need to back out your changes, you can simply revert to a back-up version of the content object. Related to this, content objects are never really deleted from the server library. Actually, they can be deleted, but only by an Administrator, and typically as part of a cleanup. However, if you delete an object (that has never been checked in to the central server) from your local repository, it is gone. Forever! Finally, it is not unheard of that for a local repository to simply disappear when UPK crashes (which thankfully doesn't happen that often, but it has been known to happen). If this does happen to you, then you may again lose all of the content that you currently have checked out even though the Lost documents view, introduced in UPK 3.5, may save you. For all of these reasons, and more, it is recommended that you check in all of the content that is stored in your local repository to the server at least at the end of each work day. Fortunately, UPK provides a quick way of doing this. If you click the Check In All button (), then all of the content objects that you currently have checked out will be checked in again. The downside of this is that if you do check in all of the documents that you are currently working on at the end of the day, you need to remember which objects these are so that you can check them out again the next day. Before checking the documents in, you can use the All Checked Out view to identify all of the documents that you currently have checked out. You can then print this list, and will know which files you need to check out again the next day. There is one further thing to bear in mind when deciding how often you are going to check in your content objects. As mentioned above, UPK retains every version of a content that has been checked in. These are accessible via the Document History, as we will see later. This means that if you check in a content object ten times, then UPK will retain ten versions of it. This can also make it difficult to identify the "released" versions of the content object in the Document History, should you subsequently need to roll back to the last-released version. The Administrator can clean up the database periodically, but the only way of differentiating between versioned drafts and versioned released content objects is by using the check-in comments. These are explained in the section Step 2: Confirming the scope of the check-in, ahead. UPK Workflow The down-side to checking in content objects that you may not have finished working on is that these objects could be mis-perceived as being final, and actually used or published. In some cases, you may have checked some of them out not because you want to change them, but specifically to stop anyone else from changing them. UPK does not provide you with a simple, automatic solution to these shortcomings, but there is a manual workaround that you can use. This is to use the Workflow properties of the objects. UPK does not have a "real" workflow, it does not have "routing" of content objects based on their status, or automatic email notification of content objects that are due for review, or any of the things that you'd expect from workflow functionality. Of course users can use a Custom View to display content objects according to their Workflow properties, but this is still not really "workflow". If you display the Properties for a content object, by clicking on the Properties button (), the last category of properties (at the end of the Properties list) is the Workflow category. Within this, there are two properties: Assigned To: This property allows you to select (from a drop-down list) the user ID of any developer who is authorized to access the content object. If you select your own user ID in this field, then this is an indication to the other developers that they should not work on this content object themselves. State: This property can be used to specify the current status of a content object. The default values are (blank), Not Started, Draft, In Review, and Final. If you select a status of Draft, then this is an indication that you have not finished with the object. An example of the Properties pane, showing the Workflow category, is in the following screenshot: Of course, these Properties do not provide "hard checks". You still rely on people seeing, and then paying attention to, these Properties but it is a start. Some strong guidance from your Project Manager or Team Leader would help, here. Administrators can add, remove, or rename statuses. It is recommended that a suitable set of statuses are established and defined prior to any development work starting, and that these statuses and their meaning are communicated to all developers. Step 1: Selecting the content objects To select content objects for checking in, carry out the steps described below: In the Library, select the content objects that you want to check in. Normally, you will want to check in specific content objects, so you would only select these. As always, you click on a content object to select it. You can Ctrl-click to select multiple objects, or Shift-click to select a series of objects. You can also select a folder in the Library to check in all of the content objects in that folder. Do not worry if some of the objects that are included in your selection are not checked out; UPK will simply ignore these objects during check-in (it will not "error-out"). You can also check in content objects by selecting them in an Outline Element. Once you have selected all of the content objects that you want to check in, click the Check In button (). Step 2: Confirming the scope of the check-in When you check in one or more specific content objects and have not selected a folder in the Library to check in, UPK will automatically check for any content objects that are related to the object that you are checking in. You will be prompted to check these in, as well. An example of this prompt is shown in the following screenshot: What are related documents? In general, they are Web Pages and Packages used by the content object that you are checking in. For example: If you have created, or changed, an Outline Element (Module or Section) then UPK will automatically select all of the content objects (Modules, Lessons, and Topics) included in this Outline Element, along with any Web Pages used by any of these content objects will be selected as well. If you are checking in a Topic for which you have also created a Web Page that is linked to the Concepts pane, then UPK will automatically select this Web Page as a related document during check-in. If you have created a Glossary and are checking this in, the related documents will be all of the Web Pages for the content definitions used by the Glossary. An example of the Related Documents dialog box is shown in the following screenshot: This list of related documents can be confusing, as it does not match the list that you see in the Related Documents pane for the content object that you are checking in. The list will include Web Pages that have been explicitly linked to from the content object that you are checking, but will not include Glossaries, Templates, Packages, or icons, all of which are listed in the Related Documents pane. This limitation is important to understand. If you checked out, and updated, a Glossary and as a result UPK checked out several content objects during the glossary link regeneration, UPK will not identify all of the Glossary elements (Web Pages) as "related documents". You will need to locate these and check them in separately using custom views. Adding to the confusion, the list of related documents will include all of the explicitly-linked content objects, and not only those objects that are currently checked out to you. Do not worry about this – UPK will only physically check in the content objects that you do have checked out (these are the ones that have your User ID in the Checked Out To column of the Related Documents dialog box). In the example above, we are checking in an Outline Element that contains one Topic, which in turn contains a Web Page. The Topic is checked out, but the Web Page is not. Step 3: Specifying a reason for the change When you check in one or more content objects, you will be prompted to enter a short description of the change, as shown in the following screenshot: The title of the content object that you are checking in is shown above the comment text box. If you are checking in multiple content objects, then this will initially specify the first object and (assuming that you deselect the Apply same comments to all documents option) will specify the next object when you click OK. It then moves on to the next object. In this way, you can provide separate comments for each content object, even though you are checking them all in at the same time. Although it is entirely optional, it is a very good practice to always enter a comment. This comment will appear in the object History, and therefore serves as a useful audit log. Specify a reason for the change by carrying out the steps described below: Enter a suitable comment in the space provided. Note that you do not need to specify the date and time of the change, or your user ID. These are captured automatically by UPK. If you are checking in multiple objects, then UPK will initially suggest applying the same comments to all of the objects. You will see that the Apply same comments to all documents checkbox toward the bottom of the dialog box is selected. If you do not want to use the same comment for all objects that you are checking in, then deselect this checkbox. Now, when you click on OK, the Check In Comment dialog box for the next content object in the check-in selection will be displayed. You can repeat the above processing from Step 3. Once you have entered your description of the change (or reason for the change), click on OK. Once you have specified a comment, and clicked on OK for the last time, then the content objects are checked in, and the Library screen is redisplayed.  
Read more
  • 0
  • 0
  • 1800

article-image-customizing-document-joomla-15-part-1
Packt
18 Nov 2009
3 min read
Save for later

Customizing the Document with Joomla! 1.5: Part 1

Packt
18 Nov 2009
3 min read
Introduction The classes that extend JDocument are intended for different response formats. The following table describes the classes and their purposes: Class Format Default MIME type Purpose JDocumentError error text/html Display a fatal error JDocumentFeed feed application/rss+xml   or application/atom+xml Syndication feed, RSS, or Atom JDocumentHTML html text/html Default document used for all typical Joomla! responses JDocumentPDF pdf application/pdf Adobe PDF representation JDocumentRAW raw* text/html All other circumstances   So what exactly does the format column represent? When a request is made, Joomla! uses the value of the request variable format to determine which document type to use. We really see this only when we retrieve something other than an HTML document, because this always defaults to html. For example, when we request an article as a PDF, we use a URI similar to this: http://example.org/index.php?option=com_content&view=article&id=5&format=pdf The JDocumentError class is slightly different from the others. We should never really need to interact directly with this. We can, of course, invoke this document indirectly by raising a fatal error. For more information, refer to Error handling and reporting. The Joomla! document object and views in Joomla! MVC components are closely related. For each format that we provide a view, we create a new JView subclass. For example, when we examine the content component, we can see that the article view supports HTML and PDF simply by the presence of the view.html.php and view.pdf.php files. This article also deals with the static JResponse class. This class is used to define the HTTP response, including the HTTP headers. The separation between JResponse and the JDocument object is not always as clear as one would hope. However, this is somewhat inevitable because the two are inextricably linked—the response describes and includes the document output. For example, outputting an HTML response will require the response Content-Type header field to be set accordingly, that is, as text/html. Setting the document title This recipe explains how to set the title of the current document. The exact meaning of title will depend on the type of document. For example, in an HTML document, this is the value encapsulated in the <head> tag. Getting ready Before we do anything, we need the global document object. $document =& JFactory::getDocument(); How to do it... To set the title of the document, we use the JDocument::setTitle() method $document->setTitle('My Unique Title'); If we are outputting an HTML document, this should generate something like this: <title>My Unique Title</title> There's more... Menu items can also define page titles. Thus, the actual title we use should not necessarily be the title of whatever we are viewing. To deal with this, we should use something along these lines: // get the component and page parameters$application =& JFactory::getApplication();$params =& $application->getParams();// get the page title$pageTitle = $params->get('page_title', $defaultTitle);// set the document title$document->setTitle($pageTitle); Setting the document generator This recipe explains how to set the name of the piece of software that generated the page. The exact meaning of generator will depend on the type of document. For example, in an HTML document, this value is used in a tag. Getting ready Before we do anything, we need the global document object. $document =& JFactory::getDocument();
Read more
  • 0
  • 0
  • 2299

article-image-processing-twitter-and-new-york-times-apis-aspnet-ajax-microsoft-cdn
Packt
18 Nov 2009
7 min read
Save for later

Processing Twitter and New York Times APIs with ASP.NET Ajax on Microsoft CDN

Packt
18 Nov 2009
7 min read
APIs (Application Programming Interface) are application-to-application programming interfaces that support harvesting information on the web using the known web standards. These APIs are provided by the entities who wish to expose parts of their resources that a third party can use. The APIs run transparent to the user and exposes just what they want to expose, with some providing access to material for public consumption with others giving access to resources based on authentication. In a sense they may be called a basic form of SAAS. Amazon.com, Google etc have exposed their APIs for some time. Twitter and New York Times have also exposed their API's which can be used to do some digging into the information contained in them, a kind of web mining. Many others such as Netflix have provided their own APIs described on their web sites. What is Twitter API? Twitter API is provided by the Social Networking and Micro-blogging service. Twitter API adheres to the web standards and one can talk to Twitter using HTTP. You can just about access anything on the Twitter web site. One example of creating a Microsoft SQL Server Report using Twitter API is available here - Tweets with Reporting Services, wherein the response from the Twitter API was in XML format. JSON (JavaScript Object Notation) is another format in which data is returned when an API call is made. In this article we will be looking at API call that returns a JSON response. Twitter exposes a large number methods through their API's such as API's for Search, Timeline, Status, User, Direct Message, Friendship and many more. As previously mentioned the responses will be in XML or JSON. Also while some APIs may take parameters others may not. The Twitter API used in this tutorial We will be looking at trends in Twitter API exposed by the url, http://search.twiiter.com/trends.format. We will be using the GET method and we will expect a JSON response. Since the volume of traffic may overwhelm, the calls that you can make to this in an hour are limited (also known as rate limiting) but not critical for the demo in this tutorial. Here is a typical call to the trends method on the Twitter API. Herein we will search for trends on the Twitter site and expect a response in JSON, if we use json instead of Format in the next URL address. Instead of:http://search.twitter.com/trends.Formattype-in, the following for URL address,http://search.twitter.com/trends.json When you plug the above in a web Brower you would get a response trends.json which you may save to your hard drive or, use it in any way you like. The next quoted text is what you get in response (note that this is what I got on Saturday 31, 2009 and what you get will be different), the content of the file trends.json you saved to your computer. Note that presently you get about top ten trends from this API call. {"as_of":"Sat, 31 Oct 2009 20:44:46 +0000","trends":[{"name":"Happy Halloween", "url":"http://search.twitter.com/search?q=%22Happy+Halloween%22+OR+%22Feliz+ Halloween%22"},{"name":"#nxzerosetechaves","url":"http://search.twitter.com/search?q=%23nxzerosetechaves"},{"name":"Danyl","url":"http://search.twitter.com/search?q=Danyl"},{"name":"#HappyHalloween","url":"http://search.twitter.com/search?q=%23HappyHalloween"},{"name":"#potterday","url":"http://search.twitter.com/search?q =%23potterday"},{"name":"X Factor","url":"http://search.twitter.com/search?q=%22X+ Factor%22"},{"name":"It's Halloween","url":"http://search.twitter.com/search?q=%22It %27s+Halloween%22+OR+%22Its+Halloween%22"},{"name":"Trick","url":"http://search.twitter.com/search?q=Trick+OR+%23trick"},{"name":"Paranormal Activity","url":"http://search.twitter.com/search?q=%22Paranormal+Activity%22"},{"name":"This Is It","url":"http://search.twitter.com/search?q=%22This+Is+It%22"}]} First of all what you see returned is a JSON object. If you are new to JSON review this article on my blog. The various elements that you see such as 'name', 'url' etc are fields in the response that are all described in the API documentation(look for Return Values). Some of the API calls can return a ton of information and you will have to know the API method so that you can correctly parse this data. Another thing you would notice is that the JSON object you get out is a nested object with many levels. You may need a JSON Parser to get a clearer picture of this nesting and I recommend using the online parser at this site. Using the above site, the JSON Object would appear as shown (only a portion is shown). New York Times API New York Times made available to the developers sometime in the middle of October 2008 APIs that can search New York Times for various kinds of information . Just like in Twitter there are a large number of APIs that you can use such as: Article Search; Best Sellers; Campaign Finance; Congress; and many others. Interested users can get on to this resource by signing up here requesting what APIs they would like to use. After signing up, New York Times would provide keys for the APIs that you want to access. It is important therefore, that the call should include the keys provided to you. For example, I received keys to access the following resources: Movie Reviews, Article Search, Best Sellers and Times Newswire. The key for the Movies Reviews API appears as shown here (the one shown here has been doctored and will not work). Movie Reviews API Key: b57378910b9fd80ecc73461547c93e8a:10:50673441 Using the New York Times API It is a valuable resource since you can get for example with the Article Search API access to more than 2.8 million articles from 1981. Using this is quite simple, just paste the URL shown below into the address box of your browser. Note that the key shown here is fake (but of correct format). http://api.nytimes.com/svc/search/v1/article?query=India&facets=publication_year&api-key=6c208890a4880093c30020be8fe17a40:0:50633441 This will display in the browser the JSON object that is returned as shown. You can use the previously mentioned site to parse it for more friendly display. {"facets" : {"publication_year" : [{"count" : 2724 , "term" : "2008"} , {"count" : 2345 , "term" : "2006"} , {"count" : 2311 , "term" : "2009"} , {"count" : 2282 , "term" : "2007"} , {"count" : 2144 , "term" : "2002"} ,{"count" : 2111 , "term" : "2001"} , {"count" : 1988 , "term" : "2005"} , {"count" : 1951 , "term" : "2004"} , {"count" : 1921 , "term" : "1985"} , {"count" : 1798 , "term" : "2003"} , {"count" : 1761 , "term" : "1999"} , {"count" : 1720 , "term" : "2000"} , {"count" : 1642 , "term" : "1998"} , {"count" : 1442 , "term" : "1984"} , {"count" : 1382 , "term" : "1986"}]} , "offset" : "0" , "results" : [{"body" : "BARSUR, India — At the edge of the Indravati River, hundreds of miles from the nearest international border, India effectively ends. Indian paramilitary officers point machine guns across the water. The dense jungles and mountains on the other side belong to Maoist rebels dedicated to overthrowing the government. "That is their liberated" , "byline" : "By JIM YARDLEY" , "date" : "20091101" , "title" : "Maoist Rebels Widen Deadly Reach Across India" , "url" : "http://www.nytimes.com/2009/11/01/world/asia /01maoist.html"} ,.........(there is more of this but abbreviated here) Response Format As you can see the responses to the API calls return JSON objects in general of the form shown belo w (this one is of the form returned by the Twiiter API). What we propose to do is to use jQuery's GetJSON() method to get the JSON Objects and use Microsoft AJAX JavaScript files to display the data on the web page. Both jQuery javascript files and Microsoft ASP.NET AJAX files are both available on the Microsoft ECN (CDN). The GetJSON() method as well as the Microsoft ASP.NET AJAX templates can be easily implemented in the Visual Studio 2008 IDE. Alternatively Microsoft AJAX can also be used to retrieve data from the web sites. In this article the GetJSON() method will be used. {"x":{"y":[{"a1":"b1", "c1":"d1"}, {"a2":"b2", "c2":"d2"}]},.... "f":"g",....}
Read more
  • 0
  • 0
  • 3838
article-image-microsoft-chart-xml-data
Packt
18 Nov 2009
4 min read
Save for later

Microsoft Chart with XML Data

Packt
18 Nov 2009
4 min read
Introduction SQL 2000 Server provided T-SQL language extensions to operate bi-directionally with relational and XML sources. It also provided two system stored procedures, sp_XML_preparedocument and sp_XML_removedocument, that assist the XML to Relational transformation. This support for returning XML data from relational data using the For XML clause is continued in SQL Server 2005 and SQL Server 2008 although the support for XML is lot more extensive. The shape of the data returned by the For XML clause is further modified by choosing the following modes, raw, auto, explicit, or path. As a preparation for this article we will be creating an XML document starting from the PrincetonTemp table used in a previous article, Binding MS Chart Control to LINQ Data Source Control, on this site. Creating an XML document from an SQL Table Open the SQL Server Management and create a new query [SELECT * from PrincetonTemp for XML auto]. You can use the For XML Auto clause to create a XML document (actually what you create is a fragment - a root-less XML without a processing directive) as shown in Figure 01. Figure 01: For XML Auto clause of a SELECT statement The result shown in a table has essentially two columns with the second column containing the document fragment shown in the next listing. Listing 01: <PrincetonTemp Id="1" Month="Jan " Temperature="4.000000000000000e+001" RecordHigh="6.000000000000000e+001"/> <PrincetonTemp Id="2" Month="Feb " Temperature="3.200000000000000e+001" RecordHigh="5.000000000000000e+001"/> <PrincetonTemp Id="3"Month="Mar " Temperature="4.300000000000000e+001" RecordHigh="6.500000000000000e+001"/> <PrincetonTemp Id="4" Month="Apr " Temperature="5.000000000000000e+001" RecordHigh="7.000000000000000e+001"/> <PrincetonTemp Id="5" Month="May " Temperature="5.300000000000000e+001" RecordHigh="7.400000000000000e+001"/> <PrincetonTemp Id="6" Month="Jun " Temperature="6.000000000000000e+001" RecordHigh="7.800000000000000e+001"/> <PrincetonTemp Id="7" Month="Jul " Temperature="6.800000000000000e+001" RecordHigh="7.000000000000000e+001"/> <PrincetonTemp Id="8" Month="Aug " Temperature="7.100000000000000e+001" RecordHigh="7.000000000000000e+001"/> <PrincetonTemp Id="9" Month="Sep " Temperature="6.000000000000000e+001" RecordHigh="8.200000000000000e+001"/> <PrincetonTemp Id="10" Month="Oct " Temperature="5.500000000000000e+001" RecordHigh="6.700000000000000e+001"/> <PrincetonTemp Id="11" Month="Nov " Temperature="4.500000000000000e+001" RecordHigh="5.500000000000000e+001"/> <PrincetonTemp Id="12" Month="Dec " Temperature="4.000000000000000e+001" RecordHigh="6.200000000000000e+001"/> This result is attribute-centric as each row of data corresponds to a row in the relational table with each column represented as an XML attribute. The same data can be extracted in an element centric manner by using the directive elements in the SELECT statement as shown in the next figure. Figure 02: For XML auto, Elements clause of a Select statement This would still give us an XML fragment but now it is displayed with element nodes as shown in the next listing (only two nodes 1 and 12 are shown). Listing 02: <PrincetonTemp><Id>1</Id><Month>Jan </Month><Temperature>4.000000000000000e+001</Temperature> <RecordHigh>6.000000000000000e+001</RecordHigh> </PrincetonTemp> ... <PrincetonTemp><Id>12</Id><Month>Dec </Month><Temperature>4.000000000000000e+001</Temperature> <RecordHigh>6.200000000000000e+001 </RecordHigh></PrincetonTemp> To make a clear distinction between the results returned by the two select statements the first row of data is shown in blue. This has returned elements and not attributes. As you can see the returned XML still lacks a root element as well as the XML processing directive. To continue with displaying this data in MS Chart Save Listing 2 as PrincetonXMLDOC.xml to a location of your choice. Create a Framework 3.5 Web Site project Let us create a web site project and display the chart on the Default.aspx page. Open Visual Studio 2008 from its shortcut on the desktop. Click File  New | Web Site...|(or Shift+Alt+N) to open the New Web Site window. Change the default name of the site to a name of your choice (herein Chart_XMLWeb) as shown. Make sure you are creating a .NET Framework 3.5 web site as shown here. Figure 03: New Framework 3.5 Web Site Project Click on APP_Data folder in the solution explorer as shown in the next figure and click on Add Existing Item… menu item. Figure 04: Add an existing item to the web site folder In the interactive window that gets displayed browse to the location where you saved the PrincetonXMLDOC.xml file and click Add button. This will add the XML file to the ADD_Data folder of the web site project. Double click PrincetonXMLDOC.xml in the web site project folder to display and verify its contents as shown in the next figure. Only nodes 1 and 12 are shown expanded. As mentioned previously this is an XML fragment. Figure 05: Imported PrincetonXMLDOC.xml Modify this document by adding the <root/> as well as the XML processing instruction as shown in the next figure. Build the project. Figure 06: Modified PrincetonXMLDOX.xml (valid XML document)
Read more
  • 0
  • 0
  • 14701

article-image-applying-special-effects-3d-game-development-microsoft-silverlight-3-part-2
Packt
18 Nov 2009
6 min read
Save for later

Applying Special Effects in 3D Game Development with Microsoft Silverlight 3: Part 2

Packt
18 Nov 2009
6 min read
Time for action – simulating fluids with movement Your project manager is amazed with the shower of dozens of meteors in the background. However, he wants to add a more realistic background. He shows you a water simulation sample using Farseer Physics Engine. He wants you to use the wave simulation capabilities offered by this powerful physics simulator to create an asteroids belt. First, we are going to create a new class to define a fluid model capable of setting the initial parameters and updating a wave controller provided by the physics simulator. We will use Farseer Physics Engine's wave controller to add real-time fluids with movement for our games. The following code is based on the Silverlight water sample offered with the physics simulator. However, in this case, we are not interested in collision detection capabilities because we are going to create an asteroid belt in the background. Stay in the 3DInvadersSilverlight project. Create a new class—FluidModel. Replace the default using declarations with the following lines of code (we are going to use many classes and interfaces from Farseer Physics Engine): using System;using FarseerGames.FarseerPhysics;using FarseerGames.FarseerPhysics.Controllers;using FarseerGames.FarseerPhysics.Mathematics; Add the following public property to hold the WaveController instance: public WaveController WaveController { get; private set; } Add the following public properties to define the wave generator parameters: public float WaveGeneratorMax { get; set; }public float WaveGeneratorMin { get; set; }public float WaveGeneratorStep { get; set; } Add the following constructor without parameters: public FluidModel(){ // Assign the initial values for the wave generator parameters WaveGeneratorMax = 0.20f; WaveGeneratorMin = -0.15f; WaveGeneratorStep = 0.025f;} Add the Initialize method to create and configure the WaveController instance using the PhysicsSimulator instance received as a parameter: public void Initialize(PhysicsSimulator physicsSimulator){ // The wave controller controls how the waves move // It defines how big and how fast is the wave // It is represented as set of points equally spaced horizontally along the width of the wave. WaveController = new WaveController(); WaveController.Position = ConvertUnits.ToSimUnits(-20, 5); WaveController.Width = ConvertUnits.ToSimUnits(30); WaveController.Height = ConvertUnits.ToSimUnits(3); // The number of vertices that make up the surface of the wave WaveController.NodeCount = 40; // Determines how quickly the wave will dissipate WaveController.DampingCoefficient = .95f; // Establishes how fast the wave algorithm runs (in seconds) WaveController.Frequency = .16f; //The wave generator parameters simply move an end-point of the WaveController.WaveGeneratorMax = WaveGeneratorMax; WaveController.WaveGeneratorMin = WaveGeneratorMin; WaveController.WaveGeneratorStep = WaveGeneratorStep; WaveController.Initialize();} Add the Update method to update the wave controller and update the points that draw the waves shapes: public void Update(TimeSpan elapsedTime){ WaveController.Update((float) elapsedTime.TotalSeconds);} What just happened? We now have a FluidModel class that creates, configures, and updates a WaveController instance according to an associated physics simulator. As we are going to work with different gravitational forces, we are going to use another independent physics simulator to work with the FluidModel instance in our game. Simulating waves The wave controller offers many parameters to represent a set of points equally spaced horizontally along the width of one or many waves. The waves can be: Big or small Fast or slow Tall or short The wave controller's parameters allow us to determine the number of vertices that make up the surface of the wave assigning a value to its NodeCount property. In this case, we are going to create waves with 40 nodes and each point is going to be represented by an asteroid: WaveController.NodeCount = 40; The Initialize method defines the position, width, height and other parameters for the wave controller. We have to convert our position values to the simulator values. Thus, we use the ConvertUnits.ToSimUnits method. For example, this line defines the 2D Vector for the wave's upper left corner (X = -20 and Y = 5): WaveController.Position = ConvertUnits.ToSimUnits(-20, 5); The best way to understand each parameter is changing its values and running the example using these new values. Using a wave controller we can create amazing fluids with movement.   Time for action – creating a subclass for a complex asteroid belt Now, we are going to create a specialized subclass of Actor (Balder.Core.Runtime. Actor) to load, create an update a fluid with waves. This class will enable us to encapsulate an independent asteroid belt and add it to the game. In this case, it is a 3D character composed of many models (many instances of Mesh). Stay in the 3DInvadersSilverlight project. Create a new class, FluidWithWaves (a subclass of Actor) using the following declaration: public class FluidWithWaves : Actor Replace the default using declarations with the following lines of code (we are going to use many classes and interfaces from Balder, Farseer Physics Engine and lists): using System.Windows;using System.Windows.Controls;using System.Windows.Media;using System.Windows.Shapes;// BALDERusing Balder.Core;using Balder.Core.Geometries;using Balder.Core.Math;using Balder.Core.Runtime;// FARSEER PHYSICSusing FarseerGames.FarseerPhysics;using FarseerGames.FarseerPhysics.Collisions;using FarseerGames.FarseerPhysics.Dynamics;using FarseerGames.FarseerPhysics.Factories;using FarseerGames.FarseerPhysics.Mathematics;// LISTSusing System.Collections.Generic; Add the following protected variables to hold references for the RealTimeGame and the Scene instances: protected RealTimeGame _game;protected Scene _scene; Add the following private variables to hold the associated FluidModel instance, the collection of points that define the wave and the list of meshes (asteroids): private FluidModel _fluidModel;private PointCollection _points;private List<Mesh> _meshList; Add the following constructor with three parameters—the RealTimeGame, the Scene, and the PhysicsSimulator instances: public FluidWithWaves(RealTimeGame game, Scene scene, PhysicsSimulator physicsSimulator){ _game = game; _scene = scene; _fluidModel = new FluidModel(); _fluidModel.Initialize(physicsSimulator); int count = _fluidModel.WaveController.NodeCount; _points = new PointCollection(); for (int i = 0; i < count; i++) { _points.Add(new Point(ConvertUnits.ToDisplayUnits (_fluidModel.WaveController.XPosition[i]), ConvertUnits.ToDisplayUnits (_fluidModel.WaveController.CurrentWave[i]))); }} Override the LoadContent method to load the meteors' meshes and set their initial positions according to the points that define the wave: public override void LoadContent(){ base.LoadContent(); _meshList = new List<Mesh>(_points.Count); for (int i = 0; i < _points.Count; i++) { Mesh mesh = _game.ContentManager.Load<Mesh>("meteor.ase"); _meshList.Add(mesh); _scene.AddNode(mesh); mesh.Position.X = (float) _points[i].X; mesh.Position.Y = (float) _points[i].Y; mesh.Position.Z = 0; }} Override the Update method to update the fluid model and then change the meteors' positions taking into account the points that define the wave according to the elapsed time: public override void Update(){ base.Update(); // Update the fluid model with the real-time game elapsed time _fluidModel.Update(_game.ElapsedTime); _points.Clear(); for (int i = 0; i < _fluidModel.WaveController.NodeCount; i++) { Point p = new Point(ConvertUnits.ToDisplayUnits (_fluidModel.WaveController.XPosition[i]), ConvertUnits.ToDisplayUnits (_fluidModel.WaveController.CurrentWave[i]) +ConvertUnits.ToDisplayUnits (_fluidModel.WaveController.Position.Y)); _points.Add(p); }// Update the positions for the meshes that define the wave's points for (int i = 0; i < _points.Count; i++) { _meshList[i].Position.X = (float)_points[i].X; _meshList[i].Position.Y = (float)_points[i].Y; }}
Read more
  • 0
  • 0
  • 3020

article-image-unity-game-development-interactions-part-2
Packt
18 Nov 2009
14 min read
Save for later

Unity Game Development: Interactions (Part 2)

Packt
18 Nov 2009
14 min read
Opening the outpost In this section, we will look at the two differing approaches for triggering the animation giving you an overview of the two techniques that will both become useful in many other game development situations. In the first approach, we'll use collision detection—a crucial concept to get to grips with as you begin to work on games in Unity. In the second approach, we'll implement a simple ray cast forward from the player. Approach 1—Collision detection To begin writing the script that will trigger the door-opening animation and thereby grant access to the outpost, we need to consider which object to write a script for. In game development, it is often more efficient to write a single script for an object that will interact with many other objects, rather than writing many individual scripts that check for a single object. With this in mind, when writing scripts for a game such as this, we will write a script to be applied to the player character in order to check for collisions with many objects in our environment, rather than a script made for each object the player may interact with, which checks for the player. Creating new assets Before we introduce any new kind of asset into our project, it is good practice to create a folder in which we will keep assets of that type. In the Project panel, click on the Create button, and choose Folder from the drop-down menu that appears. Rename this folder Scripts by selecting it and pressing Return (Mac) or by pressing F2 (PC). Next, create a new JavaScript file within this folder simply by leaving the Scripts folder selected and clicking on the Project panel's Create button again, this time choosing JavaScript. By selecting the folder, you want a newly created asset to be in before you create them, you will not have to create and then relocate your asset, as the new asset will be made within the selected folder. Rename the newly created script from the default—NewBehaviourScript—to PlayerCollisions. JavaScript files have the file extension of .js but the Unity Project panel hides file extensions, so there is no need to attempt to add it when renaming your assets. You can also spot the file type of a script by looking at its icon in the Project panel. JavaScript files have a 'JS' written on them, C# files simply have 'C#' and Boo files have an image of a Pacman ghost, a nice little informative pun from the guys at Unity Technologies! Scripting for character collision detection To start editing the script, double-click on its icon in the Project panel to launch it in the script editor for your platform—Unitron on Mac, or Uniscite on PC. Working with OnControllerColliderHit By default, all new JavaScripts include the Update() function, and this is why you'll find it present when you open the script for the first time. Let's kick off by declaring variables we can utilise throughout the script. Our script begins with the definition of four variables, public member variables and two private variables. Their purposes are as follows: doorIsOpen: a private true/false (boolean) type variable acting as a switch for the script to check if the door is currently open. doorTimer: a private floating-point (decimal-placed) number variable, which is used as a timer so that once our door is open, the script can count a defined amount of time before self-closing the door. currentDoor: a private GameObject storing variable used to store the specific currently opened door. Should you wish to add more than one outpost to the game at a later date, then this will ensure that opening one of the doors does not open them all, which it does by remembering the most recent door hit. doorOpenTime: a floating-point (potentially decimal) numeric public member variable, which will be used to allow us to set the amount of time we wish the door to stay open in the Inspector. doorOpenSound/doorShutSound: Two public member variables of data type AudioClip, for allowing sound clip drag-and-drop assignment in the Inspector panel. Define the variables above by writing the following at the top of the PlayerCollisions script you are editing: private var doorIsOpen : boolean = false;private var doorTimer : float = 0.0;private var currentDoor : GameObject;var doorOpenTime : float = 3.0;var doorOpenSound : AudioClip;var doorShutSound : AudioClip; Next, we'll leave the Update() function briefly while we establish the collision detection function itself. Move down two lines from: function Update(){} And write in the following function: function OnControllerColliderHit(hit : ControllerColliderHit){} This establishes a new function called OnControllerColliderHit. This collision detection function is specifically for use with player characters such as ours, which use the CharacterController component. Its only parameter hit is a variable that stores information on any collision that occurs. By addressing the hit variable, we can query information on the collision, including—for starters—the specific game object our player has collided with. We will do this by adding an if statement to our function. So within the function's braces, add the following if statement: function OnControllerColliderHit(hit: ControllerColliderHit){ if(hit.gameObject.tag == "outpostDoor" && doorIsOpen == false){ }} In this if statement, we are checking two conditions, firstly that the object we hit is tagged with the tag outpostDoor and secondly that the variable doorOpen is currently set to false. Remember here that two equals symbols (==) are used as a comparative, and the two ampersand symbols (&&) simply say 'and also'. The end result means that if we hit the door's collider that we have tagged and if we have not already opened the door, then it may carry out a set of instructions. We have utilized the dot syntax to address the object we are checking for collisions with by narrowing down from hit (our variable storing information on collisions) to gameObject (the object hit) to the tag on that object. If this if statement is valid, then we need to carry out a set of instructions to open the door. This will involve playing a sound, playing one of the animation clips on the model, and setting our boolean variable doorOpen to true. As we are to call multiple instructions—and may need to call these instructions as a result of a different condition later when we implement the ray casting approach—we will place them into our own custom function called OpenDoor. We will write this function shortly, but first, we'll call the function in the if statement we have, by adding: OpenDoor(); So your full collision function should now look like this: function OnControllerColliderHit(hit: ControllerColliderHit){ if(hit.gameObject.tag == "outpostDoor" && doorIsOpen == false){ OpenDoor(); }} Writing custom functions Storing sets of instructions you may wish to call at any time should be done by writing your own functions. Instead of having to write out a set of instructions or "commands" many times within a script, writing your own functions containing the instructions means that you can simply call that function at any time to run that set of instructions again. This also makes tracking mistakes in code—known as Debugging—a lot simpler, as there are fewer places to check for errors. In our collision detection function, we have written a call to a function named OpenDoor. The brackets after OpenDoor are used to store parameters we may wish to send to the function—using a function's brackets, you may set additional behavior to pass to the instructions inside the function. We'll take a look at this in more depth later in this article under the heading Function Efficiency. Our brackets are empty here, as we do not wish to pass any behavior to the function yet. Declaring the function To write the function we need to call, we simply begin by writing: function OpenDoor(){} In between the braces of the function, much in the same way as the instructions of an if statement, we place any instructions to be carried out when this function is called. Playing audio Our first instruction is to play the audio clip assigned to the variable called doorOpenSound. To do this, add the following line to your function by placing it within the curly braces after { "and before" }: audio.PlayOneShot(doorOpenSound); To be certain, it should look like this: function OpenDoor(){ audio.PlayOneShot(doorOpenSound);} Here we are addressing the Audio Source component attached to the game object this script is applied to (our player character object, First Person Controller), and as such, we'll need to ensure later that we have this component attached; otherwise, this command will cause an error. Addressing the audio source using the term audio gives us access to four functions, Play(), Stop(), Pause(), and PlayOneShot(). We are using PlayOneShot because it is the best way to play a single instance of a sound, as opposed to playing a sound and then switching clips, which would be more appropriate for continuous music than sound effects. In the brackets of the PlayOneShot command, we pass the variable doorOpenSound, which will cause whatever sound file is assigned to that variable in the Inspector to play. We will download and assign this and the clip for closing the door after writing the script. Checking door status One condition of our if statement within our collision detection function was that our boolean variable doorIsOpen must be set to false. As a result, the second command inside our OpenDoor() function is to set this variable to true. This is because the player character may collide with the door several times when bumping into it, and without this boolean, they could potentially trigger the OpenDoor() function many times, causing sound and animation to recur and restart with each collision. By adding in a variable that when false allows the OpenDoor() function to run and then disallows it by setting the doorIsOpen variable to true immediately, any further collisions will not re-trigger the OpenDoor() function. Add the line: doorOpen = true; to your OpenDoor() function now by placing it between the curly braces after the previous command you just added. Playing animation We have already imported the outpost asset package and looked at various settings on the asset before introducing it to the game in this article. One of the tasks performed in the import process was the setting up of animation clips using the Inspector. By selecting the asset in the Project panel, we specified in the Inspector that it would feature three clips: idle (a 'do nothing' state) dooropen doorshut In our openDoor() function, we'll call upon a named clip using a String of text to refer to it. However, first we'll need to state which object in our scene contains the animation we wish to play. Because the script we are writing is to be attached to the player, we must refer to another object before referring to the animation component. We do this by stating the line: var myOutpost : GameObject = GameObject.Find("outpost"); Here we are declaring a new variable called myOutpost by setting its type to be a GameObject and then selecting a game object with the name outpost by using GameObject.Find. The Find command selects an object in the current scene by its name in the Hierarchy and can be used as an alternative to using tags. Now that we have a variable representing our outpost game object, we can use this variable with dot syntax to call animation attached to it by stating: myOutpost.animation.Play("dooropen"); This simply finds the animation component attached to the outpost object and plays the animation called dooropen. The play() command can be passed any string of text characters, but this will only work if the animation clips have been set up on the object in question. Your finished OpenDoor() custom function should now look like this: function OpenDoor(){ audio.PlayOneShot(doorOpenSound); doorIsOpen = true; var myOutpost : GameObject = GameObject.Find("outpost"); myOutpost.animation.Play("dooropen");} Reversing the procedure Now that we have created a set of instructions that will open the door, how will we close it once it is open? To aid playability, we will not force the player to actively close the door but instead establish some code that will cause it to shut after a defined time period. This is where our doorTimer variable comes into play. We will begin counting as soon as the door becomes open by adding a value of time to this variable, and then check when this variable has reached a particular value by using an if statement. Because we will be dealing with time, we need to utilize a function that will constantly update such as the Update() function we had awaiting us when we created the script earlier. Create some empty lines inside the Update() function by moving its closing curly brace } a few lines down. Firstly, we should check if the door has been opened, as there is no point in incrementing our timer variable if the door is not currently open. Write in the following if statement to increment the timer variable with time if the doorIsOpen variable is set to true: if(doorIsOpen){ doorTimer += Time.deltaTime;} Here we check if the door is open — this is a variable that by default is set to false, and will only become true as a result of a collision between the player object and the door. If the doorIsOpen variable is true, then we add the value of Time.deltaTime to the doorTimer variable. Bear in mind that simply writing the variable name as we have done in our if statement's condition is the same as writing doorIsOpen == true. Time.deltaTime is a Time class that will run independent of the game's frame rate. This is important because your game may be run on varying hardware when deployed, and it would be odd if time slowed down on slower computers and was faster when better computers ran it. As a result, when adding time, we can use Time.deltaTime to calculate the time taken to complete the last frame and with this information, we can automatically correct real-time counting. Next, we need to check whether our timer variable, doorTimer, has reached a certain value, which means that a certain amount of time has passed. We will do this by nesting an if statement inside the one we just added—this will mean that the if statement we are about to add will only be checked if the doorIsOpen if condition is valid. Add the following code below the time incrementing line inside the existing if statement: if(doorTimer > doorOpenTime){shutDoor();doorTimer = 0.0;} This addition to our code will be constantly checked as soon as the doorIsOpen variable becomes true and waits until the value of doorTimer exceeds the value of the doorOpenTime variable, which, because we are using Time.deltaTime as an incremental value, will mean three real-time seconds have passed. This is of course unless you change the value of this variable from its default of 3 in the Inspector. Once the doorTimer has exceeded a value of 3, a function called shutDoor() is called, and the doorTimer variable is reset to zero so that it can be used again the next time the door is triggered. If this is not included, then the doorTimer will get stuck above a value of 3, and as soon as the door was opened it would close as a result. Your completed Update() function should now look like this: function Update(){ if(doorIsOpen){ doorTimer += Time.deltaTime; if(doorTimer > 3){ shutDoor(); doorTimer = 0.0; } }} Now, add the following function called shutDoor() to the bottom of your script. Because it performs largely the same function as openDoor(), we will not discuss it in depth. Simply observe that a different animation is called on the outpost and that our doorIsOpen variable gets reset to false so that the entire procedure may start over: function shutDoor(){audio.PlayOneShot(doorShutSound);doorIsOpen = false;var myOutpost : GameObject = GameObject.Find("outpost");myOutpost.animation.Play("doorshut");}
Read more
  • 0
  • 0
  • 3019
article-image-restful-java-web-services-design
Packt
18 Nov 2009
5 min read
Save for later

RESTful Java Web Services Design

Packt
18 Nov 2009
5 min read
We'll leave the RESTful implementation for a later article. Our sample application is a micro-blogging web service (similar to Twitter), where users create accounts and then post entries. Finally, while designing our application, we'll define a set of steps that can be applied to designing any software system that needs to be deployed as a RESTful web service. Designing a RESTful web service Designing RESTful web services is not different from designing traditional web applications. We still have business requirements, we still have users who want to do things with data, and we still have hardware constraints and software architectures to deal with. The main difference, however, is that we look at the requirements to tease out resources and forget about specific actions to be taken on these resources. We can think of RESTful web service design as being similar to Object Oriented Design (OOD). In OOD, we try to identify objects from the data we want to represent together with the actions that an object can have. But the similarities end at the data structure definition, because with RESTful web services we already have specific calls that are part of the protocol itself. The underlying RESTful web service design principles can be summarized in the following four steps: Requirements gathering—this step is similar to traditional software requirement gathering practices. Resource identification—this step is similar to OOD where we identify objects, but we don't worry about messaging between objects. Resource representation definition—because we exchange representation between clients and servers, we should define what kind of representation we need to use. Typically, we use XML, but JSON has gained popularity. That's not to say that we can't use any other form of resource representation—on the contrary, we could use XHTML or any other form of binary representation, though we let the requirements guide our choices. URI definition—with resources in place, we need to define the API, which consists of URIs for clients and servers to exchange resources' representations. This design process is not static. These are iterative steps that gravitate around   resources. Let's say that during the URI definition step we discover that one of the URI's responses is not covered in one of the resources we have identified. Then we go back to define a suitable resource. In most cases, however, we find that the resources that we already have cover most of our needs, and we just have to combine existing resources into a meta-resource to take care of the new requirement. Requirements of sample web service The RESTful web service we design in this article is a social networking web application similar to Twitter. We follow an OOD process mixed with an agile philosophy for designing and coding our applications. This means that we create just enough documentation to be useful, but not so much that we spend an inordinate amount of time deciphering it during our implementation phase. As with any application, we begin by listing the main business requirements, for which we have the following use cases (these are the main functions of our application): A web user creates an account with a username and a password (creating an account means that the user is now registered). Registered users post blog entries to their accounts. We limit messages to 140 characters. Registered and non-registered users view all blog entries. Registered and non-registered users view user profiles. Registered users update their user profiles, for example, users update their password. Registered and non-registered users search for terms in all blog entries. However simple this example may be, social networking sites work on these same principles: users sign up for accounts to post personal updates or information. Our intention here, though, is not to fully replicate Twitter or to fully create a social networking application. What we are trying to outline is a set of requirements that will test our understanding of RESTful web services design and implementation. The core value of social networking sites lies in the ability to connect to multiple users who connect with us, and the value is derived from what the connections mean within the community, because of the tendency of users following people with similar interests. For example, the connections between users create targeted distribution networks.The connections between users create random graphs in the graph theory sense, where nodes are users and edges are connections between users. This is what is referred to as the social graph. Resource identification Out of the use cases listed above, we now need to define the service's resources. From reading the requirements we see that we need users and messages. Users appear in two ways: a single user and a list of users. Additionally, users have the ability to post blog entries in the form of messages of no more than 140 characters. This means that we need resources for a single message and a list of messages. In sum, we identify the following resources: User List of users Message List of messages
Read more
  • 0
  • 0
  • 11057

article-image-unity-game-development-interactions-part-1
Packt
18 Nov 2009
8 min read
Save for later

Unity Game Development: Interactions (Part 1)

Packt
18 Nov 2009
8 min read
To detect physical interactions between game objects, the most common method is to use a Collider component—an invisible net that surrounds an object's shape and is in charge of detecting collisions with other objects. The act of detecting and retrieving information from these collisions is known as collision detection. Not only can we detect when two colliders interact, but we can also pre-empt a collision and perform many other useful tasks by utilizing a technique called Ray Casting, which draws a Ray—put simply, an invisible (non-rendered) vector line between two points in 3D space—which can also be used to detect an intersection with a game object's collider. Ray casting can also be used to retrieve lots of other useful information such as the length of the ray (therefore—distance), and the point of impact of the end of the line. In the given example, a ray facing the forward direction from our character is demonstrated. In addition to the direction, a ray can also be given a specific length, or allowed to cast until it finds an object. Over the course of the article, we will work with the outpost model. Because this asset has been animated for us, the animation of the outpost's door opening and closing is ready to be triggered—once the model is placed into our scene. This can be done with either collision detection or ray casting, and we will explore what you will need to do to implement either approach. Let's begin by looking at collision detection and when it may be appropriate to use ray casting instead of, or in complement to, collision detection. Exploring collisions When objects collide in any game engine, information about the collision event becomes available. By recording a variety of information upon the moment of impact, the game engine can respond in a realistic manner. For example, in a game involving physics, if an object falls to the ground from a height, then the engine needs to know which part of the object hit the ground first. With that information, it can correctly and realistically control the object's reaction to the impact. Of course, Unity handles these kinds of collisions and stores the information on your behalf, and you only have to retrieve it in order to do something with it. In the example of opening a door, we would need to detect collisions between the player character's collider and a collider on or near the door. It would make little sense to detect collisions elsewhere, as we would likely need to trigger the animation of the door when the player is near enough to walk through it, or to expect it to open for them. As a result, we would check for collisions between the player character's collider and the door's collider. However, we would need to extend the depth of the door's collider so that the player character's collider did not need to be pressed up against the door in order to trigger a collision, as shown in the following illustration. However, the problem with extending the depth of the collider is that the game interaction with it becomes unrealistic. In the example of our door, the extended collider protruding from the visual surface of the door would mean that we would bump into an invisible surface which would cause our character to stop in their tracks, and although we would use this collision to trigger the opening of the door through animation, the initial bump into the extended collider would seem unnatural to the player and thus detract from their immersion in the game. So while collision detection will work perfectly well between the player character collider and the door collider, there are drawbacks that call for us as creative game developers to look for a more intuitive approach, and this is where ray casting comes in. Ray casting While we can detect collisions between the player character's collider and a collider that fits the door object, a more appropriate method may be to check for when the player character is facing the door we are expecting to open and is within a certain distance of this door. This can be done by casting a ray forward from the player's forward direction and restricting its length. This means that when approaching the door, the player needn't walk right up to it—or bump into an extended collider—in order for it to be detected. It also ensures that the player cannot walk up to the door facing away from it and still open it—with ray casting they must be facing the door in order to use it, which makes sense. In common usage, ray casting is done where collision detection is simply too imprecise to respond correctly. For example, reactions that need to occur with a frame-by-frame level of detail may occur too quickly for a collision to take place. In this instance, we need to preemptively detect whether a collision is likely to occur rather than the collision itself. Let's look at a practical example of this problem. The frame miss In the example of a gun in a 3D shooter game, ray casting is used to predict the impact of a gunshot when a gun is fired. Because of the speed of an actual bullet, simulating the flight path of a bullet heading toward a target is very difficult to visually represent in a way that would satisfy and make sense to the player. This is down to the frame-based nature of the way in which games are rendered. If you consider that when a real gun is fired, it takes a tiny amount of time to reach its target—and as far as an observer is concerned it could be said to happen instantly—we can assume that even when rendering over 25 frames of our game per second, the bullet would need to have reached its target within only a few frames. In the example above, a bullet is fired from a gun. In order to make the bullet realistic, it will have to move at a speed of 500 feet per second. If the frame rate is 25 frames per second, then the bullet moves at 20 feet per frame. The problem with this is a person is about 2 feet in diameter, which means that the bullet will very likely miss the enemies shown at 5 and 25 feet away that would be hit. This is where prediction comes into play. Predictive collision detection Instead of checking for a collision with an actual bullet object, we find out whether a fired bullet will hit its target. By casting a ray forward from the gun object (thus using its forward direction) on the same frame that the player presses the fire button, we can immediately check which objects intersect the ray. We can do this because rays are drawn immediately. Think of them like a laser pointer—when you switch on the laser, we do not see the light moving forward because it travels at the speed of light—to us it simply appears. Rays work in the same way, so that whenever the player in a ray-based shooting game presses fire, they draw a ray in the direction that they are aiming. With this ray, they can retrieve information on the collider that is hit. Moreover, by identifying the collider, the game object itself can be addressed and scripted to behave accordingly. Even detailed information, such as the point of impact, can be returned and used to affect the resultant reaction, for example, causing the enemy to recoil in a particular direction. In our shooting game example, we would likely invoke scripting to kill or physically repel the enemy whose collider the ray hits, and as a result of the immediacy of rays, we can do this on the frame after the ray collides with, or intersects the enemy collider. This gives the effect of a real gunshot because the reaction is registered immediately. It is also worth noting that shooting games often use the otherwise invisible rays to render brief visible lines to help with aim and give the player visual feedback, but do not confuse these lines with ray casts because the rays are simply used as a path for line rendering. Adding the outpost Before we begin to use both collision detection and ray casting to open the door of our outpost, we'll need to introduce it to the scene. To begin, drag the outpost model from the Project panel to the Scene view and drop it anywhere—bear in mind you cannot position it when you drag-and-drop; this is done once you have dropped the model (that is, let go off the mouse). Once the outpost is in the Scene, you'll notice its name has also appeared in the Hierarchy panel and that it has automatically become selected. Now you're ready to position and scale it!  
Read more
  • 0
  • 0
  • 3522
Modal Close icon
Modal Close icon