Location: PHPKode > projects > Kirby CMS > bastianallgeier-kirbycms-691bb66/kirby/lib/files.php
<?php

// direct access protection
if(!defined('KIRBY')) die('Direct access is not allowed');

class file extends obj {
  
  var $meta = array();
  
  function __toString() {
    return '<a href="' . $this->url() . '">' . $this->url() . '</a>';  
  }

  function meta($code=false) {
    if(!$code) $code = c::get('lang.default');
    return new obj(a::get($this->meta, $code));
  }

  function next() {

    if($this->next) return $this->next;

    $parent = $this->parent();
    if(!$parent) return false;    
    $siblings = $parent->findByType($this->type);
    $index = $siblings->indexOf($this);
    if($index === false) return false;
    
    $siblings  = array_values($siblings->toArray());
    $nextIndex = $index+1;
    return a::get($siblings, $nextIndex);                
  }

  function hasNext() {
    return ($this->next()) ? true : false;     
  }
  
  function prev() {

    if($this->prev) return $this->prev;

    $parent = $this->parent();
    if(!$parent) return false;    
    $siblings = $parent->findByType($this->type);
    $index = $siblings->indexOf($this);
    if($index === false) return false;
    
    $siblings  = array_values($siblings->toArray());
    $prevIndex = $index-1;
    return a::get($siblings, $prevIndex);                
  }

  function hasPrev() {
    return ($this->prev()) ? true : false;       
  }

  function url() {
    return c::get('url') . '/' . $this->uri;  
  }
    
  function info() {

    if($this->info) return $this->info;

    $info = array(
      'size' => f::size($this->root),
      'mime' => (function_exists('mime_content_type')) ? @mime_content_type($this->root) : false
    );
    
    // set the nice size
    $info['niceSize'] = f::nice_size($info['size']);
    
    return $this->info = new obj($info);

  }

  function size() {
    $info = $this->info();
    return $info->size();
  }

  function niceSize() {
    $info = $this->info();
    return $info->niceSize();
  }
  
  function mime() {
    $info = $this->info();
    return $info->mime();
  }
      
}

class image extends file {

  function __construct($array=array()) {
    parent::__construct($array);
    $this->thumb = $this;
    $this->title = $this->name;
  }

  function width() {
    $info = $this->info();
    return $info->width();
  }

  function height() {
    $info = $this->info();
    return $info->height();
  }

  function fit($box, $force=false) {
    $size = size::fit($this->width(), $this->height(), $box, $force);    
    $this->info->width  = $size['width'];
    $this->info->height = $size['height'];
    return $this;
  }

  function fitWidth($width, $force=false) {
    $size = size::fit_width($this->width(), $this->height(), $width, $force);    
    $this->info->width  = $size['width'];
    $this->info->height = $size['height'];
    return $this;      
  }

  function fitHeight($height, $force=false) {
    $size = size::fit_height($this->width(), $this->height(), $height, $force);    
    $this->info->width  = $size['width'];
    $this->info->height = $size['height'];
    return $this;      
  }

  function info() {
    
    if($this->info) return $this->info;
    
    $info = parent::info();
    $size = @getimagesize($this->root);

    if(!$size) {
      $info->width  = false;
      $info->height = false;
    } else {
      $info->width  = $size[0];
      $info->height = $size[1];
      $info->mime   = $size['mime'];
    }

    return $this->info = $info;

  }
  
}

class video extends file {

  function __construct($array=array()) {
    parent::__construct($array);
  }

  function mime() {

    switch($this->extension) {
      case 'ogg':
      case 'ogv':
        return 'video/ogg';
      case 'webm':
        return 'video/webm';
      case 'mp4':
        return 'video/mp4';
    }

    $info = $this->info();
    return $info->mime();

  }

}


class files extends obj {

  var $pagination = null;

  function __toString() {
    $output = array();
    foreach($this->_ as $key => $file) {
      $output[] = $file . '<br />';          
    }    
    return implode("\n", $output);
  }
  
  function init($page) {
        
		foreach($page->rawfiles AS $key => $file) {
      
      // skip invisible files      
      if(preg_match('!^\.!', $file)) continue;
      
			$info = array(
			  'name'      => f::name($file),
				'filename'  => $file,
				'extension' => f::extension($file),
				'root'      => $page->root . '/' . $file,
				'uri'       => $page->diruri . '/' . $file,
				'parent'    => $this,
				'modified'  => @filectime($page->root . '/' . $file)
			);
				
      switch($info['extension']) {
        case 'jpg':
        case 'jpeg':
        case 'gif':
        case 'png':
          $info['type'] = 'image';
          $class = 'image';
          break;
        case 'pdf':
        case 'doc':
        case 'xls':
        case 'ppt':
          $info['type'] = 'document';
          $class = 'file';
          break;
        case 'mov':
        case 'avi':
        case 'ogg':
        case 'ogv':
        case 'webm':
        case 'flv':
        case 'swf':
        case 'mp4':
          $info['type'] = 'video';
          $class = 'video';
          break;
        case 'mp3':
          $info['type'] = 'sound';
          $class = 'file';
          break;
        case c::get('content.file.extension', 'txt'):
          $info['type'] = 'content';
          $class = 'variables';
          break;
        default:
          $info['type'] = 'other';
          $class = 'file';
      }			
    
      $this->$file = new $class($info);
    
    }

    $this->dispatchImages();
    $this->dispatchContent();
              
  }

