n1ed-8.x-2.31/src/Flmngr/fs/DriverLocal.php

src/Flmngr/fs/DriverLocal.php
<?php

namespace Drupal\n1ed\Flmngr\fs;

use Drupal\n1ed\Flmngr\model\Message;
use Drupal\n1ed\Flmngr\lib\file\Utils;
use Drupal\n1ed\Flmngr\lib\MessageException;

class DriverLocal {

  private $dir;

  private $isCacheDriver;

  // Link to cache driver
  // NULL if we are inside cache driver instance
  private $driverCache;

  // Some cached info (array of named chunks)
  // Access it only by getCacheChunk() and write by setCacheChunk()
  private $cacheChunks = [];

  // For use by FileSystem.php only, do not override
  public function setDriverCache($driverCache) {
    $this->driverCache = $driverCache;
  }

  function __construct($config, $isCacheDriver = FALSE) {
    $this->isCacheDriver = $isCacheDriver;

    if (!in_array('dir', array_keys($config)) || $config['dir'] === NULL) {
      try {
        throw new MessageException(
          Message::createMessage(
            $this->isCacheDriver,
            Message::FM_ROOT_DIR_IS_NOT_SET
          )
        );
      } catch (Exception $e) {
        error_log(print_r($e, TRUE));
      }
    }

    $this->dir = rtrim($config['dir'], '\\/');

    $this->makeRootDir();

    if (!is_readable($this->dir)) {
      throw new MessageException(
        Message::createMessage(
          $this->isCacheDriver,
          Message::FM_DIR_IS_NOT_READABLE,
          $this->dir
        )
      );
    }

    if (!is_writable($this->dir)) {
      throw new MessageException(
        Message::createMessage(
          $this->isCacheDriver,
          Message::FM_DIR_IS_NOT_WRITABLE,
          $this->dir
        )
      );
    }

  }

  private function getCacheChunkPath($chunkName) {
    return "/fs/" . $chunkName . ".json";
  }

  // Returns "path-to-cache/fs/driver-name/chunk-name.json" content
  // i. e. ".cache/fs/all-files.json"
  // if file modify time is not older then $validSeconds
  // Returns NULL if file does not exist of outdated
  function &getCacheChunk($chunkName, $validSeconds) {

    if (in_array($chunkName, $this->cacheChunks)) {
      return $this->cacheChunks[$chunkName];
    }

    $chunkPath = $this->getCacheChunkPath($chunkName);
    if ($this->driverCache->fileExists($chunkPath) && time() - $this->driverCache->lastModified($chunkPath) <= $validSeconds) {
      $content = $this->driverCache->get($chunkPath);
      $json = json_decode($content, JSON_OBJECT_AS_ARRAY);
      return $json;
    }
    else {
      $null = NULL;
      return $null;
    }

  }

  function setCacheChunk($chunkName, &$json) {
    $chunkPath = $this->getCacheChunkPath($chunkName);
    $chunkPathDir = dirname($chunkPath);
    $this->driverCache->makeDirectory($chunkPathDir, 0777, TRUE);
    $this->driverCache->put($chunkPath, json_encode($json, JSON_PRETTY_PRINT));
  }

  function deleteCacheChunk($chunkName) {
    try {
      $chunkPath = $this->getCacheChunkPath($chunkName);
      if ($this->driverCache->fileExists($chunkPath)) {
        $this->driverCache->delete($chunkPath);
      }
    } catch (Exception $e) {
      error_log("Error on deleting cache chunk");
      error_log($e);
    }
  }

  function getDriverName() {
    return "Local";
  }

  function getDir() {
    return $this->dir;
  }

  function size($path) {
    return filesize($this->dir . $path);
  }

  function lastModified($path) {
    return filemtime($this->dir . $path);
  }

  function makeDirectory($path) {

    if (file_exists($this->dir . $path) && is_dir($this->dir . $path)) {
      return;
    }

    $result = mkdir($this->dir . $path, 0777, TRUE);
    if (!$result) {
      throw new MessageException(
        Message::createMessage(
          $this->isCacheDriver,
          Message::FM_UNABLE_TO_CREATE_DIRECTORY,
          $path
        )
      );
    }
  }

  function getRootDirName() {
    $i = strrpos($this->dir, '/');
    if ($i === FALSE) {
      return $this->dir;
    }
    return substr($this->dir, $i + 1);
  }

  function makeRootDir() {
    if (!$this->directoryExists("")) {
      $this->makeDirectory("");
    }
  }

  const MAX_DEPTH = 20;

  function allDirectories() {
    $dirs = [];
    $fDir = $this->dir;

    if (!file_exists($fDir) || !is_dir($fDir)) {
      error_log("Root directory does not exist: " . $fDir);
      throw new MessageException(
        Message::createMessage(
          $this->isCacheDriver,
          Message::FM_ROOT_DIR_DOES_NOT_EXIST
        )
      );
    }
    $hideDirs[] = '.cache';

    $this->getDirs__fill($dirs, $fDir, $hideDirs, '', 0);
    return $dirs;
  }

  private function getDirs__fill(&$dirs, $fDir, $hideDirs, $path, $currDepth) {
    $i = strrpos($fDir, '/');
    if ($i !== FALSE) {
      $dirName = substr($fDir, $i + 1);
    }
    else {
      $dirName = $fDir;
    }

    $dirs[] = (strlen($path) > 0 ? '/' . $path : '') . '/' . $dirName;

    $rawDirs = glob($fDir . '/*', GLOB_ONLYDIR);
    if ($rawDirs === FALSE) {
      throw new MessageException(
        Message::createMessage(
          $this->isCacheDriver,
          Message::FM_UNABLE_TO_LIST_CHILDREN_IN_DIRECTORY
        )
      );
    }

    foreach ($rawDirs as $dir) {
      $dir = str_replace($fDir . '/', '', $dir);

      $isHide = FALSE;
      for ($j = 0; $j < count($hideDirs) && !$isHide; $j++) {
        $isHide = $isHide || fnmatch($hideDirs[$j], $dir);
      }

      if (is_dir($fDir . '/' . $dir) && !$isHide && $currDepth < self::MAX_DEPTH) {
        $this->getDirs__fill(
          $dirs,
          $fDir . '/' . $dir,
          $hideDirs,
          $path . (strlen($path) > 0 ? '/' : '') . $dirName,
          $currDepth + 1
        );
      }
    }
  }

  function directories($path) {
    $dirs = [];
    try {
      $rawDirs = glob($this->dir . $path . '/*', GLOB_ONLYDIR);
    } catch (Exception $e) {
      throw new MessageException(
        Message::createMessage(
          $this->isCacheDriver,
          Message::DIR_DOES_NOT_EXIST,
          $path
        )
      );
    }
    foreach ($rawDirs as $dir) {
      $dirs[] = str_replace($this->dir . $path . '/', '', $dir);
    }
    return $dirs;
  }

  function files($path) {
    try {
      $rawFiles = glob($this->dir . $path . '/*');
    } catch (Exception $e) {
      error_log("Error while reading dir contents: " . $path);
      error_log($e);
      throw new MessageException(
        Message::createMessage(
          $this->isCacheDriver,
          Message::FM_DIR_CANNOT_BE_READ
        )
      );
    }

    $files = [];
    foreach ($rawFiles as $file) {
      if (is_file($file)) {
        $filename = basename($file);
        $files[] = [
          'name' => $filename,
          'mtime' => $this->lastModified($path . '/' . $filename),
          'size' => $this->size($path . '/' . $filename),
        ];
      }
    }
    return $files;
  }

  function move($path, $newName) {
    $res = rename($this->dir . $path, $this->dir . $newName);
    if ($res === FALSE) {
      throw new MessageException(
        Message::createMessage(
          $this->isCacheDriver,
          Message::FM_UNABLE_TO_RENAME
        )
      );
    }
  }

  function getMimeType($path) {
    return Utils::getMimeType($this->dir . $path);
  }

  function exists($path) {
    return file_exists($this->dir . $path);
  }

  function directoryExists($path) {
    return file_exists($this->dir . $path) && is_dir($this->dir . $path);
  }

  function fileExists($path) {
    return file_exists($this->dir . $path) && is_file($this->dir . $path);
  }

  // Get file contents
  function get($path) {
    return file_get_contents($this->dir . $path);
  }

  // Put file contents
  function put($path, $contents) {
    $this->makeDirectory(dirname($path)); // ensure dir exists
    file_put_contents($this->dir . $path, $contents);
  }

  // Dir (not empty) or file
  function delete($path) {
    if (is_file($this->dir . $path)) {
      $result = @unlink($this->dir . $path);
      if ($result === FALSE) {
        throw new MessageException(
          Message::createMessage(
            $this->isCacheDriver,
            Message::UNABLE_TO_DELETE_FILE,
            $path
          )
        );
      }

    }
    else {

      // There can be a try to delete unexisting file (in cache dir),
      // so we will have is_file() == false and fall here.
      // So there is required to check does this dir actually exists.
      if (is_dir($this->dir . $path)) {

        foreach ($this->directories($path) as $dir) {
          $this->delete($path . '/' . $dir);
        }

        foreach ($this->files($path) as $file) {
          $this->delete($path . '/' . $file['name']);
        }

        $this->deleteDirectory($path);

      }
    }
  }

  // Delete empty dir
  function deleteDirectory($path) {
    $result = rmdir($this->dir . $path);
    if ($result === FALSE) {
      throw new MessageException(
        Message::createMessage(
          $this->isCacheDriver,
          Message::FM_UNABLE_TO_DELETE_DIRECTORY
        )
      );
    }
  }

  // Returns stream for `fpassthru`
  function readStream($path) {
    return fopen($this->dir . $path, 'rb');
  }

  function copyFile($pathSrc, $pathDst) {
    $res = copy($this->dir . $pathSrc, $this->dir . $pathDst);
    if ($res === FALSE) {
      throw new MessageException(
        Message::createMessage(
          $this->isCacheDriver,
          Message::FM_ERROR_ON_COPYING_FILES
        )
      );
    }
  }

  function copyDirectory($src, $dst) {
    $this->copyDirectory__recurse($src, $dst, FALSE);
  }

  private function copyDirectory__recurse($src, $dst, $createThisDstDir) {
    // Do not create a root directory (target directory to copy inside already exists)
    if ($createThisDstDir) {
      $this->makeDirectory($dst);
    }

    $fFiles = $this->files($src);
    foreach ($fFiles as $file) {
      $fileName = $file['name'];
      if ($fileName != '.' && $fileName != '..') {
        if ($this->directoryExists(TRUE, $src . '/' . $fileName)) {
          $this->copyDir__recurse(
            $src . '/' . $fileName,
            $dst . '/' . $fileName,
            TRUE
          );
        }
        else {
          $this->copyFile($src . '/' . $fileName, $dst . '/' . $fileName);
        }
      }
    }
  }

  function uploadFile__getName($file, $dir, $isOverwrite) {
    if ($isOverwrite) {
      // Remove existing file if exists
      $name = $file['name'];
      if ($this->exists($dir . '/' . $name))
        $this->delete($dir . '/' . $name);
    } else {
      // Get free file name
      $i = -1;
      do {
        $i++;
        if ($i == 0) {
          $name = $file['name'];
        }
        else {
          $name =
            Utils::getNameWithoutExt($file['name']) .
            '_' .
            $i .
            (Utils::getExt($file['name']) != NULL
              ? '.' . Utils::getExt($file['name'])
              : '');
        }
        $ok = !$this->exists($dir . '/' . $name);
      } while (!$ok);
    }
    return $name;
  }

  function uploadFile($file, $dir, $isOverwrite) {

    $name = $this->uploadFile__getName($file, $dir, $isOverwrite);

    $result = move_uploaded_file($file['tmp_name'], $this->dir . $dir . '/' . $name);
    if (!$result) {
      throw new MessageException(
        Message::createMessage(
          $this->isCacheDriver,
          Message::WRITING_FILE_ERROR,
          $dir . '/' . $file['name']
        )
      );
    }

    return $name;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc