phpgwapi - VFS Class: Relativity

Next Previous Contents

## 4. Relativity

Ok, just one last thing before we get into relativity. You will notice throughout the examples the use of $fakebase. $GLOBALS['phpgw']->vfs->fakebase is by default '/home'. The old VFS was hard-coded to use '/home', but the naming choice for this is now up to administrators. See the Fakebase directory (changing /home) section for more information. Throughout the rest of this document, you will see $fakebase used in calls to the VFS, and /home used in actual paths. You should always use $fakebase when making applications. I suggest doing $fakebase = $GLOBALS['phpgw']->vfs->fakebase; right off the bat to keep things neater.

## 4.1 What is it and how does it work?

One of the design challenges for a Virtual File System is to try to figure out whether the calling application is referring to a file inside or outside the virtual root, and if inside, exactly where. To solve this problem, the phpGroupWare VFS uses RELATIVE defines that are used in bitmasks passed to each function. The result is that any set of different relativities can be used in combination with each other. Let's look at a few examples. Say you want to move 'logo.png' from the user's home directory to the current directory.

    $GLOBALS['phpgw']->vfs->mv (array(
        'from' => 'logo.png',
        'to' => 'logo.png',
        'relatives' => array(
              RELATIVE_USER,
              RELATIVE_ALL
         )
    ));

RELATIVE_USER means relative to the user's home directory. RELATIVE_ALL means relative to the current directory, as set by cd () and as reported by pwd (). So if the current directory was "$fakebase/my_group/project1", the call to mv () would be processed as:

    MOVE "$fakebase/jason/logo.png" TO "$fakebase/my_group/project1/logo.png"

and the actual file system call would be:

    rename ('/var/www/phpgroupware/files/home/jason/logo.php', '/var/www/phpgroupware/files/home/my_group/project1/logo.png');

Those used to the old VFS will note that you do not have to translate the path beforehand. Let's look at another example. Suppose you were moving an email attachment stored in phpGroupWare's temporary directory to the 'attachments' directory within the user's home directory (we're assuming the attachments directory exists). Note that the temporary directory is outside the virtual root.

    $GLOBALS['phpgw']->vfs->mv (array(
         'from' => $GLOBALS['phpgw_info']['server']['temp_dir'] . '/' . $randomdir . '/' . $randomfile,
         'to' => 'attachments/actual_name.ext',
         'relatives' => array(
              RELATIVE_NONE|VFS_REAL,
              RELATIVE_USER
         )
    ));

$randomdir and $randomfile are what the directory and file might be called before they are given a proper name by the user, which is actual_name.ext in this example. RELATIVE_NONE is the define for using full path names. However, RELATIVE_NONE is still relative to the virtual root, so we pass along VFS_REAL as well, to say that the file is outside the virtual root, somewhere else in the file system. Once again, RELATIVE_USER means relative to the user's home directory. So the actual file system call might look like this (keep in mind that $randomdir and $randomfile are just random strings):

    rename ('/var/www/phpgroupware/tmp/0ak5adftgh7/jX42sC9M', '/var/www/phpgroupware/files/home/jason/attachments/actual_name.ext');

Of course you don't have to know that, nor should you be concerned with it; you can take it for granted that the VFS will translate the paths correctly. Let's take a look at one more example, this time using the RELATIVE_USER_APP define. RELATIVE_USER_APP is used to store quasi-hidden application files, similar to the Unix convention of ~/.appname. It simply appends .appname to the user's home directory. For example, if you were making an HTML editor application named 'htmledit', and wanted to keep a backup file in case something goes wrong, you could use RELATIVE_USER_APP to store it:

    $GLOBALS['phpgw']->vfs->write (array(
         'string' => 'file.name~',
         'relatives' => array(
              RELATIVE_USER_APP
         ),
         'content' => $contents
    ));

This assumes that ~/.htmledit exists of course. The backup file "file.name~" would then be written in $fakebase/jason/.htmledit/file.name~. Note that storing files like this might not be as good of a solution as storing them in the temporary directory or in the database. But it is there in case you need it.

## 4.2 Complete List

Here is the complete list of RELATIVE defines, and what they do:

RELATIVE_ROOT

  Don't translate the path at all. Just prepends a /. You'll probably want to use RELATIVE_NONE though, which handles both virtual and real files.

RELATIVE_USER

  User's home directory

RELATIVE_CURR_USER

  Current user's home directory. If the current directory is $fakebase/my_group/project1, this will return is $fakebase/my_group

RELATIVE_USER_APP

  Append .appname to the user's home directory, where appname is the current application's appname

RELATIVE_PATH

  DO NOT USE. Relative to the current directory, used in RELATIVE_ALL

RELATIVE_NONE

  Not relative to anything. Use this with VFS_REAL for files outside the virtual root. Note that using RELATIVE_NONE by itself still means relative to the virtual root

RELATIVE_CURRENT

  An alias for the currently set RELATIVE define, or RELATIVE_ALL if none is set (see the Defaults section)

VFS_REAL

  File is outside of the virtual root. Usually used with RELATIVE_NONE

RELATIVE_ALL

  Relative to the current directory. Use RELATIVE_ALLinstead of RELATIVE_PATH

## 4.3 Defaults

You might be thinking to yourself that passing along RELATIVE defines with every VFS call is overkill, especially if your application always uses the same relativity. The default RELATIVE define for all VFS calls is RELATIVE_CURRENT. RELATIVE_CURRENT itself defaults to RELATIVE_ALL (relative to the current path), unless your application sets a specific relativity. If your application requires most of the work to be done outside of the virtual root, you may wish to set RELATIVE_CURRENT to RELATIVE_NONE|VFS_REAL. set_relative () is the function to do this. For example:

    $GLOBALS['phpgw']->vfs->set_relative (array(
         'mask' => RELATIVE_NONE|VFS_REAL
    ));

    $GLOBALS['phpgw']->vfs->read (array(
         'string' => '/etc/passwd'
    ));

    $GLOBALS['phpgw']->vfs->cp (array(
         'from' => '/usr/include/stdio.h',
         'to' => '/tmp/stdio.h'
    ));

    $GLOBALS['phpgw']->vfs->cp (array(
         'from' => '/usr/share/pixmaps/yes.xpm',
         'to' => 'icons/yes.xpm',
         'relatives' => array(
              RELATIVE_CURRENT,
              RELATIVE_USER
         )
    ));

You should notice that no relativity array is needed in the other calls that refer to files outside the virtual root, but one is needed for calls that include files inside the virtual root. Any RELATIVE define can be set as the default and works in the same fashion. To retrieve the currently set define, use get_relative (). Note that the relativity is reset after each page request; that is, it's good only for the life of the current page loading, and is not stored in session management.

Next Previous Contents