Merge pull request #14 from WireShout/stable45

Stable45 - GCI Task #7947213
This commit is contained in:
Daniel Molkentin
2012-12-13 13:05:04 -08:00
20 changed files with 1170 additions and 18 deletions

View File

@@ -0,0 +1,36 @@
public.php and remote.php
=========================
public.php
----------
The public.php is used for public sharing like public file sharing, public gallery sharing and public calendar sharing.
Register:
~~~~~~~~~
To register an app for public.php you just have to put the following lines into your apps appinfo/info.xml.
Example from our source code: ``<public> <calendar>share.php</calendar> <caldav>share.php</caldav> </public>``
Now you can reach the file /apps/calendar/share.php through /public.php?service=calendar and through /public.php?service=caldav
Example for syntax: ``<public> <servicename>phpfileforsharing.php</servicename> </public>``
Now you can reach the file */apps/appid/phpfileforsharing.php* through */public.php?service=servicename*
remote.php
----------
The remote.php is used for remote services like webdav, caldav, carddav and ampache.
Register:
~~~~~~~~~
To register an app for remote.php you just have to put the following lines into your apps appinfo/info.xml.
Example from our source code: ``<remote> <calendar>appinfo/remote.php</calendar> <caldav>appinfo/remote.php</caldav> </remote>``
Now you can reach the file /apps/calendar/appinfo/remote.php through /remote.php/calendar and through /remote.php/caldav/
Example for syntax: ``<remote> <servicename>phpfileforremote.php</servicename> </remote>``
Now you can reach the file */apps/appid/phpfileforremote.php* through */remote.php/servicename/*

View File

@@ -0,0 +1,49 @@
Code Reviews on github
======================
``We will start with a test phase for the next 2 month (until end of December).
The test phase will ONLY apply for the `core repository`_ at the moment.
(Other repositories are welcome to join )
Let's see if we get any benefit from this approach.``
Linus' Law: *"given enough eyeballs, all bugs are shallow"*
Introduction
------------
In order to increase the code quality within ownCloud, developers are requested to perform code reviews.
As we are now heavily using the github platform these code review shall take place on github as well.
Precondition
------------
From now on no direct commits/pushes to master or any of the stable branches are allowed in general.
**Every code** change - **even one liners** - have to be reviewed!
How will it work?
-----------------
#. A developer will submit his changes on github via a pull request. `github:help - using pull requests`_
#. Within the pull request the developer could already name other developers (using @githubusername) and ask them for review.
#. Other developers (either named or at free will) have a look at the changes and are welcome to write comments within the comment field.
#. In case the reviewer is okay with the changes and thinks all his comments and suggestions have been take into account a :+1 on the comment will signal a positive review.
#. Before a pull request will be merged into master or the corresponding branch at least 2 reviewers need to give :+1 score.
#. In the near future we will have the `continuous integration server`_ set up to monitor pull request as well which will give an additional indicator for the quality.
Examples
--------
Please find the first good examples below!
https://github.com/owncloud/core/pull/121
https://github.com/owncloud/core/pull/146
Questions?
----------
Feel free to drop a line on the `mailing list`_ or join us on `IRC`_.
.. _core repository: https://github.com/owncloud/core
.. _github:help - using pull requests: https://help.github.com/articles/using-pull-requests
.. _continuous integration server: https://ci.tmit.eu/
.. _mailing list: https://mail.kde.org/mailman/listinfo/owncloud
.. _IRC: http://webchat.freenode.net/?channels=owncloud-dev

View File

@@ -0,0 +1,52 @@
Compatibility Notes
===================
One of our major improvements of ownCloud 4 are movable apps. Therefore we changed the way ownCloud loads apps. Apps used to be called directly through their index.php (e.g.: /files/index.php). The problem has been that apps would not been movable if they contain a hardcoded link to the Base Library.
Apps will be called trough an parameter in ownCloud 4. An example for this is: /?app=files.
ownCloud 3 apps are not supported regarding to this mayor change, but making an ownCloud 3 app compatible with ownCloud 4 is pretty easy.
The first step is to **remove** the **require_once** command to the **Base library** in **every file** of your app.
Afterwords you have to make sure that your app uses the ownCloud internal functions to generate paths.
Paths:
~~~~~~
For generating a path in PHP use our new public API:
.. code-block:: php
OCP\Util::linkTo
and for generating a path in Js use the function:
.. code-block:: php
OC.filePath
CSS:
~~~~
You have to use the placeholders ``%appswebroot%`` and ``%webroot%``, if your CSS file contains relative paths.
Example from our source code:
.. code-block:: css
#contacts_deletecard {position:relative; float:left; background:url('%webroot%/core/img/actions/delete.svg') no-repeat center; }
public.php and remote.php
~~~~~~~~~~~~~~~~~~~~~~~~~
We introduced the files public.php and remote.php in ownCloud 4.
If you want to know how to use them, you should take a look `here`_.
New public API
~~~~~~~~~~~~~~
We also introduced our new public api. The documentation for this api can be found at http://api.ownCloud.org.
.. _here: http://owncloud.org/dev/apps/public-php-and-remote-php/

View File

@@ -0,0 +1,110 @@
Data Migration
==============
As of OC4, user migration is supported. To include migration support in your app (which is highly recommended and doesnt take long) you must provide a migrate.php file in appname/appinfo/migrate.php.The function of the migrate.php file is to provide an import and export functions for app data. To assist in this, we set the user id of the user being exported / user being imported in $this->uid. There is also an instance of the OC_Migration_Content class stored in $this->content. The OC_Migration_Content class helps to make importing and exporting data easy for app developers.
Export
------
In this function, you must do everything necessary to export a user from the current ownCloud instance, given a user id. For most apps this is just the case of saving a few rows from the database.
Database Data
~~~~~~~~~~~~~
To make exporting database data really easy, the class OC_Migration_Content has a method called copyRows() which will save these rows for you given some options. Take a look at the export function for the bookmarks app:
.. code-block:: php
function export( ){
OC_Log::write('migration','starting export for bookmarks',OC_Log::INFO);
$options = array(
'table'=>'bookmarks',
'matchcol'=>'user_id',
'matchval'=>$this->uid,
'idcol'=>'id'
);
$ids = $this->content->copyRows( $options );
$options = array(
'table'=>'bookmarks_tags',
'matchcol'=>'bookmark_id',
'matchval'=>$ids
);
// Export tags
$ids2 = $this->content->copyRows( $options );
// If both returned some ids then they worked
if( is_array( $ids ) && is_array( $ids2 ) )
{
return true;
} else {
return false;
}
}
The bookmarks app stores all of its data in the database, in two tables: *PREFIX* bookmarks and *PREFIX* bookmarks_tags so to export this, we need to run copyRows() twice. Here is an explanation of the options passed to OC_Migration_Content::copyRows():
* table => string name of the table to export (without any prefix)
* matchcol => (optional) string name of the column that will be matched with the value in matchval (Basically the column used in the WHERE sql query)
* matchval => (optional) the value that will be searched for in the table
* idcol => the name of the column that will be returned
To export the bookmarks, matchcol is set to the user_id column and matchval is set to the user being exported: $this->content->uid. idcol is set to the id of the bookmark, as we need to retrive the tags associated with the bookmarks for the user being exported. The function will return an array of ids.Next we run the copyRows() method again, this time on the bookmarks_tags table, matching a range of values (as we want to find all tags, related to all bookmarks owned by the exported user).Finally we check that both functions returned arrays which confirms that they were successful and return a boolean value to represent the success of the export.
Files
~~~~~
If you use files to hold some app data in data/userid/appname, they will be automatically copied exported for you.
Import
------
Import is a little more tricky as we have to take into account data from different versions of your app, and also handle changing primary keys. Here is the import function for the bookmarks app which imports bookmarks and tags:
.. code-block:: php
function import(){
switch( $this->appinfo->version ){
default:
// All versions of the app have had the same db structure
// so all can use the same import function
$query = $this->content->prepare( "SELECT * FROM bookmarks WHERE user_id LIKE ?" );
$results = $query->execute( array( $this->olduid ) );
$idmap = array();
while( $row = $results->fetchRow() ){
// Import each bookmark, saving its id into the map
$query = OC_DB::prepare( "INSERT INTO *PREFIX*bookmarks(url, title, user_id, public, added, lastmodified) VALUES (?, ?, ?, ?, ?, ?)" );
$query->execute( array( $row['url'], $row['title'], $this->uid, $row['public'], $row['added'], $row['lastmodified'] ) );
// Map the id
$idmap[$row['id']] = OC_DB::insertid();
}
// Now tags
foreach($idmap as $oldid => $newid){
$query = $this->content->prepare( "SELECT * FROM bookmarks_tags WHERE user_id LIKE ?" );
$results = $query->execute( array( $oldid ) );
while( $row = $data->fetchRow() ){
// Import the tags for this bookmark, using the new bookmark id
$query = OC_DB::prepare( "INSERT INTO *PREFIX*bookmarks_tags(bookmark_id, tag) VALUES (?, ?)" );
$query->execute( array( $newid, $row['tag'] ) );
}
}
// All done!
break;
}
return true;
}
We start off by using a switch to run different import code for different versions of your app. $this->appinfo->version contains the version string from the info.xml of your app. In the case of the bookmarks app the db structure has not changed, so only one version of import code is needed.To import the db data, first we must retrive it from the migration.db. To do this we use the prepare method from OC_Migration_Content, which returns a MDB2 db object. We then cycle through the bookmarks in migration.db and insert them into the owncloud database. The important bit is the idmapping. After inserting a boookmark, The new id of the bookmark is saved in an array, with the key being the old id of the bookmark. This means when inserting the tags, we know what the new id of the bookmark is simply by getting the value of $idmap['oldid']. Remember this part of the import code may be a good place to emit some hooks depending on your app. For example the contacts app could emit some hooks to show some contacts have been added.After importing the bookmarks, we must import the tags. It is a very similar process to importing the bookmarks, except we have to take into account the changes in primary keys. This is done by using a foreach key in the $idmap array, and then inserting the tags using the new id.After all this, we must return a boolean value to indicate the success or failure of the import.Again, app data files stored in data/userid/appname will be automatically copied over before the apps import function is executed, this allows you to manipulate the imported files if necessary.
Conclusion
----------
To fully support user migration for your app you must provide a import and export function under an instance of OC_Migration_Provider and put this code in the file appname/appinfo/migrate.php
You can view other migration providers here:
* `Bookmarks migration provider`_
* `Contact migration provider`_
.. _Bookmarks migration provider: http://gitorious.org/owncloud/owncloud/blobs/migration/apps/bookmarks/appinfo/migrate.php
.. _Contact migration provider: http://gitorious.org/owncloud/owncloud/blobs/migration/apps/contacts/appinfo/migrate.php

View File

@@ -0,0 +1,20 @@
Database
========
ownCloud uses a database abstraction layer on top of either MDB2 or PDO, depending on the availability of PDO on the server.
Apps should always use prepared statements when accessing the database as seen in the following example:
.. code-block:: php
$query=OC_DB::prepare('SELECT foo,bar FROM *PREFIX*mytable' WHERE user=?');
$result=$query->execute(array($userId));
$data=$result->fetchAll();
*'PREFIX'* in the query string will be replaced by the configured database table prefix while preparing the query. Arguments for the prepared statement are denoted by a '?' in the query string and passed during execution in an array.
For more information about MDB2 style prepared statements, please see the official MDB2 documentation `here`_
If an app requires additional tables in the database they can be automatically created and updated by specifying them inside appinfo/database.xml using MDB2's `xml scheme notation`_ where the placeholders *'dbprefix'* and *'dbname'* can be used for the configured database table prefix and database name. To update the tables used by the app, simply adjust the database.xml file and increase the app version number to trigger an update.
.. _here: http://pear.php.net/package/MDB2/
.. _xml scheme notation: http://www.sulc.edu/sulcalumni/app/lib/pear/docs/MDB2_Schema/docs/xml_schema_documentation.html

View File

@@ -0,0 +1,4 @@
Dialogs
=======
*Coming Soon*

View File

@@ -0,0 +1,56 @@
Filesystem
==========
ownCloud handling of filesystems is very flexible. A variety of local and remote filesystem types are supported, as well as a variety of hooks and optional features such as encryption and version control. It is important that apps use the correct methods for interacting with files in order to maintain this flexibility.
In some cases using PHPs internal filesystem functions directly will be sufficient, such as unlink() and mkdir(). Most of the time however it is necessary to use one of ownClouds filesystem classes. This documentation assumes that you are working with files stored within a users directory (as opposed to ownCloud core files), and therefore need to use OC_Filesystem.
Using PHP filesystem functions directly
---------------------------------------
An example of when it is approprite to use PHPs filesystem functions instead of OC_Filesystem is if you are storing temporary files which will not be saved, or whose saving is taken care of by external code. ownClouds zip compression class does this (OC_Archive_ZIP), and returns the temporarily stored compressed file so that external code can determine what to do with it. Parts of ownClouds installation procedure also fall into this category, as certain files need only be saved temporarily in order to set up more permanent storage options.
Using ownClouds filesystem methods
-----------------------------------
Most filesystem interaction should make use of OC_Filesystem. By using the methods within this class you ensure that non-standard and future ownCloud configurations, as well as other filesystem-related apps, will function correctly with your code. Static methods for performing most filesystem operations are provided, including:
* mkdir( $path )
* rmdir( $path )
* opendir( $path )
* is_dir( $path )
* is_file( $path )
* stat( $path )
* filetype( $path )
* filesize( $path )
* readfile( $path )
* is_readable( $path )
* is_writable( $path )
* file_exists( $path )
* filectime( $path )
* filemtime( $path )
* touch( $path, $mtime )
* file_get_contents( $path )
* file_put_contents( $path,$data )
* unlink( $path )
* rename( $path1,$path2 )
* copy( $path1,$path2 )
* fopen( $path,$mode )
* toTmpFile( $path )
* fromTmpFile( $tmpFile,$path )
* getMimeType( $path )
* hash( $type,$path )
* free_space( $path )
* search( $query )
OC_Filesystem must be initiated before it can be used using the OC_Filesystem::init() method (the class is follows the `singleton pattern`_). init() takes one argument, which is the root directory to be used within the virtual filesystem that OC_Filesystem will work with.
Example:
.. code-block:: php
OC_Filesystem::init( '/' . $user . '/' . $root );
OC_Filesystem::mkdir( 'test' );
if ( OC_Filesystem::is_dir('test') ) { echo 'OC_Filesystem is being used correctly'; }``
.. _singleton pattern: https://en.wikipedia.org/wiki/Singleton_pattern

View File

@@ -0,0 +1,19 @@
Formfactors
===========
ownCloud automatically detects what kind of form factor you are using.
Supported form factors
----------------------
Currently supported are mobile, tablet, standalone and the default desktop view. Mobile is a mode that works good for touch screen smartphones. Tablet is optimized for devices like iPads or Android Tablets. The standalone view is a mode where only the content are an App is shown. The header, footer and side navigation is not visible. This is useful if ownCloud is embedded in other applications.
Over writing
------------
The auto detection can be overwritten by using the “formfactor” GET variable in the url.
How to use it in Apps?
----------------------
Developers can provide special versions of js or css files and templates. The special versions are automatically used if present. If not it falls back to the default files. If an App wants to provide a special mobile version of the css file it can just add a second file with a special name. The mobile version of example.css is example.mobile.css. The tablet template of foo.php is foo.tablet.php.

View File

@@ -0,0 +1,95 @@
Getting Started
===============
Before you start, please check if there already is a similar app you could contribute to. `On our planning page`_ there are also some app ideas. Also, feel free to communicate your idea and plans to the `mailing list`_ so other contributors might join in.
Develop an app
--------------
We will use the contacts app as an example, you find it under apps/contacts.
Folder structure
----------------
* ajax
* appinfo
* css
* img
* js
* l10n
* lib
* templates
As you can imagine, templates belong in the template directory, css files in the css directory, images in the img directory and javascript files in the js directory. Renaming these directories is a really bad idea because functions like OC_Helper::linkTo or OC_Helper::imagePath will not work then.The appinfo directory provides everything ownCloud needs to get the app working. The most important file is app.php. ownCloud will call this file everytime it runs, so this is the place where you can register your navigation entries or connect signals and slots. More on this later.The l10n will contain the translations. As soon as the translation detects a l10n folder it knows that this program is translatable.All php scripts that are used to answer AJAX requests are located in ajax. This keeps the root folder clean. Note that ownCloud does not force you to use this folder but it is recommended to use it.If you write a library for your app you can put it into lib. As with the ajax folder this is not a must, but it is recommended.
The Model: lib/
---------------
ownCloud uses the MVC principle. The libraries represent the model. Basically all data should be handled here so the php files the user calls only interact with the library. If you have a look at the lib folder in contacts, you will see three files: addressbook.php, hooks.php and connector_sabre.php.addressbook.php contains all methods that are required for handling addresses. We mostly use the classes as namespaces and write static functions, “real” OOP is only used if it is useful.All functions that are called by hooks are in hooks.phpTo use the CardDAV capabilities of SabreDAV we have the library OC_Connector_Sabre_CardDAV in connector_sabre.php. This file is very small and delegates most work to OC_Contacts_Addressbook in addressbook.php. This way you only have one file with all SQL queries.
The View: templates/
--------------------
ownCloud has its own template system. The templates are php files that are included by OC_Template. Having a look at two files basically shows you everything you need to know.The variables are assigned by using $tmpl->assign(name,'value);, have a look at the end of /index.php to see how it works.
The controllers
---------------
In contacts, you find the controllers in the root directory and in ajax/. Controllers are meant to be lean.
Javascripts
-----------
The javascript libraries we use are jQuery and Torch. You can add scripts to your pages using:OC_UTIL::addScript([app name], [script name]);Scripts can be added this way in either appinfo/app.php or in your apps individual PHP scripts.
Tell owncloud of our app: appinfo/
----------------------------------
In appinfo are three files. Each app must have app.php and info.xml, database.xml is only needed when the app creates its own tables.app.php is called by owncloud each time it runs. Let us examine this file line by line.
.. code-block:: php
OC::$CLASSPATH['OC_Contacts_Addressbook'] = 'apps/contacts/lib/addressbook.php';
OC::$CLASSPATH['OC_Contacts_Hooks'] = 'apps/contacts/lib/hooks.php';
OC::$CLASSPATH['OC_Connector_Sabre_CardDAV'] = 'apps/contacts/lib/connector_sabre.php';
This adds some entries to the OC::$CLASSPATH. This helps the ownCloud autoload function to load classes that are not in /lib. The cool thing about this is that you do not need to include anything else than /lib/base.php.
.. code-block:: php
OC_HOOK::connect('OC_User', 'post_createUser', 'OC_Contacts_Hooks', 'deleteUser');
We do not need addressbooks of deleted people. But how do we know when a user is being deleted? For this, we use hooks. As soon as someone deletes a user the OC_Uer class emits the signal post_createUser. We use this signal and connect it with the slot deleteUser in the class OC_Contact_Hooks. For more details, have a look at the documentation of OC_Hook.
.. code-block:: php
OC_App::register( array(
'order' => 10,
'id' => 'contacts',
'name' => 'Contacts' ));
Registers the app in ownCloud.
.. code-block:: php
OC_App::addNavigationEntry( array(
'id' => 'contacts_index',
'order' => 10,
'href' => OC_Helper::linkTo( 'contacts', 'index.php' ),
'icon' => OC_Helper::imagePath( 'contacts', 'icon.png' ),
'name' => 'Contacts' ));
This adds the entry to the navigation.info.xml is self-explanatory.database.xml describes the database as required by MDB2. Note that the database name is *dbname* and that each table name needs a *dbprefix* in front of it.
App Template
------------
A template for writing new apps can be found here: https://github.com/owncloud/apps/tree/master/apptemplate
Publish your app
----------------
At http://apps.owncloud.com for other ownCloud users
.. _On our planning page: http://gitorious.org/owncloud/pages/Home
.. _mailing list: http://mail.kde.org/mailman/listinfo/owncloud

View File

@@ -0,0 +1,104 @@
Contribution Guidelines
=======================
How you can contribute:
-----------------------
* `Report an issue on our bug tracker`_
* `Translate ownCloud to your language`_
* Help coding (see below) and check the `Junior Jobs`_
* `Develop Apps`_, if you're looking for ideas you can check what users reported at the `App Opportunities Page`_.
* Help out with the website and write documentation (contact tpn or deryo in the irc channel)
* Spread the word, tell your friends about it, write a blog post!
If you have any questions, `we are happy to help you`_.
Set up your development environment
-----------------------------------
#. Install git, for example by: ``sudo apt-get install git``
#. The following folder structure is suggested:
.. code-block:: bash
/path/to/webserver/owncloud - core repo
/path/to/webserver/apps - apps repo
/path/to/webserver/3rdparty - 3rdparty repo
- Open a terminal and:
.. code-block:: bash
cd /path/to/webserver
git clone https://github.com/owncloud/core ./owncloud
git clone https://github.com/owncloud/apps
git clone https://github.com/owncloud/3rdparty
- ownCloud will automatically detect the 3rdparty folder if it's either in /path/to/webserver/owncloud or in /path/to/webserver/.
#. If you want to use an app from the app repository, you have to `setup multiple app directories`_ or symlink each app like e.g.
.. code-block:: bash
ln -s /path/to/webserver/apps/news /path/to/webserver/owncloud/apps/news
#. `Install ownCloud`_
#. Dive into the code!
If you are new to git, do the `git crash course`_.
Contribution guidelines
-----------------------
* We use `Github`_, get an account there and clone the ownCloud repository
* Please check `our planning page`_ and ideally communicate your ideas to the `mailing list`_
* fixes go directly to master, nevertheless they need to be tested thoroughly
* new features are always developed in a branch and only merged to master once they are fully done
* when you are finished, use the merge request function on Gitorious. The other developers will look at it and give you feedback. Ideally also post your merge request to the mailing list to let people know.
* when you ``git pull``, always git ``pull --rebase`` to not generate extra commits like: *merged master into master*
* We need a signed contributor agreement from you to commit into the core repository. But no worries. It' a nice one. All the information is `here`_
Design guidelines
-----------------
* Software should work. Only put features into master when they are complete. It's better to not have a feature instead of having one that works poorly.
* Software should get out of the way. Do things automatically instead of offering configuration options.
* Software should be easy to use. Show only the most important elements. Secondary elements only on hover or via Advanced function.
* User data is sacred. Provide undo instead of asking for confirmation `which might be dismissed`_.
* The state of the application should be clear. If something loads, provide feedback.
* Do not adapt broken concepts (for example design of desktop apps) just for the sake of consistency. We provide a better interface.
* Regularly reset your installation to see how the first-run experience is like. And improve it.
* Ideally do `usability testing`_ to know how people use the software.
* For further UX principles, read `Alex Faaborg from Mozilla`_.
Coding guidelines
-----------------
* use tabs, not spaces
* java doc style documentation always required!
* function names in camelCase starting with a lower character
* class names are CamelCase starting with an upper case character
* opening brackets in the same line as the statement
* closing brackets in a sepearate line
* no global variables
* no global functions
* double quotes in HTML, single quotes in JavaScript & PHP
* HTML should be HTML5 compliant
* CSS in single-line notation
* provide unit tests
.. _Report an issue on our bug tracker: https://github.com/owncloud/core/issues
.. _Translate ownCloud to your language: http://owncloud.org/dev/translation/
.. _Junior Jobs: http://owncloud.org/dev/junior-jobs/
.. _Develop Apps: http://owncloud.org/dev/apps/getting-started/
.. _App Opportunities Page: http://bugs.owncloud.org/thebuggenie/owncloud/issues/find/saved_search/4/search/1
.. _we are happy to help you: http://owncloud.org/contact/
.. _setup multiple app directories: https://github.com/owncloud/documentation/blob/master/developer_manual/configfile.rst
.. _git crash course: http://git-scm.com/course/svn.html
.. _Github: https://github.com/owncloud
.. _our planning page: http://gitorious.org/owncloud/pages/Home
.. _mailing list: https://mail.kde.org/mailman/listinfo/owncloud
.. _here: http://owncloud.org/about/contributor-agreement/
.. _which might be dismissed: http://www.alistapart.com/articles/neveruseawarning/
.. _usability testing: http://jancborchardt.net/usability-in-free-software
.. _Alex Faaborg from Mozilla: http://uxmag.com/articles/quantifying-usability
.. _Install ownCloud: https://github.com/owncloud/core/issues

View File

@@ -0,0 +1,73 @@
Hooks
=====
In ownCloud apps, function or methods (event handlers) which are used by the app and called by ownCloud core hooks, are generally stored in apps/appname/lib/hooks.php.Hooks are a way of implementing the `observer pattern`_, and are commonly used by web platform applications to provide clean interfaces to third party applications which need to modify core application functionality. In ownCloud, a hook is a function whos name can be used by developers of plug-ins to ensure that additional code is executed at a precise place during the execution of other parts of ownCloud code.For example: when an ownCloud user is deleted, the ownCloud core hook post_deleteUser is executed. In the calendar apps appinfo/app.php, this hook is connected to the apps own event handler deleteUser (user here refers to an ownCloud user; deleteUser deletes all addressbooks for that a given ownCloud user). When post_deleteUser calls the calender apps deleteUser event handler, it supplies it with an argument, which is an array containing the user ID of the user that has just been deleted. This user ID is then used by the event handler to specify which address books to delete. There are three components to the use of hooks in this example:
#. The ownCloud core hook post_deleteUser, (see what arguments / data it will provide in lib/user.php, where it is defined)
#. The event handler deleteUser, (defined in apps/contacts/lib/hooks.php)
#. The connection of the hook to the event handler, in apps/contacts/appinfo/app.php
ownCloud uses the following hook terminology:
* Signal class / emitter class: the class that contains the method which contains the creation of the hook (and a call to the emit() method) e.g. OC_User
* Signal / signal name: the name of the hook, e.g. post_deleteUser
* Slot class: class housing the event handling method, e.g. OC_Contacts_Hooks
* Slot name: event handler method, e.g. deleteUser (function that deletes all contact address books for a user)
ownCloud core provides the following hooks:
File: apps/calendar/ajax/events.php, Class: OC_Calendar
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Hook: getEvents
File: apps/calendar/index.php, Class: OC_Calendar
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Hook: getSources
File: dav.php, Class: OC_DAV
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Hook: initialize
File: lib/migrate.php, Class: OC_User
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Hook: pre_createUser
* Hook: post_createUser
File: lib/filecache.php, Class: OC_Filesystem
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Hook: post_write
* Hook: post_write
* Hook: post_delete
* Hook: post_write
File: lib/user.php, Class: OC_User
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Hook: pre_createUser
* Hook: post_createUser
* Hook: pre_deleteUser
* Hook: post_deleteUser
* Hook: pre_login
* Hook: post_login
* Hook: logout
* Hook: pre_setPassword
* Hook: post_setPassword
File: lib/group.php, Class: OC_Group
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Hook: pre_createGroup
* Hook: post_createGroup
* Hook: pre_deleteGroup
* Hook: post_deleteGroup
* Hook: pre_addToGroup
* Hook: post_addToGroup
* Hook: pre_removeFromGroup
* Hook: post_removeFromGroup
.. _observer pattern: https://en.wikipedia.org/wiki/Observer_pattern

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

View File

@@ -1,18 +1,35 @@
.. _contents:
Contents
========
.. toctree::
:maxdepth: 2
debugging
apps
Indices and tables
==================
* :ref:`genindex`
.. _contents:
Contents
========
.. toctree::
:maxdepth: 2
debugging
apps
guidelines
styleguide
codereviews
kanban
translation
testing
database
getting_started
filesystem
hooks
theming
formfactors
dialogs
share-api
data-migration
access
unit-testing
compatibility
Indices and tables
==================
* :ref:`genindex`

151
developer_manual/kanban.rst Normal file
View File

@@ -0,0 +1,151 @@
Kanban Board
============
*This page contains a lot of information about the development process the ownCloud community tries to follow, so please take your time to digest all the information. In any case remember this page as the documentation on how it should be done. Nothing here is set in stone, so if you think something should be changed please discuss it on the mailing list.*
Kanban Board = github issues + huboard
--------------------------------------
We are using http://huboard.com to visualize ownCloud github issues as a `kanban board`_ (see: `core`_, `apps`_, `mirall`_):
.. image:: images/kanbanexample.png
As you may have noticed, the columns of the kanban board represent the life-cycle of an issue (be it a Bug or an Enhancement). An issue flows from the 1 - Backlog on the left to the 7 - To release column on the right and is not closed until it has been released. Instead we pull an issue to the next column by changing the label. The following tables will tell you what the labels mean in the life-cycle and will hopefully help you decide how to label an issue.
Backlog
-------
**Why do we have it?** To keep us focused on finishing issues that we started, new issues will be hidden in this column. In huboard you can see the list of things that we could think about by clicking the small arrow in the top left corner of the concept column header.
**What does a developer think?** Maybe later.
**When can I pull?** Since this is the bucket for whatever might be done you should only pick issues from the backlog when there is no other issue that you can work on. It is more important to finish an issue currently on the Kanban board than to pull a new one into the flow because only released issues have a value to our users!
**Who is Assigned?** Either a maintainer feels directly responsible for the issue and assigns himself or the gatekeeper (the guys having a look at unassigned bugs) will try to determine the responsible developer.
Concept
-------
**Why do we have it?** Our think before you act phase serves two purposes. A Bug is in the concept phase while we are trying to figure out why something is broken (analysis). An Enhancement is in the concept phase until we have decided how to implement it (design).
**What does a developer think?** *Ill write a Scenario for our BDD in `Gherkin`_ and post it as a comment. I can always look at the `existing ones`_ to get an inspiration how to phrase them as `“Given … when … then …“`_*
**When can I pull?** As long as you think and discuss on how to implement an enhancement or how to solve a bug you should leave the concept label assigned. Two things should be documented in a comment to the issue before moving it to the “To develop” step:
* At least one Scenario written in Gherkin that tells you and the tester when the issue is ready to be released.
* A concept describing the planned implementation. This can be as simple as a “this just needs changes to the login screen css” or so complex that you link to a blog entry somewhere else.
**Who is Assigned?** The maintainer that feels responsible for the issue.
To Devolp
---------
**Why do we have it?** Now that we have a plan, any developer can pick an issue from this column and start implementing it. If the issue is also marked with Junior Job this might be a good starting point for new developers.
**What does a developer think?** *Nice! I can safely implement it that way because more than one person has put his brain to the task of coming up with a good solution. Here! Me! Ill do it!*
**When can I pull?** If you feel like diving into the code and getting your hands dirty you should look for issues with this label. In the comments, there should be a gherkin scenario to tell you when you are done and a concept describing how to implement it. Before you start move the issue to the “Developing” step by assigning the “4 Developing” label.
**Who is Assigned?** No one. Especially not if you are working on something else!
Developing
----------
**Why do we have it?** This is where the magic happens. If its a Bug the fix will be submitted as a PULL REQUEST to the master or corresponding stable branch. If its an Enhancement code will be committed to a feature branch.
**What does a developer think?** *You know, Im at it. By the way, Ill also write `unit tests`_. When Im done Ill push the issue with a commit containing “push GH-#” where # is the issue number. If I have an idea of who should review it I can also notify them with @githubusername*
**When can I pull?** As long as you are writing code for the issue or if any unit test fails you should leave the “4 Developing” label assigned. Two things should have been implemented before moving the issue to the “To review” step:
* The enhancement or bug in question
* Unit tests for the changed and added code.
**Who is Assigned?** The most active developer should assign himself.
To Review
---------
**Why do we have it?** Instead of directly committing to master we agree that **a second set of eyes will spot bugs** and increase our code quality and give us an opportunity to learn from each other. See also our `Code Review Documentation`_
**What does a developer think?** *Ill check the Scenario described earlier works as expected. If necessary Ill update the related Gherkin Scenarios. `Jenkins`_ will test the scenario on all kinds of platforms, webserver and database combinations with `cucumber`_.*
**When can I pull?** If you feel like making sure an issue works as expected you should look for issues with this label. In the comments you should find a gherkin scenario that can be used as a checklist for what to try. Before you start move the issue to the “Reviewing” step by assigning the “6 Reviewing” label.
**Who is Assigned?** No one. Especially not if you are working on something else!
Reviewing
---------
**Why do we have it?** With the Gherkin Scenario from the Concept Phase reviewers have a checklist to test if a Bug has been solved and if an Enhancement works as expected. **The most eager reviewer we have is Jenkins**. When it comes to testing he soldiers on going through the different combinations of platform, webserver and database.
**What does a developer think?** *Damn! If I had written the Gherkin Scenarios and Cucumber Step Definitions I could leave the task of testing this on the different combinations of platform, webserver and database to Jenkins. Ill miss something when doing this manually.*
**When can I pull?** As long as you are reviewing the issue the you should leave the “6 Reviewing” label assigned. Before moving the issue to the “To review” step the issue should have been resolved, meaning that not only the issue has been implemented but also no other functionality has been broken.
**Who is Assigned?** The most active reviewer should assign himself.
To Release
---------
**Why do we have it?** This is a list of issues that will make it into the next release. It serves as a source for the changelog, as well as a reminder of the work we can already be proud of.
**What does a developer think?** *Look at all the shiny things we will release with the next version of ownCloud!*
**When can I pull?** This is the last step of the Kanban board. When the Release finally happens the issue will be closed and removed from the board.
**Who is Assigned?** No one.
*I said that we push issues to the next column. Of course the issue can go back and forth arbitrarily. Basically you can drag the issue around in the huboard or just change the label when viewing the issue in the github.*
Reviewing considered impossible?
--------------------------------
How can you possibly review an issue when it requires you to test various combinations of browsers, platforms, databases and maybe even app combinations? Well, you cant. But you can write a gherkin scenario that can be used to write an automated test that is executed by Jenkins on every commit to the main repositories. If for some reason Jenkins cannot be used for the review you will find yourself in the very uncomfortable situation where you release half tested code that will hopefully not eat user data. Seriously! Write gherkin scenarios!
Other Labels
------------
Priority Labels
~~~~~~~~~~~~~~~
* Panic should be used with caution. It is reserved for Bugs that would result in the loss of files or other user data. An Enhancement marked as Panic is expected by ownCloud users for the next release. In either case an open Panic issue will prevent a release.
* Attention is not as hard as Panic. But we really want this in the next release and will dedicate more effort for it. But if we think the issue is not ready for the next release we will postpone it to the next one.
* Regression is something that worked in a previous release but is now not working as expected or missing. If a certain functionality is up for code refactoring, the developer should describe all possible use cases as a Gherkin scenarios beforehand, so that any scenarios that isnt implemented before the required milestone can be marked as a regression. If a regression is found after a release, the reporter or the developer triaging the issue should describe the functionality as a Gherkin scenario and either fix it or assign it to the developer in charge of that part.
App Labels
~~~~~~~~~~
In the apps repository there are labels like app:gallery and app:calendar. The “app:” prefix is used to allow developers to filter issues related to a specific app.
Resolution Status
~~~~~~~~~~~~~~~~~
* Fixed Should be assigned to issues in to Release
* Wont fix Reason is given as a comment
* Duplicate Corresponding bug is given in a comment (using #guthubissuenumber)
Misc Labels
~~~~~~~~~~~
* Needs info Either from a developer or the bug reporter. This is nearly as severe as Panic, because no further action can be taken
* L18n A translation issue go see our `transifex`_
* Junior Job The issue is considered a good starting point to get involved in ownCloud development
Milestones equal Releases
-------------------------
Releases are planned via milestones which contain all the Enhancements and Bugs that we plan to release when the Deadline is met. When the Deadline approaches we will push new Enhancement request and less important bugs to the next milestone. This way a milestone will upon release contain all the issues that make up the changelog for the release. Furthermore, huboard allows us to filter the Kanban board by Milestone, making it especially easy to focus on the current Release.
.. _kanban board: http://en.wikipedia.org/wiki/Kanban_board
.. _core: http://huboard.com/owncloud/core/board/#
.. _apps: http://huboard.com/owncloud/apps/board/#
.. _mirall: http://huboard.com/owncloud/mirall/board/#
.. _Gherkin: https://github.com/cucumber/cucumber/wiki/Gherkin
.. _look at the existing ones: https://ci.tmit.eu/job/acceptance-test/cucumber-html-reports/?
.. _“Given … when … then …“: https://github.com/cucumber/cucumber/wiki/Given-When-Then
.. _unit tests: https://github.com/owncloud/core/tree/master/tests
.. _Code Review Documentation: http://owncloud.org/dev/code-reviews-on-github/
.. _Jenkins: https://ci.tmit.eu/
.. _cucumber: http://cukes.info/
.. _transifex: https://www.transifex.com/projects/p/owncloud/

View File

@@ -0,0 +1,138 @@
Share API
=========
**Warning: The Share API is still under heavy development and testing. Report issues to Michael Gapczynski.**
The Share API was introduced in ownCloud 5 as a public API for apps to share content. It is a revision of the original file sharing app with enhancements to increase stability, reduce conflicts, and operate in a generic fashion. At this time it is possible to share content with local ownCloud users, groups, contacts, and email via link. This document is a guide for using the Share API in apps. The Share API is made up of a public class OCP\Share in ``/lib/public/share.php``, an AJAX file ``/core/ajax/share.php``, and a JavaScript file ``/core/js/share.js``. Javadoc style documentation is included in OCP\Share.
Share backends
--------------
The share backends represent a shared item type and are responsible for communicating directly with the Share API. There are 3 interfaces that can be implemented from based on the type of shared item. Apps create a class that implements one of the below interfaces and registers it with the Share API. Item source is a unique identifier of an item to be stored in the database by the Share API. The backend needs to be able to translate the item source back into the original item. It is recommended that the item source is the id of the item in the apps own database.
OCP\Share_Backend
~~~~~~~~~~~~~~~~~
The base interface for shared items. The other interfaces extend OCP\Share_Backend.
* isValidSource($itemSource, $uidOwner)
* generateTarget($itemSource, $shareWith, $exclude = null)
* formatItems($items, $format, $parameters = null)
**isValidSource($itemSource, $uidOwner)** Return true if the ``$itemSource`` is found and belongs to the owner, otherwise false. This function should not check for shared items, the Share API automatically recognizes a reshare and does not call isValidSource(). If false, the Share API will cancel sharing the item.
**generateTarget($itemSource, $shareWith, $exclude = null)** Return a unique name for the $itemSource that can be used as a target. This is the name of the item that will be displayed for the person. The Share API will call this function again if the target already exists for the person as a shared item. For the second call, the ``$exclude`` argument will be an array with the conflicting target and similar targets that cant be used as a target. The ``$shareWith`` argument can be false if generating a target for a private link or group. In this case, the function should return the default target.
**formatItems($items, $format, $parameters = null)** Return the items in a format that is customary to the app. The Share API calls this function when a backend specific format is requested in one of the functions used for retrieving shared items. The return of this function is completely up to the backend, but the name of the items needs to be overridden by the target values. The desired implementation is to keep logic inside the backend and use array_merge() to merge shared items with normal items in the app.
OCP\Share_Backend_File_Dependent
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The interface for shared items that are depedent on a file e.g. a song or photo.
* getFilePath($itemSource, $uidOwner)
* Extends OCP\Share_Backend
**getFilePath($itemSource, $uidOwner)** Return the file path if the item source is found and belongs to the owner, otherwise false.
OCP\Share_Backend_Collection
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The interface for shared items that are collections of another shared item e.g. a folder or addressbook.
* getChildren($itemSource)
* Extends OCP\Share_Backend
**getChildren($itemSource)** Return a 2-dimensional array of the children items in the item source collection. Each child should be represented in the array as an array with the keys source and target, with their corresponding values. The children are passed to the backend that represents their item type and therefore should be able to be interpreted by that backend.
Register a backend with the Share API in ``appinfo/app.php``:
.. code-block:: php
OCP\Share::registerBackend('contact', 'OC_Share_Backend_Contact');
Register a file dependent backend by specifying file extensions within an array in the fourth parameter:
.. code-block:: php
OCP\Share::registerBackend('photo', 'OC_Share_Backend_Photo', null, array('gif', 'jpeg', 'jpg', 'png'));
Register a collection backend by specifying the children item in the third parameter:
.. code-block:: php
OCP\Share::registerBackend('addressbook', 'OC_Share_Backend_Addressbook', 'contact');
Apps should not make any explicit calls to a share backend.
Sharing dropdown
----------------
The sharing dropdown is the user interface for sharing content. It handles sharing, unsharing, and setting permissions. Attach the sharing dropdown to the app user interface using an anchor tag:
.. code-block:: php
<a class="share" data-item-type="addressbook" data-item="<?php echo $addressbook['id'] ?>" title="<?php echo $l->t("Share"); ?>" />
Specify the item type with ``data-item-type`` and the item source with ``data-item``. Shared items that dont offer private link support should set ``data-private-link`` to false. At this time any shared item that isnt file dependent is not supported for private links.
Retrieving shared items
-----------------------
Items shared with the current user and shared items owned by the current user can be retrieved using the following public functions:
Get the items of item type shared with the current user:
.. code-block:: php
OCP\Share::getItemsSharedWith('addressbook');
Get the item of item type shared with the current user:
.. code-block:: php
OCP\Share::getItemSharedWith('addressbook', "Michael's Addressbook");
Get the item of item type shared with the current user by item source:
.. code-block:: php
OCP\Share::getItemSharedWith('addressbook', 1);
Get the shared items of item type owned by the current user:
.. code-block:: php
OCP\Share::getItemsShared('addressbook');
Get the shared item of item type owned by the current user:
.. code-block:: php
OCP\Share::getItemsShared('addressbook', 1);
All of the above functions allow you to pass a ``$format`` and an additional ``$parameters`` argument for formatting the items. The ``$format`` argument should be an integer defined as a constant in the backend. There are no restrictions on what the ``$parameters`` argument is. The handling of the function returns will be passed to the formatItems() function in the backend, along with the ``$format`` and ``$parameters`` arguments. Passing a format is useful for keeping the logic in the backend and quickly integrating shared items into the existing app:
.. code-block:: php
$addressbooks = array_merge($addressbooks, OCP\Share::getItemsSharedWith('addressbook', OC_Share_Backend_Addressbook::FORMAT_ADDRESSBOOKS));
Collections of item types can be included when retrieving shared items. Setting ``$includeCollections`` to true will also return the children of collections of the item type. If the app requires a different format for the item type and the collection, separate calls should be made instead.
Handling permissions
--------------------
The Share API is capable of storing permissions associated with an item and the shared person. The permission system is CRUDS (create, read, update, delete, and share) and is an extension of the CRUD model. It is the apps responsibility to handle permission checks and not the Share API. The Share API will ensure that permissions do not exceed those assigned to the original person for reshares. The CRUDS permissions are implemented as constants in the Share API.
* OCP\Share::PERMISSION_CREATE
* OCP\Share::PERMISSION_READ
* OCP\Share::PERMISSION_UPDATE
* OCP\Share::PERMISSION_DELETE
* OCP\Share::PERMISSION_SHARE
Apps should check if permissions are granted when a user with access to a shared item attempts to manipulate the item. Check granted permissions using bitwise operators:
.. code-block:: php
if ($permissions & OCP\Share::PERMISSION_UPDATE)

View File

@@ -0,0 +1,6 @@
Coding Style Guide
==================
See `Coding Style Guidelines`_.
.. _Coding Style Guidelines: http://doc.owncloud.com/server/5.0/developer_manual/codingguidelines.html

View File

@@ -0,0 +1,49 @@
Testing
=======
Testing ownCloud is important to ensure quality and the best possible experience for users. The release cycle is fast and to maintain this speed ownCloud needs continuous testing and involvement from the community. When ownCloud approaches a major release, a formal testing process is organized with specific tasks for testers to confirm as functional. This begins with the first alpha release and will continue through the release candidates. Testers will be assigned tasks, test the pre-releases, and report bugs to the `bug tracker`_. Formal testers will be recognized on owncloud.org as a thank from the entire ownCloud community.ownCloud strives to run on all types of platforms without strict requirements. PHP does not have the same behavior on Linux, OS X, and Windows especially with regards to the filesystem. Differences in behavior can also occur on different web servers. This means that ownCloud needs to be tested on as many server configurations as possible before a major release.
Who can get involved?
---------------------
Anyone can get involved in the formal testing process. No programming experience is necessary. If you would like to get involved and help improve the quality of ownCloud please contact Michael Gapczynski (MTGap) in the `Dev IRC Channel`_. Remember, the quality of ownCloud is not only the responsibility of the developers, but the entire community.
Release Schedule
----------------
* 20.08.12 - Soft feature freeze (Alpha 1)
* 28.08.12 - Hard feature freeze (Beta 1)
* 03.09.12 - Beta 2 Only bugfixes are allowed from now on
* 10.09.12 - RC 1 Only showstopper bugfixes are allowed from now on
* 17.09.12 - RC 2
* 26.09.12 - Announcement of ownCloud 4.5
Testing guidelines
------------------
* Contact Michael Gapczynski if you would like to formally participate in testing
* Inform Michael of your exact server configuration, including OS, PHP version, and database
* Checkout the latest version from the master branch
* Do not install in a production environment, pre-releases may cause data loss
* Run the unit tests in the tests folder and ensure all tests are passing
* Perform your assigned tasks, report any bugs to the `bug tracker`_
* When reporting any bugs to the `bug tracker`_, please specify the pre-release version in the release field.
Tests
-----
Test tasks are categorized by apps, those at the top of the list have priority for testing during this release. While 3rd party apps are not supported by ownCloud, app developers may also request for testing of their apps here.
* `Files`_
* `Sharing`_
* Settings
* Calendar
* Contacts
* Media
* `LDAP user and group backend`_
.. _Files: http://owncloud.org/dev/testing/files
.. _Sharing: http://owncloud.org/dev/testing/sharing
.. _LDAP user and group backend: http://owncloud.org/dev/testing/ldap-backend/
.. _bug tracker: https://github.com/owncloud/core/issues
.. _Dev IRC Channel: http://webchat.freenode.net/?channels=owncloud-dev

View File

@@ -0,0 +1,55 @@
Theming
=======
Themes can be used to customise the look and feel of ownCloud without the need to patch the source code.
Activate
--------
Themes can be placed in the theme folder “/themes” with the name of the theme as foldername. The theme can be activated by putting “theme” => themename, into the config.php file.
Structure
---------
The folder structure of a theme is exactly the same as the main ownCloud structure. You can override js files, images and templates with own versions. css files are loaded additionally to the default files so you can override css properties.
Development
-----------
Themes should be developed here: https://github.com/owncloud/themes You can also find a super simple example `here`_.
How to change images and the logo
---------------------------------
The easiest picture to change in ownCloud is the logo. When you open your browser and point to ownCloud, you will see an ownCloud logo by default. That image can be replaced. We will show you how to do so in this section.There are two pictures to think about:
* owncloud-logo-medium-white.png This is the splash screen logo, appearing above the login page of your ownCloud instance. size: 252w x 122h pixels, approximately, works well. Too much bigger and the logo doesnt fit in the spot on the page
* logo-wide.svg This is the little logo that appears in the top left of the ownCloud navigate frame (SVGs can be created with adobe illustrator with a free 30 day trial, or open source inkscape) 140w x32h pixels. works well. Too much higher and the logo overflows into the navigation pane and looks terrible. The width, however, can be bigger or smaller to meet your needs, whatever works for your logo
To change either of these logos, simply create your own logo file with these characteristics, and put it in you themes folder in core/img/
How to change colors
--------------------
Just put a new style.css into the core/css folder in your themes directory. Changing the header bar colours on the Login and Main Navigation screen: In the style sheet, a bit further down, is a set that looks something like this:
.. code-block:: css
/* HEADERS */
#body-user #header, #body-settings #header { position:fixed; top:0; z-index:100; width:100%; height:2.5em; padding:.5em; background:#1d2d42; -moz-box-shadow:0 0 10px rgba(0, 0, 0, .5), inset 0 -2px 10px #222; -webkit-box-shadow:0 0 10px rgba(0, 0, 0, .5), inset 0 -2px 10px #222; box-shadow:0 0 10px rgba(0, 0, 0, .5), inset 0 -2px 10px #222; }
#body-login #header { margin: -2em auto 0; text-align:center; height:10em;
-moz-box-shadow:0 0 1em rgba(0, 0, 0, .5); -webkit-box-shadow:0 0 1em rgba(0, 0, 0, .5); box-shadow:0 0 1em rgba(0, 0, 0, .5);
background: #1d2d42; /* Old browsers */
background: -moz-linear-gradient(top, #33537a 0%, #1d2d42 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#F1B3A4), color-stop(100%,#1d2d42)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #33537a 0%,#1d2d42 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #33537a 0%,#1d2d42 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, #33537a 0%,#1d2d42 100%); /* IE10+ */
background: linear-gradient(top, #33537a 0%,#1d2d42 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33537a', endColorstr='#1d2d42',GradientType=0 ); /* IE6-9 */ }
#owncloud { float:left; }
This handles the headers for a lot of different browser types. What we want to do is change the #35537a (lighter blue) and #ld2d42 (dark blue) color to the colours of our choice. In some older and other browsers, there is just one color, but in the rest there are gradients.The login page background is a horizontal gradient. The first hex number, #35537a, is the top color of the gradient at the login screen. The second hex number, #ld2d42 is the botton color of the gradient at the login screen.Simply change these colours to the hex color of your choice, save, and refresh to see the new login screen.The other major color scheme is the blue header bar on the main navigation page once you log in to ownCloud. This color we will change with the above as well.Save the file and refresh the browser for the changes to take affect.
.. _here: https://github.com/owncloud/themes/tree/master/example

View File

@@ -0,0 +1,101 @@
Translation
===========
Make text translatable
----------------------
In HTML or PHP wrap it like this <?php echo $l->t('This is some text');?>
For the right date format use <?php echo $l->l('date', time());?>. Change the way dates are shown by editing /core/l10n/l10n-[lang].php
To translate text in javascript use: t('appname','text to translate');
You shall never split sentences!
--------------------------------
Reason:
~~~~~~~
Translators loose the context and they have no chance to possible re-arrange words.
Example:
~~~~~~~~
.. code-block:: php
<?php echo $l->t('Select file from') . ' '; ?><a href='#' id="browselink"><?php echo $l->t('local filesystem');?></a><?php echo $l->t(' or '); ?><a href='#' id="cloudlink"><?php echo $l->t('cloud');?></a>
Translators will translate:
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Select file from
* local filesystem
* ' or "
* cloud
By translating these individual strings for sure the case will be lost of local filesystem and cloud. The two white spaces with the or will get lost while translating as well.
Html on translation string:
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Html tags in translation strings is ugly but usually translators can handle this.
What about variable in the strings?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In case you need to add variables to the translation strings do it like that:
.. code-block:: php
$l->t('%s is available. Get <a href="%s">more information</a>',array($data['versionstring'], $data['web']));
Automated synchronization of translations
-----------------------------------------
Multiple nightly jobs have been setup in order to synchronize translations - it's a multi-step process:
``perl l10n.pl read`` will rescan all php and javascript files and generate the templates.
The templates are pushed to `Transifex`_ (tx push -s).
All translations are pulled from `Transifex`_ (tx pull -a).
``perl l10n.pl write`` will write the php files containing the translations.
Finally the changes are pushed to git.
Please follow the steps below to add translation support to your app:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create a folder ``l10n``.
Create the file ``ignorelist`` which can contain files which shall not be scanned during step 4.
Edit ``l10n/.tx/config`` and copy/past a config section and adopt it by changing the app/folder name.
Run ``perl l10n.pl read`` with l10n
Add the newly created translation template (l10n/Templates/<appname>.pot) to git and commit the changes above.
After the next nightly sync job a new resource will appear on Transifex and from now on every night the latest translations will arrive.
Translation sync jobs:
~~~~~~~~~~~~~~~~~~~~~~
http://ci.tmit.eu/job/ownCloud-core-tx/
http://ci.tmit.eu/job/ownCloud-apps-tx/
http://ci.tmit.eu/job/ownCloud-Mirall-tx/
**Caution: information below is in general not needed!**
Manual quick translation update:
--------------------------------
.. code-block:: bash
cd l10n/ && perl l10n.pl read && tx push -s && tx pull -a && perl l10n.pl write && cd ..
The translation script requires Locale::PO, installable via ``apt-get install liblocale-po-perl``
Configure transifex
-------------------
.. code-block:: bash
tx init
for resource in calendar contacts core files media gallery settings
do
tx set --auto-local -r owncloud.$resource "<lang>/$resource.po" --source-language=en \
--source-file "templates/$resource.pot" --execute
done
.. _Transifex: https://www.transifex.net/projects/p/owncloud/

View File

@@ -0,0 +1,17 @@
Unit Testing
============
ownCloud uses the `SimpleTest`_ PHP unit testing framework for monitoring code stability. As much of ownCloud as possible should be covered by unit tests, including 3rd party apps.
View unit test results in a web browser by accessing the ``/tests`` directory. The current results for the public dev demo ownCloud server (running about 5 mins behind git master) can be viewed at http://demo.owncloud.org/dev/tests/. In development versions of ownCloud tests can also be run from the command-line. To do so execute ``php -f index.php`` from within the ``/tests`` directory, with appropriate permissions.
SimpleTest has been configured for easy unit testing of ownCloud apps. The ``tests`` folder within an app root directory should be used to store unit tests and any data that they use. These tests will be run automatically when ``/tests`` is accessed.
You can run only a selected number of tests by passing a parameter as prefix-filter for the tests. When running from the browser, the ``test`` GET variable is used, when running from command-line it is passed as command line argument. For example, the tests from the ``files_archive`` app can be viewed at http://demo.owncloud.org/tests/?test=/apps/files_archive or by executing ``php -f index.php /apps/files_archive`` from the command-line.
Apps which modify core ownCloud functionality can extend test cases which already exist within ``/tests/lib``. For an example of an app unit test which extends an existing unit test, see ``/apps/files_archive/tests/storage.php``. Apps which make use of public ownCloud functions, for getting logged-in user information for example, can use dummy classes which have been provided for this purpose, such as ``/lib/user/dummy.php``.
For information about writing tests, see `SimpleTest documentation`_.
.. _SimpleTest: http://simpletest.org/
.. _SimpleTest documentation: http://simpletest.org/en/start-testing.html