Rev 17018 | Rev 17044 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?phpnamespace LeadersLinked\Library;use LeadersLinked\Model\User;use LeadersLinked\Model\UserProfile;use LeadersLinked\Model\Company;use LeadersLinked\Model\Group;use LeadersLinked\Model\StorageFile;use LeadersLinked\Mapper\StorageFileMapper;class Storage{const FILE_TYPE_IMAGE = 'image';const FILE_TYPE_VIDEO = 'video';const FILE_TYPE_DOCUMENT = 'document';const TYPE_DEFAULT = 'default';const TYPE_CHAT = 'chat';const TYPE_GROUP = 'group';const TYPE_USER = 'user';const TYPE_IMAGE = 'image';const TYPE_JOB = 'job';const TYPE_MEDIA = 'media';const TYPE_COMPANY = 'company';const TYPE_FEED = 'feed';const TYPE_POST = 'post';const TYPE_MICROLEARNING_TOPIC = 'topic';const TYPE_MICROLEARNING_CAPSULE = 'capsule';const TYPE_MICROLEARNING_SLIDE = 'slide';const TYPE_JOB_DESCRIPTION = 'jobdesc';const TYPE_SELF_EVALUATION = 'selfval';const TYPE_PERFORMANCE_EVALUATION = 'perfeva';const TYPE_RECRUITMENT_SELECTION = 'recrsel';const TYPE_PLANNING_OBJECTIVES_AND_GOALS = 'plannig';const TYPE_MESSAGE = 'message';const TYPE_SURVEY = 'survey';const TYPE_NETWORK = 'network';const TYPE_DAILY_PULSE = 'dailpuls';const TYPE_ENGAGEMENT_REWARD = 'engarewr';const TYPE_KNOWLEDGE_AREA = 'knowarea';const TYPE_MY_COACH = 'mycoach';const TYPE_HABIT_EMOJI = 'habit-emoji';const TYPE_HABIT_CONTENT = 'habit-content';const BASE_PATH = 'data' . DIRECTORY_SEPARATOR . 'storage';/*** @var \LeadersLinked\Library\Storage*/private static $_instance;/*** @var array*/private $config;/*** @var \Laminas\Db\Adapter\AdapterInterface*/private $adapter;/*** @var string*/private $tempPath;/*** @var string*/private $storagePath;/*** @var array*/private $currentFile;/*** @var array*/private $files;/*** @param array $config* @param \Laminas\Db\Adapter\AdapterInterface $adapter*/private function __construct($config, $adapter){$this->config = $config;$this->adapter = $adapter;$this->currentFile = [];$this->storagePath = self::BASE_PATH;if (!file_exists($this->storagePath)) {mkdir($this->storagePath, 0775, true);}$this->tempPath = self::BASE_PATH . DIRECTORY_SEPARATOR . 'tmp';if (!file_exists($this->tempPath)) {mkdir($this->tempPath, 0775, true);}}/*** @param array $config* @param \Laminas\Db\Adapter\AdapterInterface $adapter* @return \LeadersLinked\Library\Storage*/public static function getInstance($config, $adapter){if (self::$_instance == null) {self::$_instance = new Storage($config, $adapter);}return self::$_instance;}/**** @param User $user* @return string*/public function getUserImage($user){if ($user->image) {$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $this->getPathUser() . DIRECTORY_SEPARATOR . $user->uuid . DIRECTORY_SEPARATOR . $user->image;if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);}}$remoto = $this->config['leaderslinked.images_default.user_image'];return $this->getPresignedUrl($remoto);}/**** @param User $user* @param UserProfile $userProfile* @return string*/public function getUserProfileImage($user, $userProfile){if ($userProfile->image) {$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $this->getPathUser() . DIRECTORY_SEPARATOR . $user->uuid . DIRECTORY_SEPARATOR . $userProfile->image;if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);}}$remoto = $this->config['leaderslinked.images_default.user_profile'];return $this->getPresignedUrl($remoto);}/**** @param User $user* @param UserProfile $userProfile* @return string*/public function getUserProfileCover($user, $userProfile){if ($userProfile->cover) {$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $this->getPathUser() . DIRECTORY_SEPARATOR . $user->uuid . DIRECTORY_SEPARATOR . $userProfile->cover;if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);}}$remoto = $this->config['leaderslinked.images_default.user_cover'];return $this->getPresignedUrl($remoto);}/**** @param Company $company* @return string*/public function getCompanyImage($company){if ($company->image) {$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $this->getPathCompany() . DIRECTORY_SEPARATOR . $company->uuid . DIRECTORY_SEPARATOR . $company->image;if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);}}$remoto = $this->config['leaderslinked.images_default.company_profile'];return $this->getPresignedUrl($remoto);}/**** @param string $code* @param string $filename* @return string*/public function getCompanyImageForCodeAndFilename($code, $filename){if ($filename) {$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $this->getPathCompany() . DIRECTORY_SEPARATOR . $code . DIRECTORY_SEPARATOR . $filename;if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);}}$remoto = $this->config['leaderslinked.images_default.company_profile'];return $this->getPresignedUrl($remoto);}/**** @param Company $company* @return string*/public function getCompanyCover($company){if ($company->cover) {$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $this->getPathCompany() . DIRECTORY_SEPARATOR . $company->uuid . DIRECTORY_SEPARATOR . $company->cover;if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);}}$remoto = $this->config['leaderslinked.images_default.company_cover'];return $this->getPresignedUrl($remoto);}/**** @param Group $group* @return string*/public function getGroupImage($group){if ($group->image) {$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $this->getPathGroup() . DIRECTORY_SEPARATOR . $group->uuid . DIRECTORY_SEPARATOR . $group->image;if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);}}$remoto = $this->config['leaderslinked.images_default.group_profile'];return $this->getPresignedUrl($remoto);}/**** @param string $code* @param string $filename* @return string*/public function getGroupImageForCodeAndFilename($code, $filename){if ($filename) {$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $this->getPathGroup() . DIRECTORY_SEPARATOR . $code . DIRECTORY_SEPARATOR . $filename;if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);}}$remoto = $this->config['leaderslinked.images_default.group_profile'];return $this->getPresignedUrl($remoto);}/**** @param Group $group* @return string*/public function getGroupCover($group){if ($group->cover) {$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $this->getPathGroup() . DIRECTORY_SEPARATOR . $group->uuid . DIRECTORY_SEPARATOR . $group->cover;if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);}}$remoto = $this->config['leaderslinked.images_default.group_cover'];return $this->getPresignedUrl($remoto);}/**** @param Group $group* @return string*/public function getGenericImage($path, $code, $filename){$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $code . DIRECTORY_SEPARATOR . $filename;if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);} else {$remoto = $this->config['leaderslinked.images_default.no_image'];return $this->getPresignedUrl($remoto);}}/**** @param string $path* @param string $code,* @param string $filename* @param boolean $checkExists* @return string*/public function getFileFromDisk($path, $code, $filename){$current_file = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $code . DIRECTORY_SEPARATOR . $filename;if (file_exists($current_file)) {return $current_file;}return;}/**** @param string $path* @param string $code,* @return string*/public function getDirectoryFromDisk($path, $code){$directory = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $code;if (file_exists($directory)) {return $directory;}return;}/**** @param string $path* @param string $code,* @param string $filename* @param boolean $checkExists* @return string*/public function getGenericFile($path, $code, $filename, $checkExists = true){$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $code . DIRECTORY_SEPARATOR . $filename;if ($checkExists) {if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);} else {return;}}return $this->getPresignedUrl($remoto);}public function getPathByType($type){switch ($type) {case TYPE_CHAT:return $this->getPathChat();case TYPE_GROUP:return $this->getPathGroup();case TYPE_USER:return $this->getPathUser();case TYPE_IMAGE:return $this->getPathImage();case TYPE_JOB:return $this->getPathJob();case TYPE_COMPANY:return $this->getPathCompany();case TYPE_FEED:return $this->getPathFeed();case TYPE_POST:return $this->getPathPost();case TYPE_MICROLEARNING_TOPIC:return $this->getPathMicrolearningTopic();case TYPE_MICROLEARNING_CAPSULE:return $this->getPathMicrolearningCapsule();case TYPE_MICROLEARNING_SLIDE:return $this->getPathMicrolearningSlide();case TYPE_JOB_DESCRIPTION:return $this->getPathJobDescription();case TYPE_SELF_EVALUATION:return $this->getPathSelfEvaluation();case TYPE_PERFORMANCE_EVALUATION:return $this->getPathPerformanceEvaluation();case TYPE_RECRUITMENT_SELECTION:return $this->getPathRecruitmentSelection();case TYPE_PLANNING_OBJECTIVES_AND_GOALS:return $this->getPathPlanningObjectivesAnGoals();case TYPE_MESSAGE:return $this->getPathMessage();case TYPE_SURVEY:return $this->getPathSurvey();case TYPE_NETWORK:return $this->getPathNetwork();case TYPE_DAILY_PULSE:return $this->getPathDailyPulse();case TYPE_ENGAGEMENT_REWARD:return $this->getPathEngagementReward();case TYPE_KNOWLEDGE_AREA:return $this->getPathKnowledgeArea();case TYPE_MY_COACH:return $this->getPathMyCoach();case TYPE_HABIT_EMOJI:return $this->getPathHabitEmoji();case TYPE_HABIT_CONTENT:return $this->getPathHabitContent();default:return DIRECTORY_SEPARATOR;}}/**** @param Group $group* @return string*/public function getGenericImageByType($type, $code, $filename){$path = $this->getPathByType($type);$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $code . DIRECTORY_SEPARATOR . $filename;if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);} else {$remoto = $this->config['leaderslinked.images_default.no_image'];return $this->getPresignedUrl($remoto);}}/**** @param string $type* @param string $code,* @param string $filename* @param boolean $checkExists* @return string*/public function getGenericFileByType($type, $code, $filename, $checkExists = true){$path = $this->getPathByType($type);$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $code . DIRECTORY_SEPARATOR . $filename;if ($checkExists) {if (file_exists($remoto)) {return $this->getPresignedUrl($remoto);} else {return;}}return $this->getPresignedUrl($remoto);}/**** @param string $path* @param string $code* @param string $filename* @return string*/public function delete($path, $code, $filename){$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $code . DIRECTORY_SEPARATOR . $filename;return @unlink($remoto);}/**** @return string*/public function getPathMedia(){return $this->config['leaderslinked.storage.fullpath_media'];}/**** @return string*/public function getPathHabitEmoji(){return $this->config['leaderslinked.storage.fullpath_habit_emoji'];}/**** @return string*/public function getPathHabitContent(){return $this->config['leaderslinked.storage.fullpath_habit_content'];}/**** @return string*/public function getPathGroup(){return $this->config['leaderslinked.storage.fullpath_group'];}/**** @return string*/public function getPathUser(){return $this->config['leaderslinked.storage.fullpath_user'];}/**** @return string*/public function getPathImage(){return $this->config['leaderslinked.storage.fullpath_image'];}/**** @return string*/public function getPathJob(){return $this->config['leaderslinked.storage.fullpath_job'];}/**** @return string*/public function getPathChat(){return $this->config['leaderslinked.storage.fullpath_chat'];}/**** @return string*/public function getPathCompany(){return $this->config['leaderslinked.storage.fullpath_company'];}/**** @return string*/public function getPathFeed(){return $this->config['leaderslinked.storage.fullpath_feed'];}/**** @return string*/public function getPathMessage(){return $this->config['leaderslinked.storage.fullpath_message'];}/**** @return string*/public function getPathPost(){return $this->config['leaderslinked.storage.fullpath_post'];}/**** @return string*/public function getPathMicrolearningTopic(){return $this->config['leaderslinked.storage.fullpath_microlearning_topic'];}/**** @return string*/public function getPathMicrolearningCapsule(){return $this->config['leaderslinked.storage.fullpath_microlearning_capsule'];}/**** @return string*/public function getPathMicrolearningSlide(){return $this->config['leaderslinked.storage.fullpath_microlearning_slide'];}/**** @return string*/public function getPathJobDescription(){return $this->config['leaderslinked.storage.fullpath_job_description'];}/**** @return string*/public function getPathSelfEvaluation(){return $this->config['leaderslinked.storage.fullpath_self_evaluation'];}/**** @return string*/public function getPathRecruitmentSelection(){return $this->config['leaderslinked.storage.fullpath_recruitment_selection'];}/**** @return string*/public function getPathPerformanceEvaluation(){return $this->config['leaderslinked.storage.fullpath_performance_evaluation'];}/**** @return string*/public function getPathPlanningObjectivesAnGoals(){return $this->config['leaderslinked.storage.fullpath_planning_objectives_and_goals'];}/**** @return string*/public function getPathSurvey(){return $this->config['leaderslinked.storage.fullpath_survey'];}/**** @return string*/public function getPathNetwork(){return $this->config['leaderslinked.storage.fullpath_network'];}/**** @return string*/public function getPathEngagementReward(){return $this->config['leaderslinked.storage.fullpath_engagement_reward'];}/**** @return string*/public function getPathDailyPulse(){return $this->config['leaderslinked.storage.fullpath_daily_pulse'];}/**** @return string*/public function getPathKnowledgeArea(){return $this->config['leaderslinked.storage.fullpath_knowledge_area'];}/**** @return string*/public function getPathMyCoach(){return $this->config['leaderslinked.storage.fullpath_my_coach'];}/**** @param String $filename* return boolean*/public function objectExist($filename){return file_exists($filename);}/**** @param string $remote* @param string $local* @return boolean*/public function putObject($remote, $local){$dir = dirname($remote);if (!file_exists($dir)) {@mkdir($dir, 0755, true);}return @rename($local, $remote);}/**** @param string $filename* @return boolean*/public function deleteObject($filename){return @unlink($filename);}/**** @param string $path* @param string $code* @param string $filename* @return boolean*/public function deleteFile($path, $code, $filename){if ($code) {$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $code . DIRECTORY_SEPARATOR . $filename;} else {$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $filename;}if (file_exists($remoto)) {return @unlink($remoto);} else {return true;}}/**** @param string $path* @param string $code* @return boolean*/public function deleteDirectory($path, $code){$remoto = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $code;if (file_exists($remoto)) {$this->deleteDirectoryRecursive($remoto);return true;} else {return true;}}/**** @param string $dir*/private function deleteDirectoryRecursive($dir){if (is_dir($dir)) {$objects = scandir($dir);foreach ($objects as $object) {if ($object != '' . '' && $object != '..') {if (is_dir($dir . DIRECTORY_SEPARATOR . $object) && !is_link($dir . '/' . $object)) {@rmdir($dir . DIRECTORY_SEPARATOR . $object);} else {@unlink($dir . DIRECTORY_SEPARATOR . $object);}}}@rmdir($dir);}}/**** @param string $path* @param string $code* @param string $local_filename* @return boolean*/public function putFile($path, $code, $local_filename){if ($code) {$remote = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $code . DIRECTORY_SEPARATOR . basename($local_filename);} else {$remote = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . basename($local_filename);}$dir = dirname($remote);if (!file_exists($dir)) {@mkdir($dir, 0755, true);}return @rename($local_filename, $remote);}/**** @param string $tempfile* @param string $path* @param string $code* @param string $filename* @return boolean*/public function moveAndPutFile($tempfile, $path, $code, $filename){if ($code) {$target_file = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $code . DIRECTORY_SEPARATOR . $filename;} else {$target_file = self::BASE_PATH . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . $filename;}$dir = dirname($target_file);if (!file_exists($dir)) {@mkdir($dir, 0755, true);}return move_uploaded_file($tempfile, $target_file);}/**** @return string*/public function getStoagePath(){return 'data' . DIRECTORY_SEPARATOR . 'storage';}/**** @return string*/public function getTempPath(){$interal_path = 'data' . DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . 'tmp';if (!file_exists($interal_path)) {mkdir($interal_path, 0775);}return $interal_path;}/**** @param string $url* @return string*/public function getPresignedUrl($url){$code = hash('sha256', $url);$storageFileMapper = \LeadersLinked\Mapper\StorageFileMapper::getInstance($this->adapter);$storageFile = $storageFileMapper->fetchOneByCode($code);if (!$storageFile) {$storageFile = new \LeadersLinked\Model\StorageFile();$storageFile->code = $code;$storageFile->path = $url;$storageFile->salt = \LeadersLinked\Library\Functions::generatePassword(8);$storageFileMapper->insert($storageFile);}/*$hostname = empty($_SERVER['HTTP_ORIGIN']) ? '' : $_SERVER['HTTP_ORIGIN'];if(empty($hostname)) {$hostname = empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER'];if(empty($hostname)) {$hostname = empty($_SERVER['HTTP_HOST']) ? '' : $_SERVER['HTTP_HOST'];}}print_r($_SERVER);$hostname = trim(str_replace('http://', 'https://', $hostname));*/return 'https://' . $_SERVER['SERVER_NAME'] . '/storage/' . $code;}/*** Creates a new GD image resource with transparency settings for PNG.* @param int $width The width of the new image.* @param int $height The height of the new image.* @return \GdImage|false The image resource or false on failure.*/private function _createImageCanvas($width, $height){$new_image = imageCreateTrueColor($width, $height);if ($new_image === false) {error_log("_createImageCanvas: imageCreateTrueColor failed for dimensions {$width}x{$height}.");return false;}imageAlphaBlending($new_image, False);imageSaveAlpha($new_image, True);$transparent = imageColorAllocateAlpha($new_image, 0, 0, 0, 127);if ($transparent === false) {error_log("_createImageCanvas: imageColorAllocateAlpha failed.");imagedestroy($new_image);return false;}imagefill($new_image, 0, 0, $transparent);return $new_image;}/*** Saves a GD image resource as PNG, unlinks source, and cleans up image resource.* @param \GdImage $imageResource The GD image resource to save.* @param string $targetFilename The path to save the PNG file to.* @param string $sourceFilenameToUnlink The path to the source file to unlink.* @return bool True on success, false on failure.*/private function _savePngAndCleanup($imageResource, $targetFilename, $sourceFilenameToUnlink){$save_success = imagepng($imageResource, $targetFilename);imagedestroy($imageResource); // Clean up the image resourceif ($save_success) {if ($sourceFilenameToUnlink && file_exists($sourceFilenameToUnlink)) {unlink($sourceFilenameToUnlink);}return true;} else {error_log("_savePngAndCleanup: imagepng failed to save image to {$targetFilename}.");return false;}}/*** @param string $source_filename* @param string $target_filename* @param int $target_width* @param int $target_height* @return boolean*/public function uploadImageResize($source_filename, $target_filename, $target_width, $target_height){try {$data = file_get_contents($source_filename);$img = imagecreatefromstring($data);if ($img) {list($source_width, $source_height) = getimagesize($source_filename);$width_ratio = $target_width / $source_width;$height_ratio = $target_height / $source_height;if ($width_ratio > $height_ratio) {$resized_width = $target_width;$resized_height = $source_height * $width_ratio;} else {$resized_height = $target_height;$resized_width = $source_width * $height_ratio;}$resized_width = round($resized_width);$resized_height = round($resized_height);$new_image = $this->_createImageCanvas($target_width, $target_height);if ($new_image === false) {imagedestroy($img);unlink($source_filename);return false;}imageCopyResampled($new_image, $img, 0, 0, 0, 0, $resized_width, $resized_height, $source_width, $source_height);imagedestroy($img);return $this->_savePngAndCleanup($new_image, $target_filename, $source_filename);}unlink($source_filename);return false;} catch (\Throwable $e) {error_log($e->getTraceAsString());if (isset($img) && ($img instanceof \GdImage || is_resource($img))) {imagedestroy($img);}if (isset($new_image) && ($new_image instanceof \GdImage || is_resource($new_image))) {imagedestroy($new_image);}if (isset($source_filename) && file_exists($source_filename)) {unlink($source_filename);}return false;}}/*** @param string $source_filename* @param string $target_filename* @param int $target_width* @param int $target_height* @return boolean*/public function uploadImageCrop($source_filename, $target_filename, $target_width, $target_height){try {$data = file_get_contents($source_filename);$img = imagecreatefromstring($data);if ($img) {list($source_width, $source_height) = getimagesize($source_filename);$width_ratio = $target_width / $source_width;$height_ratio = $target_height / $source_height;if ($width_ratio > $height_ratio) {$resized_width = $target_width;$resized_height = $source_height * $width_ratio;} else {$resized_height = $target_height;$resized_width = $source_width * $height_ratio;}$resized_width = round($resized_width);$resized_height = round($resized_height);$offset_width = round(($target_width - $resized_width) / 2);$offset_height = round(($target_height - $resized_height) / 2);$new_image = $this->_createImageCanvas($target_width, $target_height);if ($new_image === false) {imagedestroy($img);unlink($source_filename);return false;}imageCopyResampled($new_image, $img, $offset_width, $offset_height, 0, 0, $resized_width, $resized_height, $source_width, $source_height);imagedestroy($img);return $this->_savePngAndCleanup($new_image, $target_filename, $source_filename);}unlink($source_filename);return false;} catch (\Throwable $e) {error_log($e->getTraceAsString());if (isset($img) && ($img instanceof \GdImage || is_resource($img))) {imagedestroy($img);}if (isset($new_image) && ($new_image instanceof \GdImage || is_resource($new_image))) {imagedestroy($new_image);}if (isset($source_filename) && file_exists($source_filename)) {unlink($source_filename);}return false;}}/*** @param string $source_filename* @param string $target_filename* @return boolean*/public function uploadImageWithOutChangeSize($source_filename, $target_filename){try {$data = file_get_contents($source_filename);$img = imagecreatefromstring($data);if ($img) {list($source_width, $source_height) = getimagesize($source_filename);$new_image = $this->_createImageCanvas($source_width, $source_height);if ($new_image === false) {imagedestroy($img);unlink($source_filename);return false;}imageCopyResampled($new_image, $img, 0, 0, 0, 0, $source_width, $source_height, $source_width, $source_height);imagedestroy($img);return $this->_savePngAndCleanup($new_image, $target_filename, $source_filename);}unlink($source_filename);return false;} catch (\Throwable $e) {error_log($e->getTraceAsString());if (isset($img) && ($img instanceof \GdImage || is_resource($img))) {imagedestroy($img);}if (isset($new_image) && ($new_image instanceof \GdImage || is_resource($new_image))) {imagedestroy($new_image);}if (isset($source_filename) && file_exists($source_filename)) {unlink($source_filename);}return false;}}/*** @param string $source_filename* @param string $target_filename* @return boolean*/public static function extractPosterFromVideo($source_filename, $target_filename){try {$cmd = "/usr/bin/ffprobe -v error -of flat=s=_ -select_streams v:0 -show_entries stream=height,width,duration $source_filename";$response = trim(shell_exec($cmd));$source_duration = 0;$lines = explode("\n", $response);foreach ($lines as $line) {$line = trim(strtolower($line));if (strpos($line, 'duration') !== false) {$values = explode('=', $line);$source_duration = intval(str_replace($values[1], '#', ''), 10);}}if ($source_duration == 0) {$second_extract = '00:00:02';} else {if ($source_duration > 10) {$second_extract = '00:00:10';} else {$second_extract = '00:00:02';}}$cmd = "/usr/bin/ffmpeg -y -i $source_filename -pix_fmt yuvj422p -an -ss $second_extract -f mjpeg -t 1 -r 1 -y $target_filename";exec($cmd);return true;} catch (\Throwable $e) {error_log($e->getTraceAsString());return false;}}/*** @param string $str* @return string*/public function normalizeStringFilename($str = ''){$basename = substr($str, 0, strrpos($str, '.'));$basename = str_replace('.', '-', $basename);$extension = substr($str, strrpos($str, '.'));$str = $basename . $extension;$str = strip_tags($str);$str = preg_replace('/[\r\n\t ]+/', ' ', $str);$str = preg_replace('/[\#\"\*\/\:\<\>\?\'\|\,]+/', ' ', $str);$str = strtolower($str);$str = html_entity_decode($str, ENT_QUOTES, "utf-8");$str = htmlentities($str, ENT_QUOTES, "utf-8");$str = preg_replace("/(&)([a-z])([a-z]+;)/i", '$2', $str);$str = str_replace(' ', '-', $str);$str = rawurlencode($str);$str = str_replace('%', '-', $str);$str = str_replace(['-----','----','---','--'], '-', $str);return trim(strtolower($str));}}