Files

In a CodKep based site you can store files managed and unmanaged way. All kind of uploaded files should located under /date directory. While unmanaged files does not have any additional info stored in the database, the managed files have a database record generated by CodKep file module. The file module registers every managed file, gives an unique identifier of each file, stores the mime type, the original upload filename, the upload time and user and other useful data. This document is describe the using of managed files in CodKep:

All managed files has an UFI (The Unique File Identifier) number which obviously identifies the file.

Database sample with two files:

mysql> select * from file;
+-----+--------+-------------+-----+--------------+------------+----------+---------------------+
| ufi | type   | name        | sub | fsname       | mime       | uploader | uploaded            |
+-----+--------+-------------+-----+--------------+------------+----------+---------------------+
|   1 | public | monkey.jpg  |     | monkey_1.jpg | image/jpeg | admin    | 2017-02-05 13:49:24 |
|   2 | secure | meerkat.jpg |     | meerkat.jpg  | image/jpeg | admin    | 2017-02-05 13:49:24 |
+-----+--------+-------------+-----+--------------+------------+----------+---------------------+
2 rows in set (0.00 sec)

Storing type

The managed files can stored in two available type:

File class

The File class of the CodKep can used to create File objects which represents a managed file in CodKep. The File class can represents both public and secure typed files.

function create_img_tag_from_ufi($image_ufi)
{
    $img = file_load($image_ufi,true);
    /* Equivalent to call:
     *  $img = new File('');
     *  $img->load($image_ufi,true);
     */

    if($img == NULL)
        return '<img src="'.url('/site/no_image.jpg').'" />';
    return '<img src="'.$img->url.'" />';
}

Fixed properties of the File object

Every File object has same built-in properties which are available in any kind of file.

Built-in properties of file object:
(The $file is only a sample object variable here))

Methods of File object

Helper functions of File class

file_load($ufi,$disable_show_error = false)
Loads a file object by UFI. This function is create an empty File object and call load($ufi,$disable_show_error) method on it.

file_load_from_array($file_data_array)
Loads the file object from a previously read array which contains all columns from the file table. This function is create an empty File object and call load_from_array($file_data_array) method on it.

file_remove($ufi,$disable_show_error = false)
Loads a file object by UFI and delete both the database record and the referenced file. This function is create an empty File object and call load($ufi,$disable_show_error) method then call the remove() on it.

file_create_upload($name,$opts = [])
Manages after the form submitted part of a file upload procedure. The $name parameter is the form item name of the input type="file" tag.

A simple file upload page callback:

function upload_page()
{
    par_def('upl','text2ns');
    if(par_is('upl','Upload'))
    {
        form_source_check(); //Recommended to do this
        $n_ufi = file_create_upload('myfile',
            ['container' => 'secure','filetypes' => 'image/jpeg;image/png']);
        if($n_ufi == NULL)
            return 'The file upload is failed.';
        $f = file_load($n_ufi);
        return "The file is uploaded (With ufi:$n_ufi): <img src=\"".$f->url."\"/>";
    }

    $f = new HtmlForm('fupl');
    $f->action_post(current_loc());
    $f->upload('myfile','');
    $f->input('submit','upl','Upload');
    ob_start();
    print "Please browse the file to upload";
    print $f->get();
    return ob_get_clean();
}

register_image_sizeclass($name, $w, $h)
See the size class chapter for details.

File access control

You can control the access of the files by implementing the HOOK_file_access hook.

The hook receives the following three parameters:

  1. $file The examined file object. The system queries the permissions for this file.
  2. $op The system queries the permission for this operation. Possible values are:
    • "create"
    • "delete"
    • "view"
  3. $account Determine the permission of this account (user node)

The hook have to return one value of these defines:

In case there is no HOOK_file_access in the system or received FILE_ACCESS_IGNORE value the system will deny every request except the following default allowed:

  1. Allows everything for admin users.
  2. Allows new file creation for authenticated users.
  3. Allows to view public files. (Pointless to disable it.)
  4. Allows delete/view to the file owner/uploader.

Note: The FILE_ACCESS_DENY is always stronger than FILE_ACCESS_ALLOW, if both received the result will FILE_ACCESS_DENY

Samples:

 // Allow add/edit/delete for editors but allows view for everyone
 function hook_mymodule_file_access($file,$op,$account)
 {
    if($op == 'view')
        return FILE_ACCESS_ALLOW;
    if($acc->auth && $acc->role >= ROLE_EDITOR)
        return FILE_ACCESS_ALLOW;
    return FILE_ACCESS_IGNORE;
 }

The file_access function

