Source for file sl_userlib.php

Documentation is available at sl_userlib.php

  1. <?php    
  2.     /**
  3.     * Sloodle user library.
  4.     *
  5.     * Provides functionality for reading, managing and editing user data.
  6.     *
  7.     * @package sloodle
  8.     * @copyright Copyright (c) 2007-8 Sloodle (various contributors)
  9.     * @license http://www.gnu.org/licenses/gpl-3.0.html GNU GPL v3
  10.     * @since Sloodle 0.2
  11.     *
  12.     * @contributor Peter R. Bloomfield
  13.     *
  14.     */
  15.     
  16.     // This library expects that the Sloodle config file has already been included
  17.     //  (along with the Moodle libraries)
  18.     
  19.     /** Include the Sloodle IO library. */
  20.     require_once(SLOODLE_DIRROOT.'/lib/sl_iolib.php');
  21.     /** Include the generali Sloodle functionality. */
  22.     require_once(SLOODLE_DIRROOT.'/lib/sl_generallib.php');
  23.     
  24.     
  25.     /**
  26.     * A class to represent a single user, including Moodle and Sloodle data.
  27.     * @package sloodle
  28.     */
  29.     class SloodleUser
  30.     {
  31.     ///// PRIVATE DATA /////
  32.     // Note: maintaining compatibility with PHP4 - treat this data as private
  33.     
  34.         /**
  35.         * Integer ID of a Sloodle user entry in the database.
  36.         * Value 0 represents no user.
  37.         * @var int 
  38.         * @access private
  39.         * @see $sloodle_user_cache
  40.         * @see $moodle_user_id
  41.         */
  42.         var $sloodle_user_id = 0;
  43.         
  44.         /**
  45.         * Integer ID of a Moodle user entry in the database.
  46.         * Value 0 represents no user.
  47.         * @var int 
  48.         * @access private
  49.         * @see $moodle_user_cache
  50.         * @see $sloodle_user_id
  51.         */
  52.         var $moodle_user_id = 0;
  53.         
  54.         
  55.     ///// PUBLIC DATA /////
  56.     
  57.         /**
  58.         * Sloodle user data cache.
  59.         * Used by various functions fetching database data about a Sloodle user.
  60.         * Contents can also be used in subsequent function calls to prevent the need for an additional database query (typically by specifying a $use_cache parameter).
  61.         * Update is *not* automatic.
  62.         * It can be updated manually by calling {@link: update_sloodle_user_cache_from_db()}.
  63.         * Data placed here can also be used to edit the database using {@link: insert_sloodle_user_cache_to_db()} or {@link: update_sloodle_user_cache_to_db()}.
  64.         * After construction, it will always be an object.
  65.         * @var object 
  66.         * @access public
  67.         * @see $sloodle_user_id
  68.         * @see $moodle_user_cache
  69.         */
  70.         var $sloodle_user_cache = NULL;
  71.         
  72.         /**
  73.         * Moodle user data cache.
  74.         * Used by various functions fetching database data about a Moodle user.
  75.         * Contents can also be used in subsequent function calls to prevent the need for an additional database query (typically by specifying a $use_cache parameter).
  76.         * Update is *not* automatic.
  77.         * It can be updated manually by calling {@link: update_moodle_user_cache_from_db()}.
  78.         * Unlike the Sloodle equivalent, this cannot be used to update the database
  79.         * After construction, it will always be an object.
  80.         * @var object 
  81.         * @access public
  82.         * @see $moodle_user_id
  83.         * @see $sloodle_user_cache
  84.         * @see $enrolled_courses_cache
  85.         */
  86.         var $moodle_user_cache = NULL;
  87.         
  88.         /**
  89.         * Cache of courses which the Moodle user is enrolled in
  90.         * Used by some functions fetching database data about a Moodle user's courses.
  91.         * It is an array which caches the list of courses the Moodle user is enrolled in
  92.         * Note that update is *not* automatic, but you can manually call {@link: update_enrolled_courses_cache_from_db()}.
  93.         * After construction, it will always be a numeric array of integers (but may be empty)
  94.         * Each element will be a course ID (integer).
  95.         * @var array 
  96.         * @access public
  97.         * @see $moodle_user_cache
  98.         */
  99.         var $enrolled_courses_cache = NULL;
  100.         
  101.         
  102.     ///// CONSTRUCTOR /////
  103.     
  104.         /**
  105.         * Class constructor.
  106.         * @return void 
  107.         * @access public
  108.         */
  109.         function SloodleUser()
  110.         {
  111.             // Make the caches empty objects
  112.             $this->sloodle_user_cache = new stdClass();
  113.             $this->moodle_user_cache = new stdClass();
  114.             $enrolled_courses_cache array();
  115.         }
  116.         
  117.         
  118.     ///// ACCESSORS /////
  119.     
  120.         /**
  121.         * Accessor: gets the Sloodle user ID member, {@link: $sloodle_user_id}.
  122.         * @return int 
  123.         * @access public
  124.         */
  125.         function get_sloodle_user_id()
  126.         {
  127.             return $this->sloodle_user_id;
  128.         }
  129.         
  130.         /**
  131.         * Accessor: sets the Sloodle user ID member, {@link: $sloodle_user_id}.
  132.         * @param int $id The integer ID of a Sloodle user entry (or 0 for no entry).
  133.         * @return void 
  134.         * @access public
  135.         */
  136.         function set_sloodle_user_id$id )
  137.         {
  138.             $this->sloodle_user_id = $id;
  139.         }
  140.         
  141.         /**
  142.         * Accessor: gets the Moodle user ID member, {@link: $moodle_user_id}.
  143.         * @return int 
  144.         * @access public
  145.         */
  146.         function get_moodle_user_id()
  147.         {
  148.             return $this->moodle_user_id;
  149.         }
  150.         
  151.         /**
  152.         * Accessor: sets the Moodle user ID member, {@link: $moodle_user_id}.
  153.         * @param int $id The integer ID of a Moodle user entry (or 0 for no entry).
  154.         * @return void 
  155.         * @access public
  156.         */
  157.         function set_moodle_user_id$id )
  158.         {
  159.             $this->moodle_user_id = $id;
  160.         }
  161.         
  162.         
  163.     ///// USER LINK FUNCTIONS /////
  164.         
  165.         /**
  166.         * Determines whether or not the current Sloodle and Moodle users are linked.
  167.         * @param bool $use_cache If true (not default) then the Sloodle and Moodle user caches ({@link:$sloodle_user_cache} and {@link:$moodle_user_cache})will be used instead of querying the database.
  168.         * @return mixed Ture if users are linked, false if not, or a string error message if something goes wrong.
  169.         * @access public
  170.         */
  171.         function users_linked($use_cache FALSE)
  172.         {
  173.             // If we are missing either the Sloodle or Moodle account ID's, then they cannot be linked
  174.             if ($this->sloodle_user_id <= || $this->moodle_user_id <= 0return FALSE;
  175.         
  176.             // Are we to check the cache?
  177.             if ($use_cache{
  178.                 // Do we have a cache available?
  179.                 if (!(is_object($this->sloodle_user_cache&& isset($this->sloodle_user_cache->userid))) {
  180.                     // No - not available - report the errorexit();
  181.                     return 'Sloodle user data not cached.';
  182.                 }
  183.                 
  184.                 // Check the cached userid value
  185.                 return ((int)$this->sloodle_user_cache->userid == $this->moodle_user_id);
  186.                 
  187.             }
  188.             
  189.             // We're checking the database instead
  190.             $sloodle_user_data get_record('sloodle_users''id'$this->sloodle_user_id);
  191.             return ((int)$sloodle_user_data->userid == $this->moodle_user_id);
  192.         }
  193.     
  194.         /**
  195.         * Links the current Sloodle and Moodle accounts together.
  196.         * <b>NOTE:</b> does not remove any other links to the Moodle account.
  197.         * @return mixed True if successful, false on failure, or a string error message if something goes wrong
  198.         * @access public
  199.         */
  200.         function link_users()
  201.         {
  202.             // We cannot link an empty Sloodle user
  203.             if ($this->sloodle_user_id <= 0return "Failed to link users - invalid Sloodle user ID";
  204.             // We cannot link to an invalid Moodle user
  205.             if ($this->moodle_user_id <= 0return "Failed to link users - invalid Moodle user ID";
  206.             
  207.             // Prepare an update object
  208.             $sloodle_user_data new stdClass();
  209.             $sloodle_user_data->id $this->sloodle_user_id;
  210.             $sloodle_user_data->userid $this->moodle_user_id;
  211.             
  212.             // Attempt the update
  213.             return update_record('sloodle_users'$sloodle_user_data);
  214.         }
  215.         
  216.         /**
  217.         * Completely unlinks the Sloodle user from any Moodle account.
  218.         * @return mixed True if successful, false on failure, or a string error message if something goes wrong
  219.         * @access public
  220.         */
  221.         function unlink_sloodle_user()
  222.         {
  223.             // We cannot link an empty Sloodle user
  224.             if ($this->sloodle_user_id <= 0return "Failed to unlink Sloodle user - invalid Sloodle user ID";
  225.             
  226.             // Prepare an update object
  227.             $sloodle_user_data new stdClass();
  228.             $sloodle_user_data->id $this->sloodle_user_id;
  229.             $sloodle_user_data->userid 0;
  230.             
  231.             // Attempt the update
  232.             return update_record('sloodle_users'$sloodle_user_data);
  233.         }
  234.         
  235.         
  236.     ///// DATABASE FUNCTIONS /////
  237.     
  238.         /**
  239.         * Deletes the Sloodle user identified by {@link:$sloodle_user_id}. 
  240.         * @return mixed True if successful, false on failure, or a string error message if something goes wrong
  241.         * @access public
  242.         */
  243.         function delete_sloodle_user()
  244.         {
  245.             // We cannot delete an empty Sloodle user
  246.             if ($this->sloodle_user_id <= 0return "Failed to delete user - invalid Sloodle user ID";
  247.             
  248.             // Attempt to delete the record from the database
  249.             return delete_records('sloodle_users''id'$this->sloodle_user_id);
  250.         }
  251.         
  252.         /**
  253.         * Updates the Sloodle user cache ({@link:$sloodle_user_cache}) from the database
  254.         * @return mixed True if successful, false on failure, or a string error message if something goes wrong
  255.         * @access public
  256.         */
  257.         function update_sloodle_user_cache_from_db()
  258.         {
  259.             // We need a valid Sloodle user ID
  260.             if ($this->sloodle_user_id <= 0return "Failed to update Sloodle user cache - invalid Sloodle user ID";
  261.             // Make and store the query
  262.             $data get_record('sloodle_users''id'$this->sloodle_user_id);
  263.             if ($data === FALSEreturn FALSE;
  264.             $this->sloodle_user_cache = $data;
  265.             return TRUE;
  266.         }
  267.         
  268.         /**
  269.         * Update the Moodle user cache ({@link:$moodle_user_cache}) from the database
  270.         * @return mixed True if successful, false on failure, or a string error message if something goes wrong
  271.         * @access public
  272.         */
  273.         function update_moodle_user_cache_from_db()
  274.         {
  275.             // We need a valid Moodle user ID
  276.             if ($this->moodle_user_id <= 0return "Failed to update Moodle user cache - invalid Moodle user ID";
  277.             // Make and store the query
  278.             $data get_record('user''id'$this->moodle_user_id);
  279.             if ($data === FALSEreturn FALSE;
  280.             $this->moodle_user_cache = $data;
  281.             return TRUE;
  282.         }
  283.         
  284.         /**
  285.         * Use the Sloodle user cache to update an entry in the Sloodle users database table.
  286.         * Uses the object-entirely as-is, so the 'id' field must be accurate.
  287.         * Ignores anu unset fields.
  288.         * @return mixed True if successful, false if the query fails, or a string error message if something goes wrong
  289.         * @access public
  290.         */
  291.         function update_sloodle_user_cache_to_db()
  292.         {
  293.             // Make sure we have a cache object
  294.             if (!is_object($this->sloodle_user_cache)) {
  295.                 return "Could not update Sloodle user details in database - cache does not contain an object.";
  296.             }
  297.             // Make sure the ID field is set and is valid
  298.             if (!isset($this->sloodle_user_cache|| (int)$this->sloodle_user_cache->id <= 0{
  299.                 return "Could not update Sloodle user details in database - cache does not contain valid ID field (should be a positive non-zero integer).";
  300.             }
  301.             
  302.             // Make the update
  303.             return update_record('sloodle_users'$this->sloodle_user_cache);
  304.         }
  305.         
  306.         // Use the Sloodle user cache to insert a new entry in the Sloodle user database table
  307.         // Uses the object entirely as-is, except that the 'id' field is ignored
  308.         // Stores the id of the new entry in $this->sloodle_user_id
  309.         // Returns TRUE if successful, FALSE if the query fails
  310.         /**
  311.         * Use the Sloodle user cache to insert a new entry in the Sloodle user database table.
  312.         * Uses the object entirely as-is, except that the 'id' field is ignored.
  313.         * The ID of the new entry is stored in {@link:$sloodle_user_id}. 
  314.         * @return bool True if successful, or false on failure.
  315.         * @access public
  316.         */
  317.         function insert_sloodle_user_cache_to_db()
  318.         {
  319.             // Make sure we have a cache object
  320.             if (!is_object($this->sloodle_user_cache)) {
  321.                 return "Could not update Sloodle user details in database - cache does not contain an object.";
  322.             }
  323.             
  324.             // Attempt the record insertion
  325.             $id insert_record('sloodle_users'$this->sloodle_user_cache);
  326.             // Check if it was successful, and store the ID if so
  327.             if ($id == FALSEreturn FALSE;
  328.             $this->sloodle_user_id = $id;
  329.             return TRUE;
  330.         }
  331.         
  332.         /**
  333.         * Create a new Sloodle user.
  334.         * All parameters are optional. To enable loginzone authentication, you *must* specify position and expiry time.
  335.         * Note that, if no login security token is specified, it is generated automatically.
  336.         * If successful, the new ID is stored and the user data is cached.
  337.         * @param string $uuid avatar UUID
  338.         * @param string $avname avatar name
  339.         * @param int $userid ID of Moodle user to be linked with this Sloodle user
  340.         * @param string $loginposition a position vector of format <x,y,z>, representing the allocated loginzone position
  341.         * @param string $loginpositionexpires an indication of when the allocated loginposition expires (format unknown)
  342.         * @param string $loginpositionregion the name of the region in which the loginzone is (NOT IN USE YET!)
  343.         * @param string $loginsecuritytoken a security token (random letters/numbers) used to allow secure authentication
  344.         * @return bool True if successful, or false if not.
  345.         * @access public
  346.         */
  347.         function create_sloodle_user$uuid ''$avname ''$userid 0$loginposition ''$loginpositionexpires ''$loginpositionregion ''$loginsecuritytoken '')
  348.         {
  349.             // If necessary, generate a login security token
  350.             if (empty($loginsecuritytoken)) $loginsecuritytoken sloodle_random_security_token();
  351.             
  352.             // Construct the user data object
  353.             $sloodle_user_data new stdClass();
  354.             $sloodle_user_data->uuid $uuid;
  355.             $sloodle_user_data->avname $avname;
  356.             $sloodle_user_data->userid $userid;
  357.             $sloodle_user_data->loginposition $loginposition;
  358.             $sloodle_user_data->loginpositionexpires $loginpositionexpires;
  359.             $sloodle_user_data->loginpositionregion $loginpositionregion;
  360.             $sloodle_user_data->loginsecuritytoken $loginsecuritytoken;
  361.             
  362.             // Add the data to the database
  363.             $id insert_record('sloodle_users'$sloodle_user_data);
  364.             if ($id === FALSEreturn FALSE;
  365.             // Store the data
  366.             $this->sloodle_user_id = $id;
  367.             $this->sloodle_user_cache = $sloodle_user_data;
  368.             
  369.             return TRUE;
  370.         }
  371.         
  372.         /**
  373.         * Clears the login position from the currently selected Sloodle user.
  374.         * This function will user the user identified by {@link:$sloodle_user_id}, 
  375.         *  retrieve all the user data, remove the login position values, and update the database.
  376.         * @return mixed True if successful, false if the database query fails, or a string if an error occurs.
  377.         * @access public
  378.         */
  379.         function delete_login_position()
  380.         {
  381.             // We need a valid Sloodle user ID
  382.             if ($this->sloodle_user_id <= 0return "Failed to update Sloodle user cache - invalid Sloodle user ID";
  383.             
  384.             // Get the user data
  385.             $sloodle_user_data get_record('sloodle_users''id'$this->sloodle_user_id);
  386.             if ($sloodle_user_data === FALSEreturn FALSE;
  387.             // Remove the login position values
  388.             $sloodle_user_data->loginposition '';
  389.             $sloodle_user_data->loginpositionexpires '';
  390.             $sloodle_user_data->loginpositionregion '';
  391.             // Update the database
  392.             return update_record('sloodler_users'$sloodle_user_data);
  393.         }
  394.         
  395.         /**
  396.         * Generates a new login position for the current Sloodle user.
  397.         * Stores the new login position in the database, and refreshes the user cache
  398.         * @param int $expires A timestamp indicating when the position should expire.
  399.         * @return mixed A numerical array containing the new position if successful, FALSE on failure, or a string if an error occurs
  400.         * @access public
  401.         */
  402.         function generate_login_position$expires )
  403.         {
  404.             // Make sure the expiry time is not already passed
  405.             if ((int)$expires time()) return "Failed to generate login position - specified expiry time is already passed.";
  406.             // We need a valid Sloodle user ID
  407.             if ($this->sloodle_user_id <= 0return "Failed to generate login position - invalid Sloodle user ID.";
  408.             
  409.             // Get the bounds of the loginzone
  410.             list($max,$minsloodle_login_zone_coordinates();
  411.             $newpos_str NULL;
  412.             $newpos_arr NULL;
  413.             // We will try up to 10 times to find a new available position
  414.             $maxtries 10;
  415.             for ($i 0$i $maxtries && $newpos_str == NULL$i++{
  416.                 // Generate a new random position
  417.                 $rndpos_arr sloodle_random_position_in_zone($max$min);
  418.                 $rndpos_str sloodle_array_to_vector($rndpos_arr);
  419.                 // Is the position already taken? (Or was it previously taken by the same user?)
  420.                 $taker get_record('sloodle_users''loginposition'$rndpos_str);
  421.                 if ($taker == FALSE || $taker->userid == $this->moodle_user_id{
  422.                     // Nobody has the position
  423.                     $newpos_arr $rndpos_arr;
  424.                     $newpos_str $rndpos_str;
  425.                 }
  426.             }
  427.             
  428.             // Were we successful?
  429.             if ($newpos_str != NULL{
  430.                 // Yes - use the Sloodle user cache to update the database
  431.                 if ($this->update_sloodle_user_cache_from_db(!== TRUE{
  432.                     return "Failed to updated Sloodle user cache.";
  433.                 }
  434.                 $this->sloodle_user_cache->loginposition $newpos_str;
  435.                 $this->sloodle_user_cache->loginpositionexpires $expires;
  436.                 $this->sloodle_user_cache->loginpositionregion '';
  437.                 if ($this->update_sloodle_user_cache_to_db(!== TRUE{
  438.                     return "Failed to update database from Sloodle user cache.";
  439.                 }
  440.                 
  441.                 return $newpos_arr;
  442.             }
  443.             
  444.             return FALSE;
  445.         }
  446.         
  447.         
  448.         /**
  449.         * Create a Moodle user account with the specified first name, last name and email address.
  450.         * @return mixed True if successful, or a string error message if something goes wrong.
  451.         * @access public
  452.         */
  453.         function create_moodle_user$firstname$lastname$email )
  454.         {
  455.             global $CFG;
  456.             // Include the Moodle authentication library
  457.             include_once("{$CFG->dirroot}/auth/{$CFG->auth}/lib.php");
  458.             include_once("{$CFG->dirroot}/auth/{$CFG->auth}/auth.php");
  459.  
  460.             // Make sure we have all necessary parameters
  461.             if (!isset($firstname|| empty($firstname)) return "Cannot register Moodle user - first name not specified.";
  462.             if (!isset($lastname|| empty($lastname)) return "Cannot register Moodle user - last name not specified.";
  463.             if (!isset($email|| empty($email)) return "Cannot register Moodle user - email address not specified.";
  464.             
  465.             // Construct a base username - we will try to use this, but adapt it in the event of a conflict
  466.             // It will start out as just the first and last names concatenated
  467.             $moodlebaseusername trim(moodle_strtolower($firstname.$lastname));
  468.             
  469.             // Construct a new Moodle user object
  470.             $moodleuser new stdClass();
  471.             // Generate and store the required items of user-data
  472.             $moodleuser->firstname strip_tags($firstname);
  473.             $moodleuser->lastname strip_tags($lastname);
  474.             $moodleuser->email strip_tags($email);
  475.             $moodleuser->username $moodlebaseusername;
  476.             $moodleuser->password sloodle_random_web_password();
  477.             $plainpass $moodleuser->password;
  478.             $moodleuser->password hash_internal_user_password($plainpass);
  479.             $moodleuser->confirmed 0;            
  480.             $moodleuser->lang current_language();
  481.             $moodleuser->firstaccess time();
  482.             $moodleuser->secret random_string(15);
  483.             $moodleuser->auth $CFG->auth;
  484.             $moodleuser->mnethostid 1;
  485.             
  486.             // Do we need to check for username conflicts in the authentication module?
  487.             $check_auth empty($CFG->auth_user_create== FALSE && function_exists('auth_user_exists'&& function_exists('auth_user_create');
  488.             // We want to find a username that does conflict with either the authentication module, or with the Moodle database        
  489.             // Try the basic username
  490.             $try_username $moodlebaseusername;
  491.             $conflict_auth FALSE;
  492.             if ($check_auth$conflict_auth auth_user_exists($try_username);
  493.             $conflict_moodle record_exists('user''username'$try_username);
  494.             
  495.             // If that didn't work, then try a few random variants (just a number added to the end of the name)
  496.             $MAX_RANDOM_TRIES 3;
  497.             $rnd_try 0;
  498.             while ($rnd_try $MAX_RANDOM_TRIES && $conflict_moodle && (($check_auth && $conflict_auth|| !$check_auth)) {
  499.                 // Pick a random 3 digit number
  500.                 $rnd_num mt_rand(100999);
  501.                 if ($rnd_num == 666$rnd_num++// Some users may object to this number
  502.                 // Construct a new username to try
  503.                 $try_username $moodlebaseusername . (string)$rnd_num;
  504.                 // Check for conflicts
  505.                 if ($check_auth$conflict_auth auth_user_exists($try_username);
  506.                 $conflict_moodle record_exists('user''username'$try_username);
  507.                 
  508.                 // Next attempt
  509.                 $rnd_try++;
  510.             }
  511.             
  512.             // Stop if we haven't found a unique name
  513.             if ($conflict_moodle || $conflict_authreturn "Cannot register Moodle user - failed to find unique username.";
  514.             // Store the username
  515.             $moodleuser->username $try_username;
  516.             
  517.             // Attempt to add the user to the authentication module
  518.             if ($check_auth{
  519.                 // Attempt to add the user to the authentication module
  520.                 if (!auth_user_create($moodleuser$plainpass)) return "Cannot register Moodle user - failed to add user to Moodle authentication module";
  521.             }
  522.     
  523.             // Attempt to add the user data to the Moodle database
  524.             $moodleuser->id insert_record('user'$moodleuserTRUE);
  525.             // User did not exist - create a new one
  526.             if ($moodleuser->id === FALSEreturn "Cannot register Moodle user - failed to add user to Moodle database";
  527.             
  528.             // Store the Moodle user details
  529.             $this->moodle_user_id = $moodleuser->id;
  530.             $this->moodle_user_cache = get_record('user''id'$moodleuser->id);
  531.             
  532.             return TRUE;
  533.         }
  534.         
  535.     
  536.     ///// FIND USER FUNCTIONS /////
  537.     
  538.         /**
  539.         * Attempts to find a Sloodle user by their UUID and/or avatar nam.
  540.         * Note: the UUID takes precedence, but the name can be used as a fall-back.
  541.         * The ID of the user is stored in {@link:$sloodle_user_id}. 
  542.         * @param string $uuid The UUID of the avatar
  543.         * @param string $name The name of the avatar
  544.         * @param bool $cache_data If true (default) then the user data is stored in the cache variable, {@link:$sloodle_user_cache}. 
  545.         * @return mixed True if successful, false if user was not found, or a string is some other error occurred.
  546.         * @access public
  547.         */
  548.         function find_sloodle_user$uuid$name$cache_data TRUE )
  549.         {
  550.             // Make sure we at least have a UUID or a name
  551.             if (empty($uuid&& empty($name)) {
  552.                 return "Failed to find Sloodle user - neither a UUID nor a name was provided.";
  553.             }
  554.             
  555.             // If we have a UUID, then search by it
  556.             $sloodle_user NULL;
  557.             if (!empty($uuid)) $sloodle_user get_record('sloodle_users''uuid'$uuid);
  558.             // If that search failed, and we have a name, then search by it
  559.             if (is_null($sloodle_user&& !empty($name)) $sloodle_user get_record('sloodle_users''avname'$name);
  560.             
  561.             // Did we find a user?
  562.             if (is_object($sloodle_user)) {
  563.                 // Yes - store the ID/data and finish
  564.                 $this->sloodle_user_id = $sloodle_user->id;
  565.                 if ($cache_data$this->sloodle_user_cache = $sloodle_user;
  566.                 return TRUE;
  567.             }
  568.             
  569.             return FALSE;
  570.         }
  571.         
  572.         /**
  573.         * Find the Sloodle user linked to the current Moodle user.
  574.         * Stores the Sloodle user ID in {@link:$sloodle_user_id}. 
  575.         * @param bool $cache_data If true (default) then the Sloodle user data is automatically cached by this function.
  576.         * @return mixed True if successful, false if no link was found, or a string if an error occurs
  577.         * @access public
  578.         */
  579.         function find_linked_sloodle_user$cache_data TRUE )
  580.         {
  581.             // Make sure a valid Moodle user ID has been specified
  582.             if ($this->moodle_user_id <= 0return 'No Moodle user ID specified.';
  583.             
  584.             // Get all Sloodle user records linking to the Moodle id
  585.             $recs get_records('sloodle_users''userid'$this->moodle_user_id);
  586.             
  587.             // Was nothing found?
  588.             if (!is_array($recs|| count($recs== 0return FALSE;
  589.             // There is a problem if more than one Sloodle user was found linked to the same Moodle user
  590.             if (count($recs1return "More than one Sloodle user linked to Moodle user #{$this->moodle_user_id}.";
  591.             
  592.             // Store any necessary data
  593.             $rec = NULL;
  594.             foreach ($recs as $currec) {
  595.                 $rec = $currec;
  596.             }
  597.             $this->sloodle_user_id = $rec->id;
  598.             if ($cache_data$this->sloodle_user_cache = $rec;
  599.             
  600.             return TRUE;
  601.         }
  602.         
  603.         /**
  604.         * Find the Moodle user linked to the current Sloodle user.
  605.         * Stores the Moodle user ID in {@link:$moodle_user_id}.
  606.         * @param bool $use_cache If true (not default) this function will use the local Sloodle user cache instead of querying the database again.
  607.         * @param bool $cache_data If true (default) then the Moodle user data is automatically cached by this function
  608.         * @return mixed True if successful, false if no link was found, or a string if an error occurs
  609.         * @access public
  610.         */
  611.         function find_linked_moodle_user( $use_cache = FALSE, $cache_data = TRUE )
  612.         {
  613.             // This value will store the Moodle ID locally
  614.             $moodle_id = 0;
  615.             
  616.             // Are we to check the cache?
  617.             if ($use_cache) {
  618.                 // Do we have a cache available?
  619.                 if (!(is_object($this->sloodle_user_cache&& isset($this->sloodle_user_cache->userid))) {
  620.                     // No - not available - report the error
  621.                     return 'Sloodle user data not cached.';
  622.                 }
  623.                 
  624.                 // Check that the user has a link, and store it if so
  625.                 if ($this->sloodle_user_cache->userid <= 0return FALSE;
  626.                 $moodle_id $this->sloodle_user_cache->userid;
  627.                 
  628.             } else {
  629.                 // We need a valid Sloodle user
  630.                 if ($this->sloodle_user_id <= 0return "Cannot find linked Moodle user - Sloodle user ID is not valid";
  631.                 // Fetch the data from the database
  632.                 $sloodle_user_data get_record('sloodle_users''id'$this->sloodle_user_id);
  633.                 // Check that the user has a link, and store it
  634.                 if ($sloodle_user_data->userid <= 0return FALSE;
  635.                 $moodle_id $sloodle_user_data->userid;
  636.             }
  637.             
  638.             // Now retrieve the Moodle user record
  639.             $moodle_user = get_record('user', 'id', $moodle_id);
  640.             if ($moodle_user === FALSE) return "Failed to find linked Moodle user - Moodle user entry does not exist in database.";
  641.             // Make sure the user has not been deleted
  642.             if ((int)$moodle_user->deleted != 0return "Failed to find linked Moodle user - Moodle user account has been deleted.";
  643.             
  644.             // User looks OK - store it
  645.             $this->moodle_user_id = $moodle_id;
  646.             if ($cache_data$this->moodle_user_cache = $moodle_user;
  647.             
  648.             return TRUE;            
  649.         }
  650.         
  651.         /**
  652.         * Attempt to find a Sloodle user by their loginzone position
  653.         * If successful, the user ID is stored in {@link:$sloodle_user_id} and the function returns true.
  654.         * If no user was found for the given position, false is returned (this may occur if the LoginZone position has expired).
  655.         * If an error occurs, then a string containing an error message is returned.
  656.         * @param mixed $position A vector, either as a string ("<x,y,z>") or an associative array.
  657.         * @param bool $cache_data If true (default) then the user data is cached. Otherwise it is discarded.
  658.         * @access public
  659.         */
  660.         function find_sloodle_user_by_login_position( $position, $cache_data = TRUE )
  661.         {
  662.             // Make sure we have a string or array for the login position
  663.             if (!((is_string($position) && !empty($position)) || (is_array($position) && count($position) == 3)) ) {
  664.                 return "Invalid login position - expected to be a string vector '&lt;x,y,z&gt;' or a vector array {x,y,z}";
  665.             }
  666.             
  667.             // If it's an array, then convert it to a string
  668.             if (is_array($position)) $position = sloodle_array_to_vector($position);
  669.             
  670.             // Keep searching until we find the right user
  671.             $sloodle_user_data = FALSE;
  672.             $stop = FALSE;
  673.             $error = '';
  674.             while ($stop == FALSE) {
  675.                 // Query for the user
  676.                 $sloodle_user_data = get_record('sloodle_users', 'loginposition', $position);
  677.                 // Did the search fail?
  678.                 if ($sloodle_user_data === FALSE) {
  679.                     // Yes - stop searching
  680.                     $stop = TRUE;
  681.                 } else {
  682.                     // We found something - is the login position expired?
  683.                     if (!empty($sloodle_user_data->loginpositionexpires&& (int)$sloodle_user_data->loginpositionexpires time()) {
  684.                         // Yes - remove the login position and move on with the search
  685.                         $sloodle_user_data->loginposition '';
  686.                         $sloodle_user_data->loginpositionexpires '';
  687.                         $sloodle_user_data->loginpositionregion '';
  688.                         // Make sure the update works... otherwise we'll find the same record again!
  689.                         if (!update_record('sloodle_users'$sloodle_user_data)) {
  690.                             $sloodle_user_data = FALSE;
  691.                             $stop = TRUE;
  692.                             $error = 'Tried to remove an expired login position from database, but failed.';
  693.                         }
  694.                     } else {
  695.                         // Login position is valid - stop searching
  696.                         $stop = TRUE;
  697.                     }
  698.                 }                
  699.             } // End of while loop
  700.             
  701.             // Did we find a user? Stop if not
  702.             if ($sloodle_user_data === FALSE) {
  703.                 // Return the error message if an error occurred
  704.                 if (is_string($error) && !empty($error)) return $error;
  705.                 else return FALSE;
  706.             }
  707.             
  708.             // Note: it is tempting to remove the login position here,
  709.             //  but we cannot be guaranteed at this point that the rest of the registration process will work.
  710.             
  711.             // Store the ID of the Sloodle user, and cache the data if necessary
  712.             $this->sloodle_user_id = $sloodle_user_data->id;
  713.             if ($cache_data$this->sloodle_user_cache = $sloodle_user_data;
  714.             return TRUE;
  715.         }
  716.         
  717.         
  718.     ///// LOGIN FUNCTIONS /////
  719.     
  720.         /**
  721.         * Performs an internal login of the current Moodle user.
  722.         * Stores all the user data in the global $USER variable.
  723.         * Note: if login fails, $USER is unchanged.
  724.         * Additionally, note that this function will not perform automatic registration.
  725.         * @return bool True if successful, or false otherwise.
  726.         * @access public
  727.         */
  728.         function login_moodle_user()
  729.         {
  730.             // Make sure we have a Moodle user selected
  731.             if ($this->moodle_user_id <= 0return FALSE;
  732.             // Attempt to retrieve all the user data, and stop if it failed
  733.             $newuser get_complete_user_data('id'$this->moodle_user_id);
  734.             if ($newuser === FALSEreturn FALSE;
  735.             // Store the user data
  736.             global $USER;
  737.             $USER $newuser;
  738.             return TRUE;
  739.         }
  740.         
  741.         /**
  742.         * Generates a new login security token for the current Sloodle user
  743.         * @param bool $cache_data If true (default) then the new login security token will be stored in the Sloodle user cache (as well as the database).
  744.         * @return bool True if successful, or false if an error occurs (such as there being no current Sloodle user)
  745.         * @access public
  746.         */
  747.         function regenerate_login_security_token( $cache_data = TRUE )
  748.         {
  749.             // Do nothing if we don't have a Sloodle user
  750.             if ($this->sloodle_user_id <= 0return FALSE;
  751.             // Construct a new user object to alter the existing one
  752.             $sloodle_user_data new stdClass();
  753.             $sloodle_user_data->id $this->sloodle_user_id;
  754.             $sloodle_user_data->loginsecuritytoken sloodle_random_security_token();
  755.             // Attempt to update the record
  756.             if (update_record('sloodle_users'$sloodle_user_data=== FALSEreturn FALSE;
  757.             // Store the new token
  758.             if ($cache_data{
  759.                 $this->sloodle_user_cache->loginsecuritytoken $sloodle_user_data->loginsecuritytoken;
  760.             }
  761.             return TRUE;
  762.         }
  763.         
  764.         /**
  765.         * Checks if the current Sloodle user has a login security token
  766.         * @param bool $use_cache If true then the cached user data will be used instead of querying the database.
  767.         * @return bool True if the user has a login security token, or false otherwise.
  768.         * @access public
  769.         */
  770.         function has_login_security_token($use_cache = FALSE)
  771.         {
  772.             // Are we to use the cache?
  773.             if ($use_cache) {
  774.                 // Make sure we have a cache
  775.                 if (!is_object($this->sloodle_user_cache)) return FALSE;
  776.                 // Check if the login security token is set and non-empty
  777.                 return (isset($this->sloodle_user_cache&& !empty($this->sloodle_user_cache));
  778.             }
  779.             
  780.             // Checking the database instead            
  781.             // Do nothing if we don't have a Sloodle user ID
  782.             if ($this->sloodle_user_id <= 0return FALSE;
  783.             
  784.             // Attempt to obtain the user data and make sure we found it OK
  785.             $sloodle_user_data get_record('sloodle_users''id'$this->sloodle_user_id);
  786.             if ($sloodle_user_data === FALSEreturn FALSE;
  787.                         
  788.             // Check that the login security token member is set and not empty
  789.             return (isset($sloodle_user_data->loginsecuritytoken&& !empty($sloodle_user_data->loginsecuritytoken));
  790.         }
  791.         
  792.        
  793.     ///// COURSE FUNCTIONS /////
  794.     
  795.         /**
  796.         * Use the database to update the cache of courses which the current Moodle user is enrolled in.
  797.         * Note that admins are considered by this function to be enrolled in all courses.
  798.         * @return True if successul, or false otherwise.
  799.         * @access public
  800.         */
  801.         function update_enrolled_courses_cache_from_db()
  802.         {
  803.             // Make sure we have a Moodle user
  804.             if ($this->moodle_user_id <= 0return FALSE;
  805.             // Obtain the array of courses and make sure the query succeeded
  806.             if (isadmin($this->moodle_user_id)) {
  807.                 // Admins technically have all courses
  808.                 $course_list = get_courses('all', 'c.sortorder ASC', 'c.id');
  809.             } else {
  810.                 // Just get the enrolled courses
  811.                 $course_list = get_my_courses($this->moodle_user_id);
  812.             }
  813.             if ($course_list === FALSE) return FALSE;
  814.             
  815.             // Extract just the course ID's
  816.             $this->enrolled_courses_cache = array();
  817.             foreach ($course_list as $course{
  818.                 $this->enrolled_courses_cache[= (int)$course->id;
  819.             }
  820.             
  821.             return TRUE;
  822.         }
  823.         
  824.         /**
  825.         * Checks if the current Moodle user is already enrolled in the specified course.
  826.         * @param int $course_id ID number of a course to check.
  827.         * @param bool $use_cache If true (not default) then the function uses the enrolled courses cache, instead of querying the database for new data.
  828.         * @param bool True if the user is enrolled, or false if not.
  829.         * @access public
  830.         */
  831.         function is_user_in_course($course_id, $use_cache = FALSE)
  832.         {
  833.             // Make sure we have a Moodle user
  834.             if ($this->moodle_user_id <= 0return FALSE;
  835.             
  836.             // If the user is an admin, then we needn't bother checking
  837.             if (isadmin($this->moodle_user_id)) return TRUE;
  838.             
  839.             // Do we need to refresh the cache?
  840.             if (!$use_cache{
  841.                 if (!$this->update_enrolled_courses_cache_from_db()) return FALSE;
  842.             }
  843.             
  844.             // Make sure we have a non-empty array of course ID's
  845.             if (!is_array($this->enrolled_courses_cache|| count($this->enrolled_courses_cache== 0return FALSE;
  846.             // Check if the course ID appears in the array
  847.             return in_array((int)$course_id$this->enrolled_courses_cache);
  848.         }
  849.     
  850.     }
  851.     
  852.  

Documentation generated on Tue, 04 Mar 2008 15:08:56 +0000 by phpDocumentor 1.4.0