User:Dv - Gallery Codex
Personal tools


From Gallery Codex

Integration Manager

The idea of this project is to create a module to help automate one of the most common of integration tasks: userbase synchronization. Each integration (e.g. G2 in Drupal) has to synchronize its Drupal users with the G2 users. This is about minimizing the amount of code that has to be written per new integration. This module will be a common point for synchronization logic.

Stories and Use Cases

You can find all the user stories and use cases here.

Overall User Story

Bob downloads Gallery 2 to integrate into his current supported emApp. He installs an existing G2 integration module into his emApp. He then configures it so that it may find G2. He then configures it so that it may find G2. The integration will then automatically check if the version of the G2 installation is compatible, check if the Integration Manager Module is active and if not, try to install and activate it. It will proceed to register its implementation of the user synchronization class with G2 which also includes default values for the synchronization options. At this point, the integration synchronizes special users first (admin and anonymous/guest.) Once the synchronization process is initiated, Bob sees a progress bar, and waits for syncing to complete. Once this is done, he is taken back to the status view. There a list of conflicts/errors is presented. If there had been no errors, it would have transparently gone from a "dry run" to actual commitment of synchronization. If there are conflicts/errors, an option to manually correct any error in the user mapping is available. Once this is done, he proceeds with a real synchronization run.

Status View User Story

Bob goes to the status view from G2 admin. The status view is currently indicating that Bob has not done a user synchronization before. It also indicates there are currently no known conflicts. Furthermore, it currently states no users listed in G2 aren't listed in emApp. He selects the synchronization view. He changes the defaults to select the option to make G2 the master for user synchronization, which will override user data in emApp if there are any conflicts. He clicks the "Synchronize" button, which does a dry run to better prepare for any errors or conflicts that may occur.

Use Cases

Anthony Administrator Wants To Synchronize

  1. Selects the synchronization view from the embed module's main admin view.
  2. Clicks the "Synchronize" button to commence a dry run of synchronizing.
  3. This dry run completes and shows any conflicts/errors on the module's main admin view, known as the status view.
  4. If no conflicts had occured, would have begun second round for commitment automatically.

Anthony Wants to Solve Conflicts

  1. If any, the list of conflicts is presented to him in the status view.
  2. There are mass resolution options to ignore certain user properties such as fullName, email, password, language, etc.
  3. Once conflicts list is empty, Anthony proceeds to the synchronization view and the Synchronization button allows him to a do a dry run -- which should now produce no conflicts -- and then automatically perform a commit run at this point.
  4. If conflicts aren't empty and Anthony still wants to commit, he goes to the synchronization view and checks the "Ignore remaining conflicts" option. He proceeds to hit the Synchronize button and the commit run is executed immediately. (To be revised.)

Isaac Integrator Wants To Make His Code Embed-module Compatible

  1. registerFactoryImplementation() on UserSynchronizationInterface_1_0. Integrators will find interface in: modules/embed/classes/UserSynchronizationInterface_1_0.class
  2. Implements necessary functions in UserSynchronizationInterface_1_0. Once the synchronizeUsers() method is called, will instantiate the registered implementation via newFactoryInstance().

Class Definitions

This module is divided up into two parts. A GalleryEmbedSynchronization class that contains all the necessary logic for this project, and one interface for integrations to use to communicate with this module. Below you will find the specifications for these classes.


This class must be instantiated. The first call must be to init() to set up the class. If the integration coder wishes to override any options the user may have selected via a view, they can call the setOptions() method.


array _g2Users

    List of all users in G2 as GalleryUser objects.

array _emAppUsers

    Array of users in emApp in the format of GalleryUser::getMemberData().

array _options

    * Synchronize options will be carried in this variable.
    * @var array('ignorePasswordMismatches' => bool, 'ignoreLanguageMismatches' => bool,
    *              'allowExternalIdMapAdditions' => bool)

