<?php

    include_once( PLOG_CLASS_PATH."class/dao/model.class.php" );
    include_once( PLOG_CLASS_PATH."class/dao/userpermission.class.php" );
	include_once( PLOG_CLASS_PATH."class/dao/daocacheconstants.properties.php" );	

    //
    // :KLUDGE: This should be done in a better way...
    //
    define( "PERMISSION_SITE_ADMIN", 1 );
    define( "PERMISSION_BLOG_USER", 2 );
    define( "PERMISSION_BLOG_OWNER", 3 );

    /**
     * Handles user permissions.
     *
     * \ingroup DAO
     */
    class UserPermissions extends Model 
    {

        function UserPermissions()
        {
            $this->Model();			
			$this->table = $this->getPrefix()."users_permissions";
        }

        /**
         * Retrieves the permissions for a given user.
         *
         * @param userId The user identifier
         * @param blogId The blog identifier
         * @return An Array of UserPermission objects with all the different permissions
         * that the user has for the given blog. the array can be empty if the user has no
         * privileges over a blog.
         */
        function getUserPermissions( $userId, $blogId )
        {
            $perms = Array();
			
            // check if the user is the blog owner
			include_once( PLOG_CLASS_PATH."class/dao/blogs.class.php" );
			$blogs = new Blogs();
			$blogInfo = $blogs->getBlogInfo( $blogId );
			if( !$blogInfo )
			 return Array();
			 
			if( $blogInfo->getOwnerId() == $userId ) {
				$perm = new UserPermission( $userId, $blogId, PERMISSION_BLOG_OWNER, 0 );
				$perms[] = $perm;
            }
			
			// get all the user permissions from the db table
			$userPerms = $this->getMany( "user_id",
			                             $userId,
			                             CACHE_USER_PERMISSIONS );
			if( !is_array( $userPerms ))
				$userPerms = Array();
				
			foreach( $userPerms as $perm ) {
				if( $perm->getBlogId() == $blogId )
					$perms[] = $perm;
			}
										
            return( $perms );
        }

        /**
         * Grants a permission to a user, for a given blog.
         * Any permission can be granted, as long as it exists.
         *
         * @param userId The user which will receive the permission
         * @param blogId The blog to which this permission will be given for this user
         * @param permissionId The identifier of the permission that will be granted
         * @return Returns true if the permission was set or already existed, or false
         * if there was any problem.
         */
        function grantPermission( &$perm )
        {
            // check if the permission has already been granted
			$userPerms = $this->getUserPermissions( $perm->getUserId(), $perm->getUserId());
			$found = false;
			foreach( $userPerms as $userPerm ) {
				if( $userPerm->getUserId() == $perm->getUserId() && $userPerm->getBlogId() == $perm->getBlogId() && 
				    $userPerm->getPermissionId() == $perm->getPermissionId()) {
					$found = true;
					break;
				}
			}
			if( $found )
				return( true );
				
			// if not, grant it now
			if(( $result = $this->add( $perm ))) {
				$this->_cache->removeData( $perm->getUserId(), CACHE_USER_PERMISSIONS );
			}
			
			return( $result );
        }

        /**
         * Removes a permission from a user, for a given blog.
         *
         * @param userId The user which will be revoked the permission
         * @param blogId The blog to which this permission will be revoked
         * @param permissionId The identifier of the permission that will be revoked
         * @return Returns true if the permission didn't exist or if the permission was
         * successfully removed, or false otherwise.
         */
        function revokePermission( $userId, $blogId, $permissionId )
        {
            // check if the permission has already been removed or doesn't exist
			$userPerms = $this->getUserPermissions( $userId, $blogId );
			foreach( $userPerms as $perm ) {
				if( $perm->getUserId() == $userId && $perm->getBlogId() == $blogId && 
				    $perm->getPermissionId() == $permissionId ) {
					$found = true;
					break;
				}
			}
			if( !$found )
				return( true );

			// build the query to remove the row
			$query = "DELETE FROM ".$this->getPrefix()."users_permissions WHERE user_id = '".Db::qstr( $userId )."'
			          AND blog_id = '".Db::qstr( $blogId ) ."' AND permission_id = '".Db::qstr( $permissionId )."'";
			// and execute it
			$result = $this->Execute( $query );
			if( $result ) {
				$this->_cache->removeData( $userId, CACHE_USER_PERMISSIONS );
			}
			
			return( $result );
        }

        /**
         * removes all the permissions for a given blog, useful when we're removing
         * the blog from the database.
         *
         * @param blogId The blog from which we'd like to remove the permissions.
         * @return true
         */
        function revokeBlogPermissions( $blogId )
        {
			include_once( PLOG_CLASS_PATH."class/dao/blogs.class.php" );
			
			$blogs = new Blogs();
			$blogInfo = $blogs->getBlogInfo( $blogId );
			if( !$blogInfo )
				return false;
			$blogUsers = $blogInfo->getUsersInfo();
			
			if(( $result = $this->delete( "blog_id", $blogId ))) {
				foreach( $blogUsers as $user ) {
					$this->_cache->removeData( $user->getId(), CACHE_USER_PERMISSIONS );
				}
			}

            return $result;
        }

        /**
        * updates the list of users that have access to the blog. But this method works so
         * that it first removes all current permissions and then recreates them again
         * based on the given list of users
         *
         * @param blogId
         * @param userIdList An associative array with user ids
         * @return true if successful or false otherwise
         */
        function updateBlogUserPermissions( $blogId, $userList )
        {
            // first of all, remove all the permissions
            $this->revokeBlogPermissions( $blogId );
            
            // load the blog to check whether it is there and to filter out
            // the blog owner
            include_once( PLOG_CLASS_PATH."class/dao/blogs.class.php" );
            $blogs = new Blogs();
            $blog = $blogs->getBlogInfo( $blogId );
            if( !$blog )
            	return false;
            
            // make sure that we're dealing with an array
            if( !is_array( $userList )) {	            
                return true;
            }
            
            // loop through the array and recreate the permissions
            foreach( $userList as $userId ) {
                if( $userId > 0 && $blog->getOwnerId() != $userId ) {
					$perm = new UserPermission( $userId, $blogId, PERMISSION_BLOG_USER );
					$this->grantPermission( $perm );
                }
            }
            
            return true;
        }

        /**
         * revokes all the permissions that a user may have
         *
         * @param userId The identifier of the user
         * @return true
         */
        function revokeUserPermissions( $userId )
        {
			if( $result = $this->delete( "user_id", $userId )) {
				$this->_cache->removeData( $userId, CACHE_USER_PERMISSIONS );
			}
			
			return( $result );
        }		

        /**
         * @private
         */
        function mapRow( $row )
        {
            $perm = new UserPermission( $row["user_id"], 
			                            $row["blog_id"], 
										$row["permission_id"], 
										$row["id"] );

            return $perm;
        }		
    }
?>