Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Build your first ownCloud App!

Build your first ownCloud App!

Slides of the Workshop I conducted at openSUSE Asia Summit 2014 Beijing, China.

Raghu Nayyar

October 14, 2014
Tweet

More Decks by Raghu Nayyar

Other Decks in Programming

Transcript

  1. Build your first ownCloud App openSUSE Summit Asia Beijing -

    October 2014 Raghu Nayyar - @raghunayyar Google Summer of Code - 2013, 2014 - ownCloud (under openSUSE) Photo by : Baron Reznik
  2. ownCloud.org 1. beyond file hosting and sharing 2. one click

    install self hosted applications • Calendar • Contacts • News • Notes • Bookmarks • Mail • Gallery …. and many many more
  3. Why should you make an ownCloud App? Miss an feature

    set? Implement it. Share it. But check if it already exists at apps.owncloud.com
  4. What do you need? 1. A webserver (Apache, NGINX) 2.

    PHP (> 5.3.8) 3. Web browser (preferably not IE8 or less) 4. A code editor of your choice.
  5. What should you know? Basic knowledge of • HTML •

    CSS • JavaScript • PHP • SQL • ownCloud API
  6. Getting Started 1. setup an ownCloud instance 2. create a

    folder within the app directory* 3. enable debugging mode DEFINE('DEBUG',  true);  (config/config.php) * folder name should be same as app id.
  7. appinfo/ Requires ! • app.php register navigation entry & connect

    to hooks ! • info.xml description, authors, license, etc. ! • version plain text file with your version number
  8. appinfo/app.php add navigation entry for your app: ! <?php  

      $l  =  OCP\Util::getL10N('myapp');     \OCP\App::addNavigationEntry(array(     'id'  =>  'myapp',  //must  equal  folder-­‐name     'order'  =>  74,  //sorting  weight  for  the  navigation     'href'  =>  \OCP\Util::linkTo('myapp',  ‘index.php'),     'icon'  =>  \OCP\Util::imagePath('myapp',  'nav-­‐icon.png'),     'name'  =>  $l-­‐>t(‘My  App’),   ));
  9. appinfo/info.xml Requires: ! • id - appId • name -

    human-readable name • description • license - must be AGPL compatible • author • require - minimal ownCloud version required
  10. appinfo/info.xml Optional: ! • public - provides public interface -

    no login • remote - provides public interface - with login • documentation - link to doc • website - link to project website • standalone - whether or not it’s a standalone app
  11. /index.php <?php     OCP\User::checkLoggedIn();     OCP\App::checkAppEnabled(‘myapp’);    

    OCP\App::setActiveNavigationEntry(‘myapp’);     $tmpl  =  new  OCP\Template(‘myapp’,  ‘main’,     ‘user’);     $tmpl-­‐>assign(‘name’,  OCP\User::getDisplayName());     $tmpl-­‐>printPage();
  12. template files $_ is an array containing variables assigned to

    template ! • never ever use echo, print, whatsoever • use p() • or print_unescaped() if you are 100% sure that the string can not be affected by XSS attacks
  13. templates/main.php <p  class=“infobox”>     You  are  logged  in  as:

        <?php       p($_['name']);     ?>   </p>
  14. css/main.css .infobox  {     font-­‐size:  20px;     text-­‐align:

     center;     padding-­‐top:  50px;     color:  #1D2D44;   } index.php   OCP\Util::addStyle(‘myapp’,  ‘main’);
  15. ajax/getnum.php <?php     OCP\JSON::checkLoggedIn();     OCP\JSON::checkAppEnabled('myapp');    

    OCP\JSON::callCheck();     $number  =  OCP\Config::getUserValue(OCP\USER::getUser(),       'myapp',  'number',  null);     if($number  ===  null)  {       OCP\JSON::error(array(         'message'  =>  'No  number  stored’,       ));       exit;     }     OCP\JSON::success(array(       'number'  =>  $number,     ));
  16. ajax/setnum.php <?php     OCP\JSON::checkLoggedIn();     OCP\JSON::checkAppEnabled('myapp');    

    OCP\JSON::callCheck();   !   if(!array_key_exists('number',  $_GET))  {       OCP\JSON::error(array(         'message'  =>  'No  number  given',       ));       exit;     }   !   $number  =  floatval($_GET['number']);     OCP\Config::setUserValue(OCP\USER::getUser(),         'myapp',  'number',  $number);     OCP\JSON::success(array(       'number'  =>  $number,     ));
  17. templates/main.php <p  class=“infobox”>     Enter  a  number  and  we’ll

     store  it!     <input  type=“number”  id=“numberinput”>   </p>
  18. $(document).ready(function()  {     $.get(OC.filePath('myapp',  'ajax',  ‘getnum.php'),     {},

     function(result)  {       if  (result.status  ==  'success')  {         $(“#numberinput”).val(escapeHTML(result.number));       }     }   );   !   $("#numberinput").change(function(event)  {       var  input  =  $(“#numberinput”).val();       $.get(OC.filePath('myapp',  'ajax',  ‘setnum.php'),         {number:  input},  function(result)  {           if  (result.status  !=  'success')  {             OC.Notification.show(result.message);           }       });     });   }); js/main.js
  19. /index.php <?php     OCP\User::checkLoggedIn();     OCP\App::checkAppEnabled('myapp');    

    OCP\Util::addStyle('myapp',  'main');     OCP\Util::addScript('myapp',  'main');     OCP\App::setActiveNavigationEntry('myapp');     $tmpl  =  new  OCP\Template('myapp',  'main',     'user');     $tmpl-­‐>printPage();
  20. OCP\Config • getSystemValue  (  $key,  $default  =  null  )  

    • setSystemValue  (  $key,  $value  )   • getAppValue  (  $app,  $key,  $default  =  null  );   • setAppValue  (  $app,  $key,  $value  );   • getUserValue  (  $user,  $app,  $key,  $default  =  null  );   • setUserValue  (  $user,  $app,  $key,  $value  );
  21. OCP\Template • __construct(  $app,  $name,  $renderas  =  ""  );  

    • addHeader(  $tag,  $attributes,  $text=‘’);   • assign  (  $key,  $value);   • printPage();   • fetchPage();
  22. Template Helpers • image_path(  $app,  $image  );   • human_file_size(

     $bytes  );   • relative_modified_date(  $timestamp,  $dateOnly  =  false  );   • html_select_options  ($options,  $selected,  $params=array())
  23. OCP\User • getUser()   • getUsers(  $search  =  '',  $limit

     =  null,  $offset  =  null  )   • getDisplayName(  $user  =  null  )   • getDisplayNames(  $search  =  '',  $limit  =  null,  $offset  =  null  )   • isLoggedIn()   • userExists(  $uid,  $excludingBackend  =  null  )
  24. appinfo/database.xml <?xml  version="1.0"  encoding="ISO-­‐8859-­‐1"  ?>   <database>     <name>*dbname*</name>

        <create>true</create>     <overwrite>false</overwrite>     <charset>utf8</charset>     <table>       <name>*dbprefix*yourapp_items</name>       <declaration>         <field>           <name>id</name>           <type>integer</type>           <default>0</default>           <notnull>true</notnull>           <autoincrement>1</autoincrement>           <length>4</length>         </field>         <!-­‐-­‐  ...  -­‐-­‐>       </declaration>     </table>   </database>
  25. OCP\DB • prepare  (  $query,  $limit=null,$offset=null  )   • execute($params

     =  null)   ! Don’t  put  variables  into  $query,  use  the  ?   placeholder  and  hand  over  the  variable  in  $params!   This  will  protect  you  from  SQL  Injections.   ! • insertid  ($table=null)
  26. Benefits • Build-In Dependency Injection • proper MVC abstraction •

    easier integration with routes • opt-out for security checks • easier testing
  27. Got Stuck? Have doubts? We help each other. ! IRC

    : freenode #ownCloud (users) #ownCloud-dev (developers) #ownCloud-design (designers) #ownCloud-testing (testing)
  28. Contribute to core? For Developers and Designers start by fixing

    issues marked as “Junior Job” ! • easy to implement • help you to get familiar with ownCloud’s code
  29. Contribute to core? Other ways to contribute ! translate ownCloud

    transifex.com/projects/p/owncloud/ ! write high-quality bug reports ! testing
  30. Looking forward to see your app! Slides : speakerdeck.com/raghunayyar Credits

    : Georg Ehrke, ownCloud Community Special Thanks : Jos Poortvliet, ownCloud Inc.