array _conflicts

    * Conflict array. Contains one or more of the following types of arrays.
    * @var array('type' => CONFLICT_USERDATA, 'g2User' => $g2UserData, 'emAppUser' =>
    *          $emAppUserData)
    * OR
    *      array('type' => CONFLICT_ORPHAN, 'entityId' => $entityId, 'message' => $message)



    * Init function. Sets up class-related options.
    * @return object GalleryStatus


    * Add a conflict to the conflicts array.
    * This function performs basic validation checks before passing on the data to the conflict
    * array. If 'type' == CONFLICT_ORPHAN, will show first param as an id of some sort and second
    * param as an error message in which first param is involved. If 'type' == CONFLICT_USERDATA,
    * will compare them by key/value pairs, because they're two conflicting user arrays.
    * @param array('type' => CONFLICT_USERDATA, 'g2User' => $g2UserData, 'emAppUser' =>
    *          $emAppUserData)
    *        OR
    *        array('type' => CONFLICT_ORPHAN, 'entityId' => $entityId, 'message' => $message)
    * @return object GalleryStatus


    * A function to retrieve all conflicts in $this->_conflicts
    * @return array(object GalleryStatus, array $this->_conflicts) 

compareUsers($g2User, $emAppUser, $params)

    * Compare a G2 user with an integration app user by user properties.
    * Set any or all of the array params to true to compare by those properties.
    * If 'case' is true, then compare will be case-sensitive. 'case' is determined within this
    * function by calling UserSynchronizationInterface_1_0::isCompareCaseSensitive().
    * @param object GalleryUser
    * @param array ('userName' => string the user name, 'fullName' => string full name,
    *              'email' => string user's e-mail, 'language' => string user's language,
    *              'hashedPassword' => string user's hashed password)
    * @param array('byUserName' => bool, 'byEmail' => bool, 'byLanguage' => bool,
    *              'byFullName' => bool, 'byHashedPassword' => bool, 'case' => bool)
    * @return array('userName' => 1, 'email' => 1, etc.) Any conflicts are entered here.


    * Set options via this method. Can be used by integration coders to override any user-selected
    * options.
    * @param array(any options from $this->_options => appropriate value)


    * Synchronize $this->_emAppUsers and $this->_g2Users
    * @param bool isDryRun determines if we are doing a dry run to check for errors
    * @return array object GalleryStatus a status code
    *         array results array (..., 'g2Users' => $this->_g2Users)
    This function instantiates the following class:
       list($ret, $this->_emApp) =


This is the interface which the integrator will use to implement integration app-related (emApp-related) tasks such as creating, deleting, and updating users in the emApp.



    * Create a user in the emApp with the supplied user data and return the id of the new user.
    * @param array new user data ('userName' => string, 'fullName' => string, 'email' => string,
    *                              'language' => string, 'hashedPassword' => string)
    * @return array (object GalleryStatus status code, mixed (string, integer) externalId of new user

updateUser($externalId, $userData)

    * Update a user in the emApp.
    * @param mixed, external user Id
    * @param array new user data ('userName' => string, 'fullName' => string, 'email' => string,
    *                              'language' => string, 'hashedPassword' => string)
    * @return array object GalleryStatus a status code


    * Delete a user from the emApp.
    * @param mixed external user Id
    * @return object GalleryStatus a status code

getUser($externalId) Currently in limbo


    * Get user properties for emApp's 'guest' user.
    * @return array object GalleryStatus status code
    *         mixed (string, integer) externalId of user


    * Get user properties for emApp's admin user.
    * @return array object GalleryStatus status code
    *         mixed (string, integer) externalId of user


    * Get list of users from emApp.
    * @return array (object GalleryStatus a status code,
    *                array (mixed id => array('userName' => string, 'email' => string,
    *                      'language' => string, 'hashedPassword' => string,
    *                      'fullName' => string, 'id' => mixed)))


    * Return which user properties are required when creating/comparing users.
    * @return array ('userName' => bool, 'email' => bool, 'language' => bool,
    *                       'hashedPassword' => bool, 'fullName' => bool)


    * Will we compare users in a case-sensitive fashion?
    * @return array (object GalleryStatus status code,
    *         bool isCaseSensitive)