file_access(File $file,$op,$account)
Calculate the permission of the operation on the secure file of the parameter passed account. (It's call the HOOK_file_access in background.)

The return value of this function can be:

Tricks with file hooks

This code changes both the display filename and the storing filename of the uploaded jpeg files with the HOOK_upload_filename_alter hook:

function hook_mymodule_upload_filename_alter($p)
{
    if($p->file_ref->type == 'secure' &&
       $p->file_ref->type == 'image/jpeg')
    {
        $nn = rand(1000, 9999);
        $p->file_ref->name = 'image' . $nn . '.jpg';
        $p->pp_ref['filename'] = time() . '_' . $nn;
    }
}

The following code re-sample all uploaded jpeg images to fit 350x350 size (while keep aspect ratio) with the HOOK_file_uploaded hook:

function hook_mymodule_file_uploaded($f)
{
    if($f->file_ref->mime == 'image/jpeg')
        image_resample($f->file_ref->path, $f->file_ref->path, 350, 350);
}

Image size classes

CodKep also can store images as file object. Often this images should be available in different size than the uploaded size. For example if you do an image gallery the pictures should have an index image variant which has smaller size than the original. The CodKep has a helper mechanism to easy handle this for png,jpeg and gif images. The system achieve this function as lazy which means that the scaled versions is generated when they needed to show not in upload phase. This behaviour enable to create/change size classes on the fly without affecting existing files.

register_image_sizeclass($name, $w, $h)
Registers an image size class in CodKep. By calling this function you will register one (more) image size class with name specified by $name parameter in size $w and $h which are the desired width and the height of the class. (The images always scaled as keeping aspect ratio, so the final sizes may differs from the values specified here. - It means that the scaled image will fit in the specified size but may differs.)

After you define your size classes in the system, the you can tell the CodKep which file should have the size classes to generate. The mechanism similar to file access. You can use the HOOK_file_image_sizeclass($fileobject,$sizeclass) hook to tell which file has the specified size class available.

The HOOK_file_image_sizeclass should one of this value:

In case a size class is defined (by register_image_sizeclass) and the HOOK_file_image_sizeclass hook will return FILE_ACCESS_ALLOW the codkep will generate a scaled version of the file:

You can use the scaled version of the image files by the file class method urlResized($sizeclass). Using example of size classes:

function hook_mymodule_before_start()
{
    ...
    //We will register two size class here
    register_image_sizeclass('40x40',40,40);
    register_image_sizeclass('100x100',100,100);
}

function hook_mymodule_file_image_sizeclass($fileobject,$sizeclass)
{
    //We will allow the scaling only for image files stored in 'customerportraits' directory
    if($fileobject->subdir == 'customerportraits')
        return FILE_ACCESS_ALLOW;
    return FILE_ACCESS_DENY;
}

//We will use the scaled images in this page callback function
function show_user_list()
{
  ...
  foreach($customers as $customer)
  {
    ...
    $cifile = file_load($customer->portrait);
    print l('<img src="' . $cifile->urlResized("100x100") . '"/>',$cifile->url());
    ...
  }
  ...
}

Note 1: If the urlResized($sizeclass) method is called on a file which has size classes disabled (One HOOK_file_image_sizeclass returns FILE_ACCESS_DENY on it) the original file url will returned. It means that the CodKep won't do error handling if non available size class requested instead serve the original (unscaled) file.

Node 2: In case a file is removed by the remove() method the system will check every available size class of the file (according to the HOOK_file_image_sizeclass hook) and remove all scaled version of the file if exists.

Note 3: The size classes are only works on files which are jpeg,png or gif files according to their mime type. Other file types are ignored. (The urlResized() returns same as url property)

Settings of the file module

The file settings which can set in site settings.

namedefaultdescription
$site_config->public_file_path "data" The location of public files in the filesystem on server. (The files can stored in subdirectories here.)
$site_config->public_file_url "/data" The browser URL prefix of public files. (url location)
$site_config->secure_file_path "data/secure" The location of secure files in the filesystem on server. (The files can stored in subdirectories here.)
$site_config->secure_file_url "/data/secure" The browser URL prefix of secure files. This is a callback function by default.
$site_config->file_ufi_lastInsertId_name '' You can specify your own sequence name which used to generate the keys of file table. The empty means autodetect.

Hooks

The following hooks can be implement to interact with file module.

Note: Many of this hooks has an $obj parameter which is a container object holding references to the object and other data structures which are modifiable by the hook.

HookDescription
HOOK_file_access($file,$op,$account)Controls the access to a secured file. Read the file access section for details.
The value of $op can be view,create,delete
HOOK_file_denied($f,$user)Runs before the user will redirect to access denied page. Possible to change the standard "not found" message.
HOOK_file_uploaded($obj)Runs when a file is uploaded, stored in sql. You can see an example here.
HOOK_upload_filename_alter($obj)Runs when a file is uploaded and the local fs name is determined. You can see an example here.
HOOK_file_upload_in($obj)Runs when a file is uploaded but not yet stored in sql.
HOOK_file_loaded($obj)Runs when a file is loaded.
HOOK_file_will_delete($obj)Runs before a file is removed.
HOOK_file_image_sizeclass($fileobject,$sizeclass)Controls the available size classes of the specified file. See size classes above.