  function dispatchImages() {
    
    foreach($this->images() as $key => $image) {
      
      // check for images with thumbnail naming      
      if(preg_match('!\.thumb!', $image->name)) {

        // get the rawFilename of the original file to which 
        // this thumb belongs to
        $rawFilename = str_replace('.thumb', '', $image->filename);
                
        // find the original size
        $original = $this->find($rawFilename);        
        
        // if there's no original skip this
        if(!$original) continue;
        
        // attach the thumbnail to the original
        $original->thumb = $image;
        
        // remove it from the list of files
        unset($this->_[$key]);
                                
      }
                      
    }
  
  }

  function dispatchContent() {

    $meta = array();

    $langSupport = c::get('lang.support');
    $translated  = c::get('lang.translated');
            
    foreach($this->contents() as $key => $content) {
            
      // split filenames (already without extension) by .
      $parts      = explode('.', $content->name);
      $countParts = count($parts);
      $lastPart   = a::last($parts);
      $firstPart  = a::first($parts);
      
      // home.txt
      if($countParts == 1) {

        // files without a language code
        // are considered to be the default language file            
        $content->languageCode = c::get('lang.default');

        // keep the entire name for the template (i.e. home)
        $content->template = $content->name;

      // home.en.txt 
      // myfile.jpg.txt 
      // article.video.txt
      } else if($countParts == 2) {

        // check for a matching file by the entire name        
        $file = $this->find($content->name);
        
        // myfile.jpg.txt
        if($file) {

          // change the filetype
          $content->type = 'meta';

          // files without a language code
          // are considered to be the default language file            
          $content->languageCode = c::get('lang.default');
          $file->meta[$content->languageCode] = $content->variables;
          
          // add this to the meta array
          $meta[] = $file;
                                                                    
        // home.en.txt
        // article.video.txt
        } else {
          
          // check for a valid language extension
          // home.en.txt
          if($langSupport && in_array($lastPart, c::get('lang.available', array()))) {         
            
            // use the first part for the template name (i.e. home)
            $content->template = $firstPart;

            // add the language code
            $content->languageCode = $lastPart;

          // plain content file with crazy name
          // article.video.txt
          } else {

            // files without a language code
            // are considered to be the default language file            
            $content->languageCode = c::get('lang.default');

            // use the entire name for the template (i.e. home)
            $content->template = $content->name;

          }

        }


      // myfile.jpg.de.txt
      // article.video.de.txt
      // something more absurd
      } else if($countParts > 2) {
                
        // check for a valid language extension
        // myfile.jpg.de.txt
        // article.video.de.txt
        if($langSupport && in_array($lastPart, c::get('lang.available', array()))) {         
          
          // name without the last part / language code
          $name = implode('.', array_slice($parts, 0, -1));
          
          // check for a matching file by the new name        
          $file = $this->find($name);
          
          // add the language code
          $content->languageCode = $lastPart;
          
          // myfile.jpg.de.txt
          if($file) {
            
            // change the filetype
            $content->type = 'meta';
            $file->meta[$content->languageCode] = $content->variables;

            // add this to the meta array
            $meta[] = $file;
                                    
          // article.video.de.txt
          } else {

            // use the already prepared name for the template (i.e. article.video)
            $content->template = $name;
                    
          }

        // something more absurd
        // article.video.whatever.txt
        // myfile.something.jpg.txt
        // or an invalid language code
        } else {

          // check for a matching file by the new name        
          $file = $this->find($content->name);

          // files without a language code
          // are considered to be the default language file
          $content->languageCode = c::get('lang.default');            
          
          if($file) {
            
            $content->type = 'meta';
            $file->meta[$content->languageCode] = $content->variables;
            
            // add this to the meta array
            $meta[] = $file;

          } else {
                      
            // use the entire name for the template (i.e. article.video.whatever)
            $content->template = $content->name;
          
          }
          
        }
            
      }
    
    }
    
    foreach($meta as $m) {
      
      if($langSupport) {      
        
        $variables = (array)a::get($m->meta, c::get('lang.default'));
                    
        if($translated) {
          $translation = (array)a::get($m->meta, c::get('lang.current'));
          $variables   = (!empty($translation)) ? array_merge($variables, $translation) : $variables;
        }
      
      } else {
        $variables = (array)@a::first($m->meta);
      }
      
      // merge the variables with the file object      
      $m->_ = array_merge($m->_, $variables);
          
    }
                                
  }
  
  function content() {
    return $this->content;
  }
  
  function slice($offset=null, $limit=null) {
    if($offset === null && $limit === null) return $this;
    return new files(array_slice($this->_, $offset, $limit));
  }

  function limit($limit) {
    return $this->slice(0, $limit);
  }

  function offset($offset) {
    return $this->slice($offset);
  }

  function without($name) {
    $files = $this->_;
    unset($files[$name]);
    return new files($files);        
  }

  function not($name) {
    return $this->without($name);
  }

  function find() {
    
    $args = func_get_args();
    
    // find multiple files
    if(count($args) > 1) {
      $result = array();
      foreach($args as $arg) {
        $file = $this->find($arg);
        if($file) $result[$file->filename] = $file;
      }      
      return (empty($result)) ? false : new files($result);
    }    
    
    // find a single file
    $key = a::first($args);      
    if(!$key) return $this->_;
    return a::get($this->_, $key);
  }

  function findByExtension() {

    $args  = func_get_args();
    $count = count($args); 
    if($count == 0) return false;
    
    $files = array();
    foreach($this->_ as $key => $file) {
      if($count > 1) {
        if(in_array($file->extension, $args)) $files[$key] = $file;
      } else {
        if($file->extension == $args[0]) $files[$key] = $file;      
      }
    }   
    return new files($files);      
  }

  function findByType($type) {

    $args  = func_get_args();
    $count = count($args); 
    if($count == 0) return false;

    $files = array();
    foreach($this->_ as $key => $file) {
      if($count > 1) {
        if(in_array($file->type, $args)) $files[$key] = $file;
      } else {
        if($file->type == $args[0]) $files[$key] = $file;      
      }
    }   
    return new files($files);        
  }

  function filterBy() {

    $args     = func_get_args();
    $field    = a::get($args, 0);
    $operator = '=='; 
    $value    = a::get($args, 1);
    $split    = a::get($args, 2);
    
    if($value === '!=' || $value === '==' || $value === '*=') {
      $operator = $value;
      $value    = a::get($args, 2);
      $split    = a::get($args, 3);
    }          
    
    $files = array();

    switch($operator) {

      // ignore matching elements
      case '!=':

        foreach($this->_ as $key => $file) {
          if($split) {
            $values = str::split((string)$file->$field(), $split);
            if(!in_array($value, $values)) $files[$key] = $file;
          } else if($file->$field() != $value) {
            $files[$key] = $file;
          }
        }
        break;    
      
      // search
      case '*=':
        
        foreach($this->_ as $key => $file) {
          if($split) {
            $values = str::split((string)$file->$field(), $split);
            foreach($values as $val) {
              if(str::contains($val, $value)) {
                $files[$key] = $file;
                break;
              }
            }
          } else if(str::contains($file->$field(), $value)) {
            $files[$key] = $file;
          }
        }
                            
      // take all matching elements          
      default:

        foreach($this->_ as $key => $file) {
          if($split) {
            $values = str::split((string)$file->$field(), $split);
            if(in_array($value, $values)) $files[$key] = $file;
          } else if($file->$field() == $value) {
            $files[$key] = $file;
          }
        }

        break;

    }

    return new files($files);    

  }

  function images() {
    return $this->findByType('image');
  }

  function videos() {
    return $this->findByType('video');
  }

  function documents() {
    return $this->findByType('document');
  }

  function sounds() {
    return $this->findByType('sound');
  }

  function contents() {
    return $this->findByType('content');
  }

  function meta() {
    return $this->findByType('meta');
  }

  function others() {
    return $this->findByType('other');
  }
  
  function totalSize() {
    $size = 0;
    foreach($this->_ as $file) {
      $size = $size + $file->size();
    }
    return $size;    
  }

  function niceTotalSize() {
    return f::nice_size($this->totalSize());
  }

  function flip() {
    $files = array_reverse($this->_, true);
    return new files($files);
  }

  function sortBy($field, $direction='asc', $method=SORT_REGULAR) {
    $files = a::sort($this->_, $field, $direction, $method);
    return new files($files);
  }

  function paginate($limit, $options=array()) {

    $pagination = new pagination($this, $limit, $options);
    $files= $this->slice($pagination->offset, $pagination->limit);
    $files->pagination = $pagination;

    return $files;

  }
  
  function pagination() {
    return $this->pagination;
  }
    
}

Return current item: Kirby CMS