Skip to content

Adding file description to Properties dialog

Lawrence Okoth-Odida edited this page Jul 20, 2015 · 7 revisions

Sometimes you need to describe files, for example if you are integrating elFinder with an enterprise document management system. This howto will show how to extend elFinder to show a file description gotten from external source.

  1. Add command for getting/setting description to volume driver. In this example using a file named elFinderVolumeMyDrive.class.php.
<?php

class elFinderVolumeMyDriver extends elFinderVolumeLocalFileSystem {
  // ...

  // Command to implement
  public function desc($target, $newdesc = NULL) {
    // get readable path from hash
    $path = $this->decode($target);

    if ($newdesc == NULL) {
      // Get current the description
      $desc = $this->getYourCoolDescription($target);
    } else {
      // Write a new description
      $desc = $this->writeYourCoolDescription($target, $newdesc);
    }

    return $desc;
  }

  // Get a description of the $target
  // @return the description if it exists; -1 otherwise
  protected function getYourCoolDescription($target) {
    // Your implementation here
    // This one just returns 'desc' every time
    return 'desc';
  }

  // Writing a description for the $target
  // @return the description if successful; -1 otherwise
  protected function writeYourCoolDescription($target, $newdesc) {
    // Your implementation here
    // This one just returns the new description
    return $newdesc;
  }

  // ...
}

Implement getYourCoolDescription($target) and writeYourCoolDescription($target, $newdesc) with real code for getting/setting the description from external source.

  1. Register the command in the elFinder object. In this example using a file named myelFinder.class.php.
<?php

class myelFinder extends elFinder {
  // Custom error message if description isn't found
  const ERROR_DESC_NOT_FOUND = 'Description not found';

  // ...

  // Modify the constructor
  // Run the old constructor and register 'desc' as a new command
  public function __construct($opts) {
    parent::__construct($opts);
    $this->commands['desc'] = array('target' => TRUE, 'content' => FALSE);
  }

  // Implement the desc command
  protected function desc($args) {
    // Get the target directory and $desc parameter
    $target = $args['target'];
    $desc   = $args['content'];

    // Get the volume, and if successful, the file
    $volume = $this->volume($target);
    $file   = $volume ? $volume->file($target) : false;

    // Check if desc is disabled, and if we can get the true description
    $disabled = $volume ? $volume->commandDisabled('desc') : false;
    $desc     = (!$disabled && $volume) ? $volume->desc($target, $desc) : false;

    // Start accumulating the results
    $results = array();

    if (!$file) {
      // File not found; send "file not found" error message
      $results['error'] = $this->error(self::ERROR_FILE_NOT_FOUND);
    } elseif ($disabled) {
      // Command disabled; send "access denied" messsage, with filename
      $results['error'] = $this->error(self::ERROR_ACCESS_DENIED, $file['name']);
    } elseif ($desc == -1) {
      // No description; send "description not found" message, with filename
      $results['error'] = $this->error(self::ERROR_DESC_NOT_FOUND, $file['name']);
    } else {
      // Success!
      $results['desc'] = $desc; 
    }

    return $results;
  }

  // ...
}
  1. Include these extended files (elFinder subclass and custom volume driver) in the connector.
<?php
include_once dirname(__FILE__).DIRECTORY_SEPARATOR.'elFinderConnector.class.php';
include_once dirname(__FILE__).DIRECTORY_SEPARATOR.'elFinder.class.php';
include_once dirname(__FILE__).DIRECTORY_SEPARATOR.'elFinderVolumeDriver.class.php';
include_once dirname(__FILE__).DIRECTORY_SEPARATOR.'elFinderVolumeLocalFileSystem.class.php';
// don't forget our new included files
include_once dirname(__FILE__).DIRECTORY_SEPARATOR.'elFinderVolumeMyDrive.class.php';
include_once dirname(__FILE__).DIRECTORY_SEPARATOR.'elmyFinder.class.php';

$opts = array( 
 'roots' => array(
    array(
      'driver' => 'MyDriver',  // use my custom volume driver
      'path' => '/tmp/myfiles',
      'URL' => 'http://example.com/my-files/',
    ),
 ),
);

$connector = new elFinderConnector(new elmyFinder($opts), true);  // instantiate using our custom elFinder object
$connector->run();
  1. Edit js/commands/info.js and extend it with following code using the new connector command to get/set description
// add a 'desc' item to the 'msg' variable near the top of the file
        msg = {
            calc : fm.i18n('calc') ,
            size : fm.i18n('size') ,
            unknown : fm.i18n('unknown') ,
            path : fm.i18n('path') ,
            aliasfor : fm.i18n('aliasfor') ,
            modify : fm.i18n('modify') ,
            perms : fm.i18n('perms') ,
            locked : fm.i18n('locked') ,
            dim : fm.i18n('dim') ,
            kind : fm.i18n('kind') ,
            files : fm.i18n('files') ,
            folders : fm.i18n('folders') ,
            items : fm.i18n('items') ,
            yes : fm.i18n('yes') ,
            no : fm.i18n('no') ,
            link : fm.i18n('link') ,
            desc: fm.i18n('desc') // our new property
        };
// add the dialog control markup after the 3 'content.push' lines in the middle of the file
var editDesc = true;
var desc = '<div id="elfinder-fm-file-desc">' + msg.calc + '</div>';        
if (editDesc)  {    
	desc  = '<textarea cols="20" rows="5" id="elfinder-fm-file-desc" class="ui-widget ui-widget-content" disabled="true" >' + msg.calc + '</textarea><input type="button" id="elfinder-fm-file-desc-btn-save" value="' + fm.i18n('btnSave') + '" />';
}

content.push(row.replace(l, 'Description').replace(v , desc));
        
fm.request({
	data : {
		cmd : 'desc', 
		target : file.hash
		},
	preventDefault : true
})
.done(function(data) {
	var fieldDesc = dialog.find('#elfinder-fm-file-desc');
          
	if (editDesc)  {
		fieldDesc.val(data.desc || '');
		fieldDesc.removeAttr('disabled');
	} else {
		fieldDesc.empty();
		fieldDesc.html(data.desc || '');
	}
});
// just above the 'Load Thumbnail' code
    if (editDesc) {
      var inputDesc = $('#elfinder-fm-file-desc', dialog);
      var btnSave = $('#elfinder-fm-file-desc-btn-save', dialog).button();
      
      btnSave.click(function() {
        fm.lockfiles({files : [file.hash]});
        fm.request({
          data   : {cmd : 'desc', target : file.hash, content : inputDesc.val()},
          notify : {type : 'desc', cnt : 1}
          })
					.always(function() {
						fm.unlockfiles({files : [file.hash]})
					});
      });
    }

Full extended info command source code can be found at http://drupalcode.org/project/elfinder.git/blob/refs/heads/7.x-2.x:/js/info.js

  1. Finally, initialize the client using the following:
<script type="text/javascript" src="elfinder.min.js"></script>
<script type="text/javascript" src="info.js"></script>
<script type="text/javascript">

$().ready(function() {
  if (Drupal.settings.elfinder) {

    var elfinderOpts = {
      url : Drupal.settings.elfinder.connectorUrl,
      lang : Drupal.settings.elfinder.langCode,
      rememberLastDir : Drupal.settings.elfinder.rememberLastDir,
      closeOnEditorCallback : false
    }
	
    $('#finder').elfinder(elfinderOpts);
  }
});
</script>
Clone this wiki locally