Wednesday, October 27, 2010

iPhone application development and outsourcing

The complete potential of iPhone, the multimedia gadget, can be utilized by developing ingenious applications for it. The launch of the SDK (software development kit) by Apple in 2008 boosted iPhone application developer worldwide to come up with unique and customized applications for iPhone users.

The SDK, also known as the ‘tool chain’ includes:

Xcode: It is the integrated development environment (IDE), wherein iPhone applications are developed. It is the integral part of the iPhone application development kit and consists of a graphical debugger and a powerful source editor too. Interface builder: It helps in the designing and testing of user interfaces. The graphical editing environment of the interface builder is utilized by the iPhone application developer to design user interfaces and seamlessly integrate the applications to the 3G environment of iPhone. Instruments: The instrument retrieves data, analyzes and compares performance and displays the results graphically in real-time. It plays a pivotal role in the real-time optimization of iPhone applications.

An iPhone application developer should have a sound knowledge about using the SDK. The SDK uses the objective C language and runs only on the MAC OS X 1.5 platform (the OS of iPhone). The applications developed needs to be approved by Apple and can be distributed solely through App Store.

iPhone website development

There are various categories catering to which, iPhone applications are developed. Many companies specialize in a particular category. For example, a company may specialize in the domain of iPhone website development. An iPhone mobile development domain includes useful web 2.0 applications designed exclusively for iPhone, like:

Search tools. Web utilities. Social networking. Ecommerce websites. Travel, sports and entertainment and so on.

Outsourcing of iPhone application development

Outsource of iPhone application development has several advantages which mainly includes:

Firstly, it is cost effective. Outsourcing of IPhone applications gets the job done in lower costs. Customized applications can be developed without much investment which was otherwise necessary for the technical manpower and training. The rigmaroles of the iPhone applications- approval by Apple, guidelines etc are taken care by the companies.

iPhone Cool Projects

41gNRqHs6qL. SL160 iPhone application development and outsourcing

I am the webmaster at www.synapse.co.in – a iPhone website development company in India offering numerous services, such as flash web development, flash scripting, customized applications for the iPhone,and website maintenance services

ISBN13: 9781430223573
Condition: USED – Very Good

Notes: BUY WITH CONFIDENCE, Over one million books sold! 98% Positive feedback. Compare our books, prices and service to the competition. 100% Satisfaction Guaranteed

The iPhone and iPod touch have provided all software developers with a level playing field—developers working alone have the same access to consumers as multinational software publishers. Very cool indeed! To make your application stand out from the crowd, though, it has to have that something extra. You must learn the skills to take your apps from being App Store filler to download chart-topping blockbusters.

Developers with years of experience helped write this book. Spend some time understanding their code and why they took the approach they did. You will find the writing, illustrations, code, and sample applications second to none. No matter what type of application you are writing, you will find something in this book to help you make your app that little bit cooler.

The book opens with Wolfgang Ante, the developer behind the Frenzic puzzle game, showing how timers, animation, and intelligence are used to make game play engaging. It moves on to Rogue Amoeba’s Mike Ash explaining how to design a network protocol using UDP, and demonstrating its use in a peer-to-peer application—a topic not normally for the faint of heart, but explained here in a way that makes sense to mere mortals. Gary Bennett then covers the important task of multithreading. Multithreading can be used to keep the user interface responsive while working on other tasks in the background. Gary demonstrates how to do this and highlights traps to avoid along the way.

Next up, Canis Lupus (aka Matthew Rosenfeld) describes the development of the Keynote-controlling application Stage Hand, how the user interface has evolved, and the lessons he has learned from that experience. Benjamin Jackson then introduces two open source libraries: cocos2d, for 2D gaming; and Chipmunk, for rigid body physics (think “collisions”). He describes the development of Arcade Hockey, an air hockey game, and explains some of the code used for this.

Neil Mix of Pandora Radio reveals the science behind processing streaming audio. How do you debug what you can’t see? Neil guides you through the toughest challenges, sharing his experience of what works and what to watch out for when working with audio. Finally, Steven Peterson demonstrates a comprehensive integration of iPhone technologies. He weaves Core Location, networking, XML, XPath, and SQLite into a solid and very useful application.

Software development can be hard work. Introductory books lay the foundation, but it can be challenging to understand where to go next. This book shows some of the pieces that can be brought together to make complete, cool applications.



You can find original post here : http://www.theoutsourceblog.com/2010/08/iphone-application-development-and-outsourcing/

Virus Cleaning and Prevention in osCommerce

What virus do?
In an osCommerce site a virus malware do the following:
- Create a form ask unnecessary to fill confidential data like order
detail or paypal detail. Once someone fills these details, those details
will be emailed to third party for misused.
- Creating link of website for creating traffic for those link.
- Using redirector for redirecting the customer to other site.
- Using iframe to display some unauthorized detail with a link to wesite.
So basically there are two objectives
- Steal data.
- Divert traffic to another website.

Different ways in which hackings are achieved.
1) SQL injection
2) Modify .htaccess and writing the error 404 rules or rewrite rules.
3) Place some javascript.
4) Placing .php or other files to execute and modify other files.

How to make out what is wrong?
Downloade all the code and check for,
- External links.
- javascript code having eval in it.
- check your .htaccess file.
- checking image folder and other folder.
- check permission is 777 or writing permission.
- use some scanning references to check for valueval pass and
analyze code.
- check your error log.
- check your access log.

Preventions:

Prevention basically includes three things.
• Your site itself
• Password of software used to upload content on site.
• And your Computer from where content is being upload.

How does one protect its site?
- Ensuring that all third party scripts or tools used on site should have
latest security updates or should be asked to hosting company to do
so.
- Delete unwanted folders, files, scripts and services those are no
more in use.
- Occasionally change the password of the software used to upload
content to the site.
Use strong password.
- Appropriate file permissions to be given.
- Disable file manager from admin.
- Site admin should be password (.htaccess) protected.
- Keep the computer used for site’s upload and download activities
should be up-to-date with all necessary operating system updates
and a strong antivirus with all latest updates.

Recommendations:
- It is always recommended, not to keep a soft copy of site
access details on computer.
- A regular code and database backup should be taken.
- There is few security add-ons are available in osCommerce that
should be installed on the site.




You can find original post here : http://www.oscprofessionals.com/blog/

Configuring a mobile Drupal site and making your theme mobile friendly

In this tutorial I'll explain how to setup your Drupal site to be mobile friendly. Before you begin, it's helpful to consider the following: 1) which mobile devices to support; 2) using a different theme for mobile; 3) which hostnames will be used; 4) multi-site configuration options; and 5) any site alterations to simplify the mobile experience.

For my site, I decided on the following:
1) iPhones (to start)
2) Use a more clean theme for my mobile site: DevSeed's Singular
3) redirect mobile traffic to a new subdomain (mobile.thedrupalblog.com)
4) I was using sites/default for my blog, so hosting another hostname on the same filesystem was not an issue
5) I decided to remove some items in my primary navigation, and add some jQuery (accordion effect) to collapse node content on my front page.


I added the new DNS for my subdomain to point to the same IP address of my main site. In a standard Apache vhosts configuration, you can add a ServerAlias directive to ensure the mobile hostname is handled by the main site's vhost. For example:


ServerName thedrupalblog.com
ServerAlias mobile.thedrupalblog.com
DocumentRoot /var/www/vhosts/thedrupalblog.com/httpdocs


I installed and enabled the Singular theme in sites/all/theme/singular.

I added some mobile specific configurations in my settings.php file (sites/default/settings.php):



Now, if someone visits my site using an iPhone, the user would be redirected to my specified mobile address, AND a new mobile theme would be used!



In addition, I decided to make some alterations to my mobile theme to simplify the interface. I created a module and added a hook_preprocess_page() implementation:

$value) {
if (in_array(strtolower($value['href']), $href_remove)) {
unset($vars['primary_links'][$key]);
}
}
}

}
?>


By added the above module code and jQuery, I removed some items from my primary navigation and added an accordion-like interface for the front page:



NOTE: If you're using a Mac, the iPhone Simulator application (which comes with Xcode + iPhone SDK) is a great way to development and test mobile configurations.


You can find original post here : http://thedrupalblog.com/

Controlling Joomla! templates depending on menu you use

We have been working on building a multi-school Joomla! website and there have been many hurdles to overcome since Joomla! isn’t a multi-site CMS. After searching for anything that’s common across each school, I realized the menu for each school could be used as a common denominator. If I could set a variable depending on which menu is loaded on the page then I can do just about anything I want, such as change the logo, set a unique CSS class, etc. After meeting with our developers we figured out how to do this and I’ll share it with all of you in case you ever need to do the same.

To start we need to pull in the information of which menus are being used on the page. Place this code in the head of your template:

jimport('joomla.application.menu');
$menus = JSite::getMenu();
$m = $menus->getActive();


This checks for the active menus on the page and sets it into the variable $m so we can manipulate it. Next, you need to look at the menutype in the administrator Menu Manager (under Type). This is what we will use to determine which school is being viewed. I want to take this information and set a new variable named $school:

if($m->menutype == 'district-information') { $school = 'district-info'; }
if($m->menutype == 'cityname-elementary-school') { $school = 'cityname-elementary'; }
if($m->menutype == 'cityname-middle-school') { $school = 'cityname-middle'; }
if($m->menutype == 'cityname-high-school') { $school = 'cityname-high'; }


The first thing I did was echo the variable $school into an ID on the body tag.

body id="< ?php echo $school; ?>"

This allows me to style the CSS uniquely according to the school being viewed which gives you a lot of style control. To change the logo I can just call it by the school.

#cityname-high .logo {background: url(../images/logo-highschool.jpg);}

Another thing I did was load a unique module position according to the school so I could publish modules in all pages the menu shows up on. I did this by doing the following:

if($school == 'district-info') {
echo '';
};
if($school == 'cityname-elementary') {
echo '';
};
if($school == 'cityname-middle') {
echo '';
};
if($school == 'cityname-high') {
echo '';
};


As you can see this can give you the ability to do things you may not have been able to do before in Joomla!. I know it saved me from a major headache!




You can find original post here : http://www.corephp.com/blog/controlling-joomla-templates-depending-on-the-menu-you-use/

Tuesday, October 26, 2010

Reverse engineering an "encrypted" Joomla! plugin

On extensions.joomla.org a lot of extensions are offered worthwhile using. Most of them are released under the GNU/GPL and free to use, others are offered under a commercial license - I don't have a problem with this, because for me the functionality is more important than the amount of money I have to pay.

Open source or not

But one thing which I find very important is the openess of the PHP-code. If an extension is GPL-ed, the code is open source which enables me as programmer to fix problems myself instead of relying on other people to fix it for me. It allows me to solve problems much quicker.

With commercial extensions however there are two variations: Extensions which are both commercial as open source and extensions which are both commercial as closed source. I prefer the open source extensions, but sometimes you're just stuck with closed source because of the functionality it sometimes offers. I always cross my fingers and hope that I don't bump into a problem that makes me call some helpdesk-guy that doesn't understand a bit of the problem.
The website is down

Now something happened which made me reconsider my point on closed source extensions (for the worse): The website was down. I have full access to the webserver, so I logged in through SSH to have a look at the Apache error-log. There I quickly discovered the problem. Some kind of Joomla! plugin gave a huge timeout.

The Joomla! plugin in question was a system plugin and depended on a helper-file. Somehow this helper-file tried to reach another remote site. And because this other remote site was down as well, the Joomla! plugin was waiting indefinitely for a response and so did my website. No timeout was being given.

I quickly logged into the Joomla! Administrator, navigated to the Plugin Manager and disabled the plugin. Hmm, the website was still down. Appearently disabling the plugin from within the Joomla! backend did not actually disable the plugin itself. With a steady hand I removed the plugin-files. The website was up again.

Next, I deciced to do a full audit on this plugin. What was causing the problem? And more importantly, why did it not give a timeout when trying to reach the remote site - for a proper PHP-script it seemed to be the most responsible thing to do.
A first glance at the evil Joomla! plugin

At a first glance the plugin looked very cool. The backend did not have any parameters, it showed an HTML description which was displayed just as plain text and not as HTML, and the plugin title did not follow the plugin naming conventions ("System - My Plugin"). But sometimes I'm just too picky about these things. Instead of becoming to frustrated I had a look at the code instead.

The main PHP-script is written following the JPlugin-class standard, which is a clear way of writing your own plugin. However the main file included a helper file, even when the plugin itself was disabled. That was a big mistake: The helper tried to fetch content from a remote site, which was down. But it tried to do this, regardless of the state of the plugin. If the plugin would be disabled, there was no need for this action anyway.

...
include_once( dirname( __FILE__ ) . '/evil.helper.php' );
...
class plgSystemEvilplugin extends JPlugin
...


License and reverse engineering

The Joomla! plugin was mentioning (in the source code) a copyright but not a license. On the website I could not find any word of the license under which the source code was distributed. Now, Joomla! is released under the GNU/GPL and officially all extensions that extend Joomla! should fall under the GPL as well, and thus make it open source. I took the liberty to assume that the GPL was applied to this plugin as well and began reading the code.

The main plugin-file did not do much, except include a helper-file and call a function within this helper-file. So I opened up the helper-file to discover that it did not contain readable code but something encrypted instead. Looking at the GPL it is absolutely legal to decrypt this encrypted code, so I started decoding it.

BFkWUEZsfUtbXj9YS1gqIC47dzdzUBpQLQlaBQ9KUxgPA1g4XBZdGxwHUzZXVBYyFl1LZ
wkRSRlHDgddQx8KHQEODRUNGA4dXwRXBgBDGR9jF10UcgATSRxaVR1HS11BAVphQh0Wa2
lfFhgKHzxEAB0cTw0aBgMKFg1vHxYLHxcSRlxHTgBUEAJjQhocGgA7BFQCR1IKRwAH


Decrypting the base64 file

The file was encoded with base64 encryption, and any PHP-programmer should know that there is a PHP-function "base64_decode()" to help you with this. The difficult part was that after base64-decryption I ended up with again a base64 encryption. So again I decrypted it, but now I ended up with a base64-encryption locked with a specific encoding key.

$codelock_decrypter["t"] = base64_decode("LlJpagxUIiZLXmc3Ijk5PzUaMCM
pKStbKikEHm48W0FZISlwKSQiVz8jLidnTz8jXxdqGExfWTExNTg+NF4MdzstNRRtHUFe
LSJWTl0NYSYrOWY ...
...
$codelock_decrypter["z"] = substr($codelock_decrypter["license"], $codelock_decrypter["x"] % strlen($codelock_decrypter["license"]), 1);


This CodeLock-encryption is however not impossible to crack. Still this is not real closed source like ionCube or Zend Encryptor - it just takes some good knowledge of PHP to turn the base64-encryption into regular PHP-code. After 15 minutes of good hacking I succeeded in breaking the full encryption and store the PHP-code as a readable content.

There I found the root of the whole problem: The PHP-scripts themselves did not contain any logic by themselves. Instead the PHP-script was encrypted with CodeLock but still able to decrypt itself. After this a request was made to the remote site to get again encryted text which was then decrypted and then executed as PHP. And what was all the fuzz about? About 400 lines of code that I could write easily in one evening.
So what's bad about this Joomla! plugin

Though the functionality of the plugin was very useful, the downtime of the remote site brought a very weak architecture into the light. This is the list:

* The plugin is not clear on the license needed to redistribute the PHP-code. I assumed the code to be GPL, which is probably legally the right assumption.
* The plugin called a helper-file even when the plugin was disabled, which shows that the manufacturor did not actually test things properly.
* The code is encrypted with encryption software written in a manner, which I have seen only with script-kiddies. It contained PHP Notices and even PHP Warnings which were manually oppressed, which is a bad habit.
* The whole functionality depends fully on a remote site. If this site is down, the plugin doesn't work.
* They ask money for this type of software.


How could you know?

You don't, unless you are an experienced PHP-programmer like me. It takes a lot of knowledge to find out what an extension is doing exactly and things get even more complicated with things like base64-encryption. But you can now for sure that with closed source less people are making sure that the PHP-code is of a high quality.


You can find the original post here : http://blog.opensourcenetwork.eu/blog/programming/reverse-engineering-an-qencryptedq-joomla-plugin

Setting up a symfony project with PHPUnit on Hudson

We are using Hudson now for several months as Continous Integration System. This short article describes how we have configured a hudson project for a symfony 1.4 project. I am assuming that the reader is already used to Hudson and knows how a normal project has to be configured.

PHPUnit is the test framework of our choice (surprise, surprise) and we are using the sfPHPUnit2Plugin for all our projects. If you do not now this plugin you may first read another post where the usage and features are described in detail.

All requirements in short:

* Hudson has to be installed
* Hudson plugin xUnit Plugin has to be installed
* the symfony project needs the sfPHPUnit2Plugin
* PHPUnit has to be installed on your test server


Ok, here the configuration steps of the hudson project:

1. Configure your project

Configure standard settings for a hudson project like source-code management settings or email notifications. Please check the official docs if you do not know how to handle this.

2. Add a shell build step


Building a symfony project in a test environment is pretty easy. With the help of some shell commands the project is completely configured and ready for testing. Those shell commands may be entered in the build step section of the hudson project. Defining the correct commands is the main part during the configuration process.

Our configuration looks like this:

1. cd $WORKSPACE/trunk
2. sh _deployment/install_test.sh
3. php symfony cc
4. php symfony phpunit:test-all --configuration --options="--log-
5. junit=build/testresult_$BUILD_NUMBER.xml" cd build
6. ln -s -f testresult_$BUILD_NUMBER.xml currentTestResult.xml

1. Jump in the project root of the project
2. Install the project on the test server with the help of a internal shell script. This step includes for example the generation of the databases.yml.
3. Clear the symfony cache (always a good choice)
4. Run all PHPUnit tests including unit and functional tests. The test result is written in a jUnit compatible logfile (needed for the xUnit Plugin).
5. Jump in the build directory, which is internally used by Hudson
6. Symlink the latest testresult

3. Configure Post-Build-Action

After the xUnit Plugin is installed correctly, an additional PHPUnit Pattern field should be displayed in the post build action section. In this field has to be entered:

1 trunk/build/currentTestResult.xml

The options “Fail the build if test results were not updated this run” and “Delete temporary JUnit file” should be both checked.

The xUnit Plugin takes the currentTestResult.xml file, which was previously created with the help of the sfPHPUnit2Plugin and analyzes it. When everything works fine, you should be able to review the created test reports.

Here some screenshots how this result could look like.

Build history:


Trend graph of the test results:




You can find the original post here : http://dev.esl.eu/blog/category/symfony/

Symfony Tutorials: Using sfValidatorCallback

Many times when you're validating forms in symfony you need to do more than what the standard validators allow, and since you're lazy you don't feel like creating your own custom validator. sfValidatorCallback to the rescue!

sfValidatorCallback allows you to define your own validation function to be used for a given form field. It also allows you to scrub the data in any way you see fit. We'll look at both uses.
A Psudo-example

Since you can use the callback validator for literally anything you want, here's a simple example of how to use a function in your model to validate a field on the form for that model object

In MyObjectForm.class.php:

1.public function configure() {
2. ...
3. $this->widgetSchema['some_text_field'] =
4. new sfWidgetFormTextArea(array('required'=>false));
5.
6. $this->validatorSchema['some_text_field'] = new sfValidatorCallback(
7. array('callback'=>
8. array($this->getObject(), 'someTextFieldValidatorHook')
9. )
10. );
11. ...
12. }


Here we see that we're setting the validator for some_text_field to our call back. The first parameter to the callback takes our options. For these we need to pass a callback, which takes the same parameters as PHP's call_user_func. Since we want to call a method in our base model object, we'll use an array as the first parameter to pass our object and the method we want to call. $this->getObject(); returns the model object of the form, and someTextFieldValidatorHook is what we want to call.

So, in MyObject.php, in your model folder:

1. public function someTextFieldValidatorhook($validator, $value) {
2.
3. //test $value, set $pass if its ok
4.
5. if($pass) {
6. return $value;
7. }
8.
9. else {
10.
11. $message = "I can write whatever I want here based on the results ".
12. "of my test. The point is that this field didn't validate though";
13.
14. throw new sfValidatorError($validator, $message);
15.
16. }
17.
18. }


We can see here that the magic is throwing the exception when your test fails. The exception bubbles up and is caught by the form stuff on a higher level to render the error message to the user as you would expect.

Now, there are are a few things to keep in mind:

* sfValidatorError can take a message code and error messages as its second and third parameters. However, most of the time you use the call back, you'll want to generate the error message internally, since its dependant on the test you just wrote. Still, remember that you can respond with canned error messages if you want.
* Your data hasn't been saved yet, so you really have no notion of what the other fields are unless you grab the request object and look at them.
* You can make your validation method static if you want, but sometimes its helpful to have the old values of your current object, or you may have expanded your model object to do things beyond the standard get/set stuff.

Is This Cool?

Some may argue that this kind of validation doesn't belong in your model object, and a separate validator object should be created. I can see that point, and I think I mostly agree with it, but there are exceptions to every rule. Sometimes this simple approach is the correct one, and it can streamline your development.

Still, you should keep in mind that your validation function is going to throw a validator exception, so indicate that you'll need to catch it in your documentation if the test fails, or name the method something to show that it should only be used as a hook to the validator, as I've done with someTextFieldValidatorHook.
Scrubbing

One last benefit of the validator is that it gives you a good way to scrub your data before you save it. Since your callback function (someTextFieldValidatorHook in our case) takes the value in to verify it and returns it at the end if the test passed, you can technically change it to whatever you want. Some possible ideas are:

1. Removing HTML
2. Converting text links to actual links (bad example as you should probably do this on output)
3. Formatting Phone Numbers
4. Etc, etc

That's It

Hope you found this useful. Feel free to share how you've used the callback validator in your applications.



You can find the original post here : http://www.pbtg.com/blogs/jim/tag/symfony

A new perspective on the future development of Joomla!



There have been endless discussions around how Joomla! is developed and maintained. One thing is clear though: development is quite slow and new significant features for the end user have not yet been introduced since the Mambo days... It's one of the reasons we decided to build K2, so we could introduce more modern and popular features into Joomla! now.

But how could the development of Joomla! not be slow? Given that the core team are human beings and not robots that work 24 hours a day on coding and debugging Joomla!, it's really simple to realize why the development process is slow. Additionally, it is not easy to contribute code to Joomla! because there are certain protocols need to be followed that make the entire process even slower.

Obviously this is not a post to bash the core team but a new thought on how we could possibly see Joomla! being development in the not so distant future.
So how could we speedup Joomla! development?

It's really simple. Joomla! is modular by nature. So why not make development modular as well?

Here's a realistic example: Joomla! is made up of components like com_content (for articles), com_menus (for the menu management system), com_polls (for the polls) and so on. The Joomla! team could easily "contract" some professional developers and have them undertake the development of a specific component or perhaps module or plugin or whatever!

Imagine this: Joomla! 1.6 will be released without comments (despite original claims for the opposite). How difficult would it be for some developers to create a comments component, contribute it to the default Joomla! 1.6 distribution and also be responsible for maintaining the code!

One thing is for sure. A lot of weight would be lifted off the core team and significantly boost Joomla!'s development. If a bug is introduced on the above example of the comments component, the developers of that component could issue an upgrade and deliver the upgrade through joomla.org to all Joomla! users. Why update an entire Joomla! website when there is a specific problem in some component?

It's how things work in bigger software deployments like operating systems (OS). Teams and sub-teams developing and maintaining individual applications that make up the end product. The best example I guess is from the Linux world where there are applications developed for certain Linux distributions - the bond is so strong that you think they are actually part of the OS (see Ubuntu).

To conclude, I don't think it will be hard for the Joomla! core team to find such developers to code and maintain specific elements of Joomla!. If others can do this in projects with a gazillion lines of code, then Joomla! can do it too.

We (as JoomlaWorks) have offered to code (yes, code, not debug) many times and I know a lot more people who have expressed the same interest as well. And I know it's difficult for the core team to just give away SVN access to others. I wouldn't easily trust other devs to code on K2! But I would certainly trust someone to develop and maintain a module of K2 and have it included in the default distribution.

The only hard part is for the Joomla! core team to actually approve that some developer can deliver quality code by some standards, but it's really no biggie. We are a large community and there's a lot of talent to jump in and help things out. Can you imagine what a positive impact this would have to Joomla!'s PR and especially to users of other content management systems?

What do you think?




You can find the original post here : http://blog.joomlaworks.gr/a-new-perspective-on-the-future-development-o

SOAP WebService in Symfony

One interesting topic on web development is webservice development. There are several techniques to implement a webservice out there, and today I’ll talk about one technique that I worked in the recent past that I really like: SOAP. As per wikipedia:

SOAP, originally defined as Simple Object Access Protocol, is a protocol specification for exchanging structured information in the implementation of Web Services in computer networks. It relies on Extensible Markup Language (XML) as its message format and usually relies on other Application Layer protocols, most notably Remote Procedure Call (RPC) and HTTP for message negotiation and transmission. SOAP forms the foundation layer of the web services protocol stack providing a basic messaging framework upon which abstract layers can be built.

The plan for this tutorial is to build a complete set of webservice methods to interact with the citypicker, built in a previous post. For this, I’ll use a great symfony plugin called ckWebService. This plugin enables the developer to expose your actions as a SOAP webservices. Another great functionality is the built-in WSDL generator, that parses module’s doc comment in order to identify which actions should be exposed and it’s input/output parameters.

Let’s start by installing ckWebService plugin in our symfony project. I’ll not install the latest release, instead I’ll checkout from trunk svn, as it contains some nice improvements if compared to latest release:

info@amphee.com [~/symfony/blog]# cd plugins/
barrosws@barros.ws [~/symfony/blog/plugins]# svn co http://svn.symfony-project.com/plugins/ckWebServicePlugin/trunk ckWebServicePlugin


OBSERVATION: Current trunk version has a small bug (actually a wrong variable name) that must be fixed before continuing:

public function getResultProperty()
{
- return $this->resultMember;
+ return $this->resultProperty;
}


Now we need to configure the plugin in order to make it work. The read-me located at plugin page provides a complete guide to configure it. For this project we use a basic configuration:

apps/frontend/config/app.yml:

soap:
enable_soap_parameter: on
ck_web_service_plugin:
wsdl: soap.wsdl
handler: ckSoapHandler
persist: %SOAP_PERSISTENCE_SESSION%
render: off
result_callback: getSoapResult
soap_options:
encoding: utf-8
soap_version: %SOAP_1_2%


apps/frontend/config/filters.yml:

soap_parameter:
class: ckSoapParameterFilter
param:
condition: %APP_ENABLE_SOAP_PARAMETER%


apps/frondend/config/factories.yml:

soap:
controller:
class: ckWebServiceController


Done! That’s all we need to start exposing actions as SOAP webservices. For now on we can expose any of our previously created action by adding a special tag to the doc comment, like this:

/**
* Action description
* @ws-enable
*
* @param string $name
* @return boolean
*/
public function executeSomeAction($request)
{
/* action here */
}


This doc comment will expose the action and instruct the WSDL generator that this action expects a string input parameter, called $name and that it will return a boolean value. An interesting thing about this plugin is that it will place all input parameters in the $request object, so the action can access it as if it was called from a browser, passing name as a query string or a post value:

...
$name = $request->getParameter('name');
...


Also, notice that $request parameter was removed from the doc comment. This is necessary because if we keep it, the WSDL generator will add $request as a parameter to the webservice, what is not the case here.

Let’s start the implementation for this project. We have three actions that will be exposed:

* executeIndex: to list users;
* executeEdit: to insert/edit users;
* executeDel: to delete users.


One might think that we will need to add @ws-enable to these actions doc comment… well, yes, that’s the original idea, but I prefer using a different approach. My approach is to create a new module, called soap (or whatever you want) and create wrappers to actual actions. This will reduce the number changes needed to be done in the actual actions (sometimes it won’t require any change at all) and will make it possible for the developer to code the entire system without even caring about webservice, all adjustments can be easily made only when actually implementing the webservice. This is not the best way to achieve this result. The correct way to do this is to create a custom SoapHandler, but this will kill WSDL generator, so I’ll stick to my way by now (trunk version has all the necessary changes to make this possible – it’s not the case with latest release).

So, let’s create our new module:

info@amphee.com [~/symfony/blog]# symfony generate:module frontend soap
>> dir+ /home/amphee/symfony/blog/apps/frontend/modules/soap/templates
>> file+ /home/amphee/symfony/blog/app...soap/templates/indexSuccess.php
>> dir+ /home/amphee/symfony/blog/apps/frontend/modules/soap/actions
>> file+ /home/amphee/symfony/blog/app.../soap/actions/actions.class.php
>> file+ /home/amphee/symfony/blog/tes...al/frontend/soapActionsTest.php
>> tokens /home/amphee/symfony/blog/tes...al/frontend/soapActionsTest.php
>> tokens /home/amphee/symfony/blog/app...soap/templates/indexSuccess.php
>> tokens /home/amphee/symfony/blog/app.../soap/actions/actions.class.php


The first action will expose is executeIndex, that will return a list of all users registered in the system. This is the simplest one and I’ll use to explain some important points:

apps/frontend/modules/soap/actions/actions.class.php:

/**
* Get users
*
* @ws-enable
*
* @return SoapUser[]
*/
public function executeGetUsers($request)
{
// call actual action
$this->getController()->forward('citypicker','index');

// set result
$actionInstance = $this->getLastActionInstance();
$actionInstance->result = $actionInstance->users;
}


As I said before, we will create wrappers to actual actions. For this action, we don’t have any input parameter, so we don’t need any extra processing. First thing the action does is a forward to actual action. Note that I use the forward method from the controller instead of forward method from sfAction. This is necessary because we need continue our execution flow AFTER actual action returns (sfAction’s forward won’t return control to us). Return value is expected to be located in the deepest action instance, in our case, citypicker/index action, in a property called result (in our case, we store the result of a UserPeer::doSelect() call – made in citypicker/index action and stored in users property). In order to do this we need to get this action’s instance and that’s what getLastActionInstance method do:

apps/frontend/modules/soap/actions/actions.class.php:

/**
* Get last action instance
*
* @return sfActionInstance
*/
private function getLastActionInstance()
{
return $this->getController()->getActionStack()->getLastEntry()->getActionInstance();
}


This method will simply return last actions instance from the action stack, and we will use it in all of our wrappers. If you look at doc comments, you will notice return value is declared as an array of SoapUser objects. SoapUser class is defined as follows:

lib/soap/SoapUser.class.php



Doc comments are REQUIRED here too, because WSDL generator will use it to build the object definition. When sending result back, our result (array of User objects) will be converted into SoapUser objects, making these properties available.

Our first method is complete. In order to start using it, we need to generate the WSDL definition, using the built-in WSDL generator. The generator will also create the frontend dispatcher, in web/ directory:

info@amphee.com [~/symfony/blog]# symfony webservice:generate-wsdl frontend soap http://blog.barros.ws/symfony
>> file- /home/amphee/symfony/blog/web/soap.php
>> file+ /home/amphee/symfony/blog/web/soap.php
>> tokens /home/amphee/symfony/blog/web/soap.php
>> file+ /home/amphee/symfony/blog/web/soap.wsdl


In order to test it we can use a nice piece of software called SoapUI. This software will read soap.wsdl and build the request, all using a nice GUI. I recommend downloading the trial of PRO version, as it is capable of generating forms (web like) where you can input parameters:

executeDel actions is similar to executeIndex:

apps/frontend/modules/soap/actions/actions.class.php:

/**
* Deletes an user
*
* @ws-enable
* @param integer $id
*
* @return boolean
*/
public function executeDelUser($request)
{
// call actual action
$this->getController()->forward('citypicker','del');

// set result
$actionInstance = $this->getLastActionInstance();
$actionInstance->result = true;
}


Now, executeEdit (executeNewUser in our wrapper) is a bit trickier:

apps/frontend/modules/soap/actions/actions.class.php:

/**
* Creates a new user in the system
*
* @ws-enable
* @param SoapUser $user
*
* @return boolean
*/
public function executeNewUser($request)
{
// convert input param from OBJECT to ARRAY
$request->setParameter('user',get_object_vars($request->getParameter('user')));

// call actual action
$this->getController()->forward('citypicker','edit');

// check errors
$actionInstance = $this->getLastActionInstance();
if(!$actionInstance->form->isValid()) $this->throwSoapFormException($actionInstance->form);

$actionInstance->result = true;
}


First difference we can note is the fact this action requires one input parameters. In doc comment we declare that this action expects an SoapUser object as input, but the actual action expects an simple array. The first step then is to convert received object into an array. For this we use get_object_vars and after conversion, we set it back to the $request object. Finally we call actual action, that will act as if the user had submitted the form. Next difference is that we need to check if there was any error processing input data. We do this by checking if form, in actual action instance, is valid, and if not return an error message. In order to throw an exception with detailed errors, I created an small method called throwSoapFormException, that will iterate through all errors in the form and build single string, with one error per line:

apps/frontend/modules/soap/actions/actions.class.php:

/**
* Throw a SoapFault error based on form errors
*
* @param sfForm $form
*/
public function throwSoapFormException($form)
{
foreach($form->getFormFieldSchema()->getError() as $e)
$errors[] = $e;

throw new SoapFault('ERROR',implode("n",$errors));
}

And that’s it, we can now create new users using the new SOAP interface:



Well, actually one small thing is missing to make it really work… Did u notice that I didn’t touch actual actions yet? Sometimes we don’t need to touch it, but that’s not our case. If you look at citypicker post you will notice that both “del” and “edit” actions redirect the user back to index page on success. We can’t do this when running on soap mode, or we will lose control and we won’t be able to send correct result back to the client. To fix this, we just need to make an small change:

if(!$this->isSoapRequest()) return $this->redirect('citypicker/index');

isSoapRequest is a new method added by ckWebservicePlugin and it will return true when executing the actions via SOAP. Adding this check we just perform the redirect when NOT in SOAP mode.

That’s all we need to talk about how to expose your actions via SOAP, but in order to complete our example, we need to create some methods to fetch countries/states/cities informations. For this we create 6 new actions:

/**
* Get countries list
* @ws-enable
*
* @return SoapGeo[]
*/
public function executeGetCountries($request)
{
$this->result = CountryPeer::doSelect(new Criteria());
}

/**
* Get a country
*
* @ws-enable
* @param integer $id
*
* @return SoapGeo
*/
public function executeGetCountry($request)
{
$this->result = CountryPeer::retrieveByPK($request->getParameter('id'));
}

/**
* Get states list
*
* @ws-enable
* @param integer $country_id
*
* @return SoapGeo[]
*/
public function executeGetStates($request)
{
$country = CountryPeer::retrieveByPK($request->getParameter('country_id'));
if(!$country) throw new SoapFault('ERROR','Invalid country');

$this->result = $country->getStates();
}

/**
* Get a state
*
* @ws-enable
* @param integer $id
*
* @return SoapGeo
*/
public function executeGetState($request)
{
$this->result = StatePeer::retrieveByPK($request->getParameter('id'));
}

/**
* Get cities list
*
* @ws-enable
* @param integer $state_id
*
* @return SoapGeo[]
*/
public function executeGetCities($request)
{
$state = StatePeer::retrieveByPK($request->getParameter('state_id'));
if(!$state) throw new SoapFault('ERROR','Invalid state');

$this->result = $state->getCitys();
}

/**
* Get a city
*
* @ws-enable
* @param integer $id
*
* @return SoapGeo
*/
public function executeGetCity($request)
{
$this->result = CityPeer::retrieveByPK($request->getParameter('id'));
}


And to finish, we need to create the SoapGeo class, that will store country name and id:

lib/soap/SoapGeo.class.php:



And we’re done. With this we can now build an external app to create/edit/delete users in the database. I spent several days working with the plugin before coming up with this solution and I hope this will save other developers some time dealing with SOAP implementations.



You can find original post here : http://blog.barros.ws/2008/11/16/soap-webservice-in-symfony/