Skip to content

Instantly share code, notes, and snippets.

@mungurs
Created April 11, 2017 07:07
Show Gist options
  • Save mungurs/4d73f0978385bfedc3fbcca601de0e3f to your computer and use it in GitHub Desktop.
Save mungurs/4d73f0978385bfedc3fbcca601de0e3f to your computer and use it in GitHub Desktop.
<?
class leafFile extends leafBaseObject
{
const tableName = 'leafFiles';
const defaultFolderMode = 0775; // rwx rwx r-x
const defaultFileMode = 0666; // rw- rw- rw-
const inputFieldSuffix = '_hash';
protected
$path,
$originalName,
$type,
$optimized,
$add_date,
$author_ip
;
protected $fileName;
protected $fieldsDefinition = array(
'path' => array
(
),
'type' => array
(
),
'originalName' => array
(
),
'optimized' => array
(
)
);
protected static $_tableDefsStr = array(
self::tableName => array (
'fields' =>
'
id int auto_increment
path text
originalName text
type varchar(255)
optimized datetime
add_date datetime
author_ip varchar(255)
'
,
'indexes' => '
primary id
index type
',
'engine' => 'innodb'
)
);
public static function _autoload( $className )
{
parent::_autoload( $className );
dbRegisterRawTableDefs( self::$_tableDefsStr );
}
public static function create( $uploadData)
{
if (!is_array($uploadData))
{
return null;
}
unset( $uploadData['localFile'] );
return self::createInternal( $uploadData);
}
public static function createFromLocalFile($fileName, $filePath)
{
$file = array
(
'name' => $fileName,
'tmp_name' => $filePath,
'localFile' => true
);
return self::createInternal( $file );
}
protected static function createInternal( $inputFileData)
{
if (!is_array($inputFileData)){
return null;
}
$localFileMode = (!empty($inputFileData['localFile']));
$uploadMode = !$localFileMode;
$fileData = [ 'originalName' => $inputFileData['name'] ];
if ($uploadMode){
$fileData['type'] = $inputFileData['type'];
}elseif ($localFileMode){
$fileData['type'] = self::getFileType( $inputFileData['tmp_name'] );
}else{
return null;
}
$fileData['path'] = self::getNewFilePath( $fileData );
if(empty($fileData['path']))
{
return null;
}
if($uploadMode && !is_uploaded_file($inputFileData['tmp_name'])){
return null;
}elseif($localFileMode && !is_writable($inputFileData['tmp_name'])){
return null;
}
$pathParts = pathinfo($fileData['path']);
$dirName = $pathParts['dirname'];
$fileName = $pathParts['filename'] . ((!empty($pathParts['extension'])) ? '.' . $pathParts['extension'] : '');
$root = self::getRoot();
$fullDirName = $root . $dirName;
if (!file_exists($fullDirName))
{
$newDirPermissions = self::getNewDirMode( $fileData );
$makeOk = @mkdir($fullDirName, $newDirPermissions, true);
if (!$makeOk)
{
return null;
}
@chmod($fullDirName, $newDirPermissions); // repeat chmod, mkdir permissions sometimes do not work
}
$fullDirName = realpath( $fullDirName );
if ((!$fullDirName) || (!is_dir($fullDirName)) || (!is_writable($fullDirName)))
{
return null;
}
$targetFile = $fullDirName . '/' . $fileName;
if ($uploadMode)
{
$movedOk = @move_uploaded_file( $inputFileData['tmp_name'], $targetFile);
if (!$movedOk)
{
return null;
}
}
elseif ($localFileMode)
{
@rename( $inputFileData['tmp_name'], $targetFile);
}
else
{
return null;
}
@chmod($targetFile, self::getNewFileMode( $fileData ));
$file = getObject(__CLASS__, 0);
$file->assignArray($fileData);
$file->save();
return $file;
}
protected static function getRoot()
{
$root = LEAF_FILE_ROOT;
return $root;
}
protected static function getNewDirMode( $fileData )
{
// custom permission settings depending on $fileData may be implemented if needed
return self::defaultFolderMode;
}
protected static function getNewFileMode( $fileData )
{
// custom permission settings depending on $fileData may be implemented if needed
return self::defaultFileMode;
}
public static function downloadFile($fileId, $downloadType = null)
{
/** @var leafFile $file */
$file = new self($fileId);
if (
(!$file)
||
(empty($file->path))
)
{
die ('file not found');
}
return $file->download($downloadType);
}
public static function getByPath($path){
$queryParts = static::getQueryParts([]);
$queryParts['select'] = 't.id';
$queryParts['where'] = 't.path = "' . $path . '"';
$id = dbgetone($queryParts);
if (!$id)
{
return null;
}
return getObject(__CLASS__, $id);
}
public static function getByDir($dirPath){
$queryParts = static::getQueryParts([]);
$queryParts['select'] = 't.id';
$queryParts['where'] = 't.path LIKE "' . $dirPath . '%"';
$files = $collection = new pagedObjectCollection( __CLASS__, $queryParts );
return $files;
}
protected static function getNewFilePath( $fileData )
{
$dir = null;
if (
(is_object($fileData['ownerObject']))
&&
(method_exists($fileData['ownerObject'], 'getRelativeFilePath'))
)
{
$dir = $fileData['ownerObject']->getRelativeFilePath( $fileData );
}
// use default dir, if no custom folder is set
if(is_null($dir)) // store in class folder by default
{
$dir = $fileData['ownerClass'] . '/';
}
$fileName = $fileData['originalName'];
$fileNameParts = pathinfo($fileName);
$namePart = (empty($fileNameParts['filename'])) ? '' : $fileNameParts['filename'];
$extPart = (empty($fileNameParts['extension'])) ? '' : $fileNameParts['extension'];
$namePart = stringtolatin($namePart, true);
if (strlen($extPart) > 0)
{
$extPart = '.' . stringtolatin($extPart, true);
}
$fileName = $namePart . $extPart;
$limit = 1000;
$i = 0;
$root = self::getRoot();
while (file_exists($root . $dir . $fileName) && $i < $limit)
{
$i++;
$fileName = self::getRandomFileName($namePart, $extPart);
}
if ($i == $limit)
{
// exceeded safety limit
return null;
}
return $dir . $fileName;
}
protected static function getRandomFileName($namePart, $extPart)
{
$suffix = '_' . substr(md5(rand()), 0, 8);
return $namePart . $suffix . $extPart;
}
public function delete( $deleteFolderIfLastFile = false )
{
$fullPath = $this->getFullPath();
if (
(!empty($fullPath))
&&
(file_exists($fullPath))
&&
(is_file($fullPath))
)
{
@unlink( $fullPath );
if ($deleteFolderIfLastFile)
{
$dir = dirname( $fullPath );
if ( self::isDirEmpty( $dir ) )
{
@rmdir ( $dir );
}
}
}
return parent::delete();
}
public static function isDirEmpty( $dir )
{
if (
(!is_dir($dir))
||
(!is_readable($dir))
)
{
return false; // not dir or cant tell if empty
}
$files = scandir( $dir );
if (!is_array($files))
{
return false; // file listing failed
}
foreach ($files as $file)
{
if (
($file == '.') || ($file == '..')
)
{
continue; // skip these
}
return false; // file found, dir not empty
}
return true;
}
public function download($downloadType = null)
{
$fullPath = $this->getFullPath();
if (
(!file_exists($fullPath))
||
(!is_file($fullPath))
||
(!is_readable($fullPath))
)
{
die ('file not found');
}
$download = new fileDownload($fullPath, $this->originalName);
if(!is_null($downloadType))
{
$type = $downloadType;
}
else
{
$type = (empty($this->type)) ? null : $this->type;
}
return $download->download($type);
}
public function getFullPath()
{
$root = self::getRoot();
$fullPath = realpath( $root . $this->path );
return $fullPath;
}
public function getFileName()
{
if (empty($this->fileName))
{
$this->fileName = basename( $this->path );
}
return $this->fileName;
}
public static function getCollection( $params = array (), $itemsPerPage = null, $page = null )
{
$queryParts = array();
$queryParts['select'][] = 'c.*';
$queryParts['from'][] = '`' . leafBaseObject::getClassTable(__CLASS__) . '` `c`';
$queryParts['groupBy'][] = 'c.id';
if (!empty($params['ownerClass']))
{
$queryParts['where'][] = 'c.ownerClass = "' . dbse($params['ownerClass']) . '"';
}
if (
(!empty($params['ownerObjecId']))
&&
(isPositiveInt($params['ownerObjecId']))
)
{
$queryParts['where'][] = 'c.ownerObjectId = ' . $params['ownerObjecId'];
}
$collection = new pagedObjectCollection( __CLASS__, $queryParts );
return $collection;
}
public static function getFileType( $fileName )
{
$contentType = null;
if (!file_exists($fileName))
{
return null;
}
if (function_exists('finfo_open'))
{
$finfo = finfo_open(FILEINFO_MIME);
$contentType = finfo_file( $finfo, $fileName );
}
elseif (function_exists('mime_content_type'))
{
$contentType = mime_content_type( $fileName );
}
if (empty($contentType))
{
return null;
}
$contentType = explode(';', $contentType);
$contentType = trim($contentType[0]);
return $contentType;
}
public function getUrl()
{
// returns default url to file
return LEAF_FILE_ROOT_WWW . $this->path;
}
public static function getFreeFileName( $fullDirPath, $originalFileName = null, $nameSuffix = null )
{
if (
(file_exists($fullDirPath))
&&
(!is_dir($fullDirPath))
)
{
return null;
}
if (empty($originalFileName))
{
$namePart = sha1(str_repeat(uniqid(), 100));
$extPart = '';
}
else
{
$fileNameParts = pathinfo($originalFileName);
$namePart = (empty($fileNameParts['filename'])) ? '' : $fileNameParts['filename'];
$extPart = (empty($fileNameParts['extension'])) ? '' : $fileNameParts['extension'];
$namePart = stringtolatin($namePart, true);
if (strlen($extPart) > 0)
{
$extPart = '.' . stringtolatin($extPart, true);
}
}
if (!is_null($nameSuffix))
{
$namePart .= $nameSuffix;
}
$fileName = $namePart . $extPart;
$limit = 1000;
$i = 0;
while (file_exists($fullDirPath . $fileName) && $i < $limit)
{
$i++;
$fileName = self::getRandomFileName($namePart, $extPart);
}
if ($i == $limit)
{
// exceeded safety limit
return null;
}
return $fileName;
}
public static function getUnoptimizedImages()
{
$qp = array(
'select' => 't.*',
'from' => leafBaseObject::getClassTable( __CLASS__ ) . ' t',
'where' => 't.optimized IS NULL AND t.type LIKE \'image%\''
);
$collection = new pagedObjectCollection( __CLASS__, $qp );
return $collection;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment