Creating Mobile Apps With PHP & Symfony2

41,275 views

Published on

Published in: Technology
9 Comments
32 Likes
Statistics
Notes
  • Njce! Thanks for sharing.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Good share Pablo! If you'd like to get some stats on mobile messaging app usage, we just share a few slides on our profile!
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • The Mobile App Masterplan: Learn how to make excellent money selling apps and quit your job (no coding required) (Online Business Collection Book 1) --- http://amzn.to/1ZgA0hd
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Mobile Strike --- http://amzn.to/1nZstWt
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Mobile Apps Made Simple: The Ultimate Guide to Quickly Creating, Designing and Utilizing Mobile Apps for Your Business - 2nd Edition (mobile ... android programming, android apps, ios apps) --- http://amzn.to/1nZsrOk
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
41,275
On SlideShare
0
From Embeds
0
Number of Embeds
979
Actions
Shares
0
Downloads
514
Comments
9
Likes
32
Embeds 0
No embeds

No notes for slide

Creating Mobile Apps With PHP & Symfony2

  1. 1. Creating Mobile Apps withPHP & Symfony2Pablo Godel @pgodelhttp://joind.in/8675Symfony Live, Portland, May 22 2013Thursday, May 23, 13
  2. 2. ⁃ Born in Argentina, living in the US since 1999⁃ PHP & Symfony developer⁃ Founder of the original PHP mailing list in spanish⁃ Master of the parrilla⁃ Co-founder of ServerGroveWho am I?!Thursday, May 23, 13
  3. 3. Thursday, May 23, 13
  4. 4. Thursday, May 23, 13
  5. 5. ⁃ Founded ServerGrove Networks in 2005⁃ Provider of web hosting specialized in PHP,Symfony, ZendFramework, MongoDB and others⁃ Servers in USA and Europe!Who am I?!Thursday, May 23, 13
  6. 6. ⁃ Very active open source supporter through codecontributions and usergroups/conference sponsoringCommunity is our TeacherThursday, May 23, 13
  7. 7. Why?Mobile Apps - WhyThursday, May 23, 13
  8. 8. •More & more people have access to Internet throughmobile devicesMobile Apps - WhyThursday, May 23, 13
  9. 9. •More & more people have access to Internet throughmobile devices•Devices are more powerful & versatileMobile Apps - WhyThursday, May 23, 13
  10. 10. •More & more people have access to Internet throughmobile devices•Devices are more powerful & versatile•Internet access is faster and more reliableMobile Apps - WhyThursday, May 23, 13
  11. 11. •More & more people have access to Internet throughmobile devices•Devices are more powerful & versatile•Internet access is faster and more reliable•Users demand services and applications on the go at alltimesMobile Apps - WhyThursday, May 23, 13
  12. 12. •More & more people have access to Internet throughmobile devices•Devices are more powerful & versatile•Internet access is faster and more reliable•Users demand services and applications on the go at alltimes•Don’t give advantages in an ultra-competitive marketMobile Apps - WhyThursday, May 23, 13
  13. 13. Some numbers...Mobile Apps - WhyThursday, May 23, 13
  14. 14. •Estimated 6.5 billion mobile subscriptions globally (over90%)Mobile Apps - WhyThursday, May 23, 13
  15. 15. •Estimated 6.5 billion mobile subscriptions globally (over90%)•1.7 billion mobile phones sold in 2012Mobile Apps - WhyThursday, May 23, 13
  16. 16. •Estimated 6.5 billion mobile subscriptions globally (over90%)•1.7 billion mobile phones sold in 2012•1 billion users in China aloneMobile Apps - WhyThursday, May 23, 13
  17. 17. •Estimated 6.5 billion mobile subscriptions globally (over90%)•1.7 billion mobile phones sold in 2012•1 billion users in China alone•321M subscriptions in the US (over 100%)Mobile Apps - WhyThursday, May 23, 13
  18. 18. •Estimated 6.5 billion mobile subscriptions globally (over90%)•1.7 billion mobile phones sold in 2012•1 billion users in China alone•321M subscriptions in the US (over 100%)•Devices range from phone and tablets to door locks,thermostats, TVs, Cars, etc.Mobile Apps - WhyThursday, May 23, 13
  19. 19. How did we get here?Mobile Apps - WhyThursday, May 23, 13
  20. 20. Let’s see some history...Mobile Apps - HistoryThursday, May 23, 13
  21. 21. First commercial cellular network launched inJapan )1G - first generation(1979Mobile Apps - HistoryThursday, May 23, 13
  22. 22. The “mobile” telephoneMotorola DynaTAC -aka “The Boot”cost: US$ 3995weight:793g / 28 ounces1983 Motorola DynaTACMobile Apps - HistoryThursday, May 23, 13
  23. 23. Common Standard to connect networks andapps•WAP client•Server sends WML (XML)WAP - Wireless Application Protocol<?xml version="1.0"?><!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML1.1//EN""http://www.wapforum.org/DTD/wml_1.1.xml" ><wml><card id="main" title="First Card"><p mode="wrap">This is a sample WMLpage.</p></card></wml>1997Mobile Apps - HistoryThursday, May 23, 13
  24. 24. WAP/WMLMobile Apps - HistoryThursday, May 23, 13
  25. 25. WAP/WMLMobile Apps - HistoryThursday, May 23, 13
  26. 26. WAP/WMLMobile Apps - HistoryThursday, May 23, 13
  27. 27. Developer:WAP/WMLMobile Apps - HistoryThursday, May 23, 13
  28. 28. User:WAP/WMLMobile Apps - HistoryThursday, May 23, 13
  29. 29. 2007...Mobile Apps - HistoryThursday, May 23, 13
  30. 30. •Revolutionizedthe market ofmobile telephony•Safari Web ClientiPhone2007Mobile Apps - HistoryThursday, May 23, 13
  31. 31. iPhone App Store2007Mobile Apps - HistoryThursday, May 23, 13
  32. 32. First Android Device2008Mobile Apps - HistoryThursday, May 23, 13
  33. 33. iPad2010Mobile Apps - HistoryThursday, May 23, 13
  34. 34. So what does allthis mean?Mobile Apps - HistoryThursday, May 23, 13
  35. 35. The PC is not deadThe Mobile GenerationMobile Apps - HistoryThursday, May 23, 13
  36. 36. The PC is not dead, yet?The Mobile GenerationMobile Apps - HistoryThursday, May 23, 13
  37. 37. Information is now consumed on phones and tabletsThe Mobile GenerationMobile Apps - HistoryThursday, May 23, 13
  38. 38. And this is just the beginning...The Mobile GenerationMobile Apps - HistoryThursday, May 23, 13
  39. 39. Mobile Apps - SymfonyThursday, May 23, 13
  40. 40. Mobile Apps - SymfonyDefinition by Fabien Potencier:⁃ Symfony2 is a reusable set of standalone,decoupled, and cohesive PHP componentsthat solve common web developmentproblems.⁃ Based on these components, Symfony2 isalso a full-stack web framework.http://fabien.potencier.org/article/49/what-is-symfony2Thursday, May 23, 13
  41. 41. 25 high qualitycomponentshttp://symfony.com/doc/current/components/index.htmlMobile Apps - SymfonyThursday, May 23, 13
  42. 42. • DependencyInjection• EventDispatcher• HttpFoundation• DomCrawler• ClassLoader• CssSelector• HttpKernel• BrowserKit• Templating• Translation• Serializer• Validator• Security• Routing• Console• Process• Config• Finder• Locale• Yaml• Form• ...Components:GitHub: http://github.com/symfonyMobile Apps - SymfonyThursday, May 23, 13
  43. 43. Mobile Apps - SymfonySilexThe PHP/‘Symfony’ micro-frameworkhttp://silex.sensiolabs.org/// web/index.phprequire_once __DIR__./../vendor/autoload.php;$app = new SilexApplication();$app->get(/hello/{name}, function ($name) use ($app) {return Hello .$app->escape($name);});$app->run();Thursday, May 23, 13
  44. 44. Why Symfony?Mobile Apps - SymfonyThursday, May 23, 13
  45. 45. •Provides solid base to build good HTTP &RESTful APIsMobile Apps - SymfonyThursday, May 23, 13
  46. 46. •Provides solid base to build good HTTP &RESTful APIs•Twig makes it easy to build templates formobile devicesMobile Apps - SymfonyThursday, May 23, 13
  47. 47. •Provides solid base to build good HTTP &RESTful APIs•Twig makes it easy to build templates formobile devices•Re-use code for different devices thanks totemplates, controllers and routingMobile Apps - SymfonyThursday, May 23, 13
  48. 48. •Provides solid base to build good HTTP &RESTful APIs•Twig makes it easy to build templates formobile devices•Re-use code for different devices thanks totemplates, controllers and routing•Bundles + Composer = Endless possibilities!Mobile Apps - SymfonyThursday, May 23, 13
  49. 49. &Mobile Web ApplicationsMobile Apps - Web AppsThursday, May 23, 13
  50. 50. http://forecast.ioMobile Apps - Web AppsThursday, May 23, 13
  51. 51. Frameworks HTML / Javascript• iuihttp://code.google.com/p/iui/ (one of the first ones)• JQuery Mobilehttp://jquerymobile.com/ (Open source)• JQTouchhttp://jqtouch.com/ (Open source)• DHTMLX Touchhttp://dhtmlx.com/touch/ (Open source)• The M Projecthttp://www.the-m-project.org/ (Open source)• Sensa Touchhttp://www.sencha.com/products/touch/Mobile Apps - Web AppsThursday, May 23, 13
  52. 52. jQuery MobileMobile Apps - Web AppsThursday, May 23, 13
  53. 53. Supports:- IOS (iPhone/iPad)- Android- Blackberry- Windows Phone- palm webOS- symbianjQuery MobileMobile Apps - Web AppsThursday, May 23, 13
  54. 54. jQuery MobileMobile Apps - Web AppsThursday, May 23, 13
  55. 55. •Based on jQueryjQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  56. 56. •Based on jQuery•Light (40KB)jQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  57. 57. •Based on jQuery•Light (40KB)•HTML5jQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  58. 58. •Based on jQuery•Light (40KB)•HTML5•Accessible (works on screen readers)jQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  59. 59. •Based on jQuery•Light (40KB)•HTML5•Accessible (works on screen readers)•Events, plugins, themesjQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  60. 60. •Based on jQuery•Light (40KB)•HTML5•Accessible (works on screen readers)•Events, plugins, themes•Lots of documentationjQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  61. 61. •Page managementjQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  62. 62. •Page management•TransitionsjQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  63. 63. •Page management•Transitions•Dialog windowsjQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  64. 64. •Page management•Transitions•Dialog windows•Links and buttonsjQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  65. 65. •Page management•Transitions•Dialog windows•Links and buttons•Navigation barsjQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  66. 66. •Page management•Transitions•Dialog windows•Links and buttons•Navigation bars•Header / FooterjQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  67. 67. •Page management•Transitions•Dialog windows•Links and buttons•Navigation bars•Header / Footer•FormsjQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  68. 68. •Page management•Transitions•Dialog windows•Links and buttons•Navigation bars•Header / Footer•Forms•ListsjQuery Mobile - FeaturesMobile Apps - Web AppsThursday, May 23, 13
  69. 69. jQuery Mobile - Page management<body><!-- Start of first page --><div data-role="page" id="foo">! <div data-role="content">!! ! <p>Im first in the source order so Im shown as the page.</p>!!! ! <p>View internal page called <a href="#bar">bar</a></p>!! </div><!-- /content --></div><!-- /page --></body>Mobile Apps - Web AppsThursday, May 23, 13
  70. 70. <body><!-- Start of first page --><div data-role="page" id="foo">! <div data-role="content">!! ! <p>View internal page called <a href="#bar">bar</a></p>!! </div><!-- /content --></div><!-- /page --><!-- Start of second page --><div data-role="page" id="bar">! <div data-role="content">!! ! <p><a href="#foo">Back to foo</a></p>!! </div><!-- /content --></div><!-- /page --></body>jQuery Mobile - Page managementMobile Apps - Web AppsThursday, May 23, 13
  71. 71. jQuery Mobile - Transitions<a href="foo.html" data-rel="dialog" data-transition="pop">Open dialog</a><a href="foo.html" data-rel="dialog" data-transition="slidedown">Open dialog</a><a href="foo.html" data-rel="dialog" data-transition="flip">Open dialog</a><a href="foo.html" data-rel="dialog" data-transition="fade">Open dialog</a>Mobile Apps - Web AppsThursday, May 23, 13
  72. 72. jQuery Mobile - DialogsMobile Apps - Web AppsThursday, May 23, 13
  73. 73. jQuery Mobile - Navigation bars<div data-role="header" data-position="inline">! <a href="index.html" data-icon="delete">Cancel</a>! <h1>Edit Contact</h1>! <a href="index.html" data-icon="check">Save</a></div>Mobile Apps - Web AppsThursday, May 23, 13
  74. 74. jQuery Mobile - FormsMobile Apps - Web AppsThursday, May 23, 13
  75. 75. jQuery Mobile - FormsMobile Apps - Web AppsThursday, May 23, 13
  76. 76. jQuery Mobile - ListsMobile Apps - Web AppsThursday, May 23, 13
  77. 77. &jQuery MobileMobile Apps - Web AppsThursday, May 23, 13
  78. 78. TemplatesMobile Apps - Web AppsThursday, May 23, 13
  79. 79. <!DOCTYPE html><html><head> <title>Podisum by ServerGrove</title> <meta name="viewport" content="width=device-width, initial-scale=1"></head><body>{% block content %}{% endblock %}</body></html>layout.html.twigMobile Apps - Web AppsThursday, May 23, 13
  80. 80. {% extends "layout.html.twig" %}{% block content %}<div data-role="page" id="home"><div data-role="header"><h1>Podisum</h1></div><div data-role="content"><1-- ... --></div></div>index.html.twigMobile Apps - Web AppsThursday, May 23, 13
  81. 81. <div data-role="header" data-theme="b"><h1>{{title}}</h1><a href="#home" data-icon="home" data-iconpos="notext" data-direction="reverse"class="ui-btn-right jqm-home" data-ajax="false">Home</a></div>header.html.twigMobile Apps - Web AppsThursday, May 23, 13
  82. 82. {% extends "layout.html.twig" %}{% block content %}{% include “header.html.twig’ %}<div data-role="content"><1-- ... --></div></div>index.html.twigMobile Apps - Web AppsThursday, May 23, 13
  83. 83. RoutingMobile Apps - Web AppsThursday, May 23, 13
  84. 84. home:pattern: /defaults: { _controller: DemoBundle:Default:index }talks:pattern: /talks.{_format}defaults: { _controller: DemoBundle:Talk:index, _format: html }requirements:_format: html|xml|icstalk:pattern: /talk/{slug}defaults: { _controller: DemoBundle:Talk:talk }jQuery Mobile & Symfony / RoutingMobile Apps - Web AppsThursday, May 23, 13
  85. 85. jQuery Mobile & Symfony / Routinghome:pattern: /mdefaults: { _controller: DemoBundle:Default:index,_format:mhtml }talks:pattern: /m/talksdefaults: { _controller: DemoBundle:Talk:index, _format:mhtml }talk:pattern: /m/talk/{slug}defaults: { _controller: DemoBundle:Talk:talk, _format:mhtml }Mobile Apps - Web AppsThursday, May 23, 13
  86. 86. jQuery Mobile & Symfony / Routing(option 2)home:pattern: /mdefaults: { _controller: DemoBundle:Default:index, mobile:true }talks:pattern: /m/talksdefaults: { _controller: DemoBundle:Talk:index, mobile:true }talk:pattern: /m/talk/{slug}defaults: { _controller: DemoBundle:Talk:talk, mobile:true }Mobile Apps - Web AppsThursday, May 23, 13
  87. 87. m_home:pattern: /mdefaults: { _controller: DemoBundle:Mobile:index }jQuery Mobile & Symfony / Routing(option 3)Mobile Apps - Web AppsThursday, May 23, 13
  88. 88. Controllers & ActionsMobile Apps - Web AppsThursday, May 23, 13
  89. 89. jQuery Mobile & Symfony / Controller & Actionpublic function indexAction(){$em = $this->get(doctrine)->getEntityManager();// ...$format = $this->get(request)->getRequestFormat();return $this->render(DemoBundle:Default:index..$format..twig, array(// ...));}Mobile Apps - Web AppsThursday, May 23, 13
  90. 90. Detect Mobile Devices•http://mobiledetect.net/•Symfony2 + MobileDetectBundle•Silex + MobileDetectServiceProviderMobile Apps - Web AppsThursday, May 23, 13
  91. 91. Mobile Apps - Web AppsMobileDetectBundlepublic function indexAction(){$em = $this->get(doctrine)->getEntityManager();// ...$mobileDetector = $this->get(mobile_detect.mobile_detector);$tpl = $mobileDetector->isMobile() ? ‘mhtml’ : ‘html’;return $this->render(DemoBundle:Default:index..$tpl..twig, array(// ...));}Thursday, May 23, 13
  92. 92. Mobile Apps - Web AppsMobileDetectBundle{% if is_mobile() %}{% if is_tablet() %}{% if is_device(iphone) %} # magic methods is[...]{% extends is_mobile() ? "MyBundle:Layout:mobile.html.twig" :"MyBundle:Layout:full.html.twig" %}Thursday, May 23, 13
  93. 93. Mobile Apps - Web AppsMobileDetectBundlemobile_detect:redirect:mobile:is_enabled: truehost: http://m.site.comstatus_code: 301action: redirecttablet: ~switch_device_view: ~Thursday, May 23, 13
  94. 94. •Symfony2 functional tests for HTML pages•For AJAX other testing methods may be used:•Selenium RC•BehatMobile Apps - Web AppsTestingThursday, May 23, 13
  95. 95. DEMOS !Podisum:http://github.com/pgodel/podisumsunshinephphttp://m.sunshinephp.com/Control Panel:•https://control.servergrove.com/•https://control.servergrove.com/mlogin: demo@servergrove.compassword: demoMobile Apps - Web AppsThursday, May 23, 13
  96. 96. Podisum http://github.com/pgodel/podisum•Generates summaries of Logstash events•Silex app•Twig templates•Mobile versionMobile Apps - Web AppsThursday, May 23, 13
  97. 97. PodisumMobile Apps - Web AppsThursday, May 23, 13
  98. 98. PodisumApache access_log LogstashRedisPodisum redis-clientMongoDBPodisum Silex AppWeb ClientMobile Apps - Web AppsThursday, May 23, 13
  99. 99. Mobile Apps&Native ApplicationsThursday, May 23, 13
  100. 100. •iPhone - Objective-C•Android - Java•Windows Mobile - .NET•Frameworks multi-platform⁃ PhoneGap http://phonegap.com⁃ rhomobile http://rhomobile.com⁃ Appceledator http://appcelerator.com⁃ Corona http://anscamobile.com/corona/Mobile Apps - Native AppsThursday, May 23, 13
  101. 101. Mobile Apps - Native AppsPHP does not run in thesedevices but native apps need toretrieve and store data fromservers.Thursday, May 23, 13
  102. 102. Common uses:•send emails & messages in general•loading of profile data•authentication & authorization•chatsMobile Apps - Native AppsPHP does not run in thesedevices but native apps need toretrieve and store data fromservers.Thursday, May 23, 13
  103. 103. Some considerations:•Design API (RESTful, HTTP, XML-RPC) early on atthe development cycleMobile Apps - Native AppsThursday, May 23, 13
  104. 104. Some considerations:•Design API (RESTful, HTTP, XML-RPC) early on atthe development cycle•APIs can be used by multiple types of clientsMobile Apps - Native AppsThursday, May 23, 13
  105. 105. Some considerations:•Design API (RESTful, HTTP, XML-RPC) early on atthe development cycle•APIs can be used by multiple types of clients•Re-use controllers and use _format to generatedifferent content types (XML, JSON, etc)Mobile Apps - Native AppsThursday, May 23, 13
  106. 106. Build APIs with Symfony2- FOSRestBundlehttps://packagist.org/packages/friendsofsymfony/rest-bundle- ApiDocBundlehttps://packagist.org/packages/nelmio/api-doc-bundleMobile Apps - Native AppsThursday, May 23, 13
  107. 107. Build APIs with Symfony2- FOSRestBundlehttps://packagist.org/packages/friendsofsymfony/rest-bundle- ApiDocBundlehttps://packagist.org/packages/nelmio/api-doc-bundleMobile Apps - Native AppsBuild APIs with Silex- responsible-service-provider- silex-skeleton-restThursday, May 23, 13
  108. 108. Push NotificationsServer sends messages to mobile devices- AppleApnPushBundle- RMSPushNotificationsBundle- DABSquaredPushNotificationsBundle- ZendServiceGoogleGcm- ZendServiceAppleApnsMobile Apps - Native AppsThursday, May 23, 13
  109. 109. Mobile Apps - Native AppsRMSPushNotificationsBundlepublic function pushAction(){$message = new iOSMessage();$message->setMessage(Oh my! A push notification!);$message->setDeviceIdentifier(test012fasdf482asdfd63f6d7bc6d4293aedd5fb448fe505eb4asdfef8595a7);$this->container->get(rms_push_notifications)->send($message);return new Response(Push notification sent!);}Thursday, May 23, 13
  110. 110. Mobile Apps - SMS Apps&SMS (and voice) ApplicationsThursday, May 23, 13
  111. 111. Mobile Apps - SMS AppsThursday, May 23, 13
  112. 112. Symfony can send/receive text messagesCommon uses:- Alerts- Chats- Electronic payments- Ads- Two-factor authenticationMobile Apps - SMS AppsThursday, May 23, 13
  113. 113. SMS Gateway providers:•Twilio•Nexmo•Clickatell•BulkSMSMobile Apps - SMS AppsThursday, May 23, 13
  114. 114. Mobile Apps - SMS AppsVreshTwilioBundle$twilio = $this->get(twilio.api);$message = $twilio->account->sms_messages->create(9991231234, // From a valid Twilio number8881231234, // Text this number"Hello monkey!");Thursday, May 23, 13
  115. 115. Mobile Apps - Voice AppsTwilio-php SDK$client = new Services_Twilio($sid, $token);$call = $client->account->calls->create(9991231234, // From a valid Twilio number8881231234, // Call this number// Read TwiML at this URL when a call connects (hold music)http://twimlets.com/holdmusic?Bucket=com.twilio.music.ambient);Thursday, May 23, 13
  116. 116. MMS are multimedia messages with text,images, video, audio.Common uses:- Photo processing- Sending/scanning 2D barcodesMobile Apps - SMS/MMS Appshttps://github.com/endroid/QrCodehttps://github.com/endroid/EndroidQrCodeBundlehttps://github.com/mkoppanen/php-zbarcodeThursday, May 23, 13
  117. 117. Mobile Apps - Hybrid Apps&Hybrid Applications(mix native, web, others)Thursday, May 23, 13
  118. 118. Applications that combine web, sms,voice and native aspectsFramework PhoneGap- Build apps with HTML & JavaScript- Integrates with XCode- Compiles app into native code- Access to accelerometer, camera, geolocation,notifications and moreMobile Apps - Hybrid AppsThursday, May 23, 13
  119. 119. Questions?Mobile AppsThursday, May 23, 13
  120. 120. Twitter: @pgodelIRC Freenode: pgodelSource: https://github.com/pgodel/podisumSlides: http://slideshare.net/pgodelMobile Apps - Thanks!Feedback Please:http://joind.in/8675Thank you!Thursday, May 23, 13

×