+------------------+ | LCC Drivers | +------------------+ So you want to write your own driver? Thats fine! You will soon find out that this is not as complicated as it sounds. Please see the chapter for what kind of driver you want to write: I. General II. Driver loading, configuration and initialisation III. UserDriver IV. EventDriver V. NoteDriver I. General ------------ Before reading on, be sure that you have read "drivers/whats_this.txt". To implement your own driver, the following conditions must be met: 1. Your class must be a subclass of 'LCC_<drivertype>' (You don't need to include that parent class yourself, it is loaded within LCC core) 2. The name of the class file must be '<yourname>.class.php' 3. The Name of the class must be "LCC_<drivertype>_<yourname>" 4. The classfile must be placed inside the correct subdirectory (e.g. "drivers/event" for EventDrivers) 5. The filename is expected lowercase 6. All required driver methods must be implemented as defined below <drivertype> is one of 'EventDriver' or 'UserDriver' and <drivername> is a free, case sensitive name of your choice (but should be meaningful) Example: To implement a UserDriver called "File": The class file would be 'drivers/user/file.class.php'. Inside this File, a class must be defined: 'LCC_UserDriver_File'. This can be loaded into the core using: "$lcc_core->loadUserDriver('File')". It is important, that the drivers interfaces (eg the function parameters and return values) are exactly as specified here, because otherwise the core will crash or in the best case only do weird things. Please write some documentation what the driver is capaple of and what configuration items exist so people know what to do to use the driver correctly. The proper place for this is the class level phpdoc documentation block. If you are done with your driver, you can configure the core (e.g. lcc_standalone.php) so it uses your newly written driver! Maybe you might want to share your driver with us. Feel free to send us a quick email or open a support ticket at the soruceforge bugtracker. For detailed use and design of the neccesary methods you should also refer to the already written drivers. A good start for UserDrivers is the UserDriver_Simple. II. Driver loading, configuration and initialisation ------------------------------------------------------ The driver loading happens in several steps performed by LCC_Core: 1. creating instance of selected driver (calling constructor of drivers class) 2. storing reference to LCC_Core in object variable $lcc_core 3. custom init of driver (calling init() of the driver object if exists) 4. overwriting default config of driver with real values (calling setConfig() of parent class) 5. custom configuration of driver (calling configure() of the driver object if exists) You must provide some default configuration via a class variable called "$config" (is an array, see below) The core will always make a new empty instance of a driver and call the inherited method $object->setConfig() to initialize the drivers configuration, so be sure to acces your config via $this->config. Configuration means that the default config is overwritten with the real config desired by the user. A drivers configuration is always an array containing at most one additional array dimension. If the second dimension is left an empty array, dynamic keys are assumed. Otherwise a strict schema check will be performed. A drivers configuration may look like: $config = array( 'key1' => 'default_value1', 'key2' => array('subkey1' => 'subval1', 'subkey2' => 'subval2'), 'key3' => array() ); Here, key1 and key2 have both default values assigned which imposes strict checks. key3 however, has only the definition, that it must be an array so dynamic keys are assumed. Dynamic keys should not be used for hard coded keys needed by the driver but instead be used to story dynamic data for the driver. An example is the storage of usernames and groups of the simple user driver. Because the core always uses the same driver instance, you are free to define your own class variables to store everything you like. Please don't forget to ensure that your config is reasonable. If you define a filepath, for example, you must make sure that this file is accessible prior using it. LCC_Core stores a reference to itself in the drivers class variable $lcc_core, so you have access to the core configuration items if neccessary. You may implement a custom constructor, since the core always creates a instance of the driver class to be able to use the defined class variables. The core calls the constructor without parameters. However, the problem with the constructor is, that neither the driver is configured (only default config values are accessible) nor is the reference to $lcc_core set. For this reason, it is in 99% of the cases better to implement a configure() (or maybe a init()) method. The init() and configure() methods are called also without parameters. III. UserDriver --------------- To write your own UserDriver, you must extend the LCC_UserDriver class. The UserDriver is the part that establishes the connection between the events and the external application. This is what enables LCC to use the user management of nearly any other application. The driver's default config must be stored in a class variable named "$config" which is an array. If you want to write a new UserDriver, you must at least define the following methods: - fetchLogin() This method is used by the core to get the username of the currently logged in user in the external application. For example, the getLogin() method could be able to fetch the username from a session variable or a cookie. If you cannot fetch the username for some reason, return false. You may implement some custom login mechanism here if you want. - getGroups($username) The return value must be a one dimensional array of names of groups the user is part of. If there are no groups, return an empty array. On error return false - getGroupsLeaded($username) The return value is similar to getGroups() but only contains the names of groups the user is leader of. If there are no groups in the backend or the user has no groups, return an empty array. If an error occurs, return false. - getGroupMembers($groupname) Used to fetch all members of a specific group. Return always an array containing the usernames of the members, even if the group is empty. (empty array in this case) On error return false. - getLevel($username) Returns the Level of the user - a simple integer. As a convention, use the following convention: Level == 0: Unauthorized users (anonymous) Level > 0: Authorized users Level >= 50: Moderators or something like that Level == 100: Administrators But of course you can implement your own convention. In every case DOCUMENT what levels are returned!!! Be sure to document what levels your driver will fetch! Return false on error. Also, be sure to read "configuring_lcc.txt" to review the default ACL of LCC. IV. EventDriver --------------- To write your own EventDriver, you must extend the LCC_EventDriver class. The driver's default config must be stored in a class variable named "$config" which is an array. The ID of the events should be a INT but strings are also supported by LCC. The following class methods will be called from the core, but you are free to implement additional ones: - getEventsForDate($timestamp) This is used by the core to see if there are events for a specific date, and if so, to become access to that events ids. $timestamp is a traditional UNIX timestamp. Please note that LCC asks the start of a day (00:00). Return value must be an indexed Array containing the ID's of events for that day. Return false on error. - getData($id) Used by the core to fetch all available data from the event $id from the backend. The return value must be a associative array containing $key => $value pairs. If there is no such event in the backend, return false - this will be used by the core to test if a event exists. - storeData($id, $data) This method is used to write data into the backend. $data is a associative array similar to the return value of getData(), say field names as array key and field values as value of that array key. This method must be written in such a way, that every field can be stored. If $id is empty (= false, null or '') or not present in the backend, a new event must be created. Otherwise the present data must be updated. Return the $id of the written (or created) event or false, depending if storage succeedet - deleteEvent($id) This is used to delete this specific event in the backend. Return true or false, depending on success. Keep security in mind when writing drivers! Check all parameters for proper format! The core uses the id's the driver define, so ensure that $id is always valid prior writing/reading anything! If you want to fetch data manually, you should always use getAllData()since getData() only returns stored data. getAllData() do security checks and also assign some meta data. V. NoteDriver ------------- To write your own NoteDriver, you must extend the LCC_EventDriver class. The driver's config must be stored in a class variable named "$config" which is an array. Note drivers serve the purpose to store and get notes data - this is text data along with some metadata. - getNotes($event_id) Returns the IDs of all notes of a specific event $event_id. Return always an array but false if an error occurs. - getData($id) Used by the core to fetch all available data from the note $id from the backend. The return value must be a associative array containing $key => $value pairs. If there is no such event in the backend, return false - this will be used by the core to test if a event exists. - storeData($id, $data) This method is used to write data into the backend. $data is a associative array similar to the return value of getData(), say field names as array key and field values as value of that array key. This method must be written in such a way, that every field can be stored. If $id is empty (= false, null or '') or not present in the backend, a new note must be created. Otherwise the present data must be updated. Return the $id of the written (or created) event or false, depending if storage succeedet - deleteNote($id) This deletes a specific note. Return false or true, depending on success. If you want to fetch data manually, you should always use getAllData() since getData() only returns stored data. getAllData() do security checks and also assign some meta data.