I have a class that uses Assetic to generate some css files to disk. I'll jump right into the code.
In my layout header, I'm doing something like this:
$assetify = new Assetify();
$assetify->setDebug(true);
$assetify->setAssetDirectory(BASE_DIR . '/public/assets');
$assetify->setOutputDirectory(BASE_DIR . '/public/assets/generated');
$assetify
->addStylesheet('/assets/css/bootstrap-2.3.2.css')
->addStylesheet('/assets/css/select2-3.4.3.css')
->addStylesheet('/assets/css/main.css');
echo $assetify->dump();
My "Assetify" class runs this through Assetic. I'll paste what I hope are only the relevant portions from the dump() function:
// The Asset Factory allows us to not have to do all the hard work ourselves.
$factory = new AssetFactory($this->assetDirectory, $this->debug);
$factory->setDefaultOutput('/generated/*.css');
// The Filter Manager allows us to organize filters for the asset handling.
// For other filters, see: https://github.com/kriswallsmith/assetic
$fm = new FilterManager();
$fm->set('yui_css', new Yui\CssCompressorFilter('/usr/local/bin/yuicompressor-2.4.7.jar'));
$fm->set('yui_js', new Yui\JsCompressorFilter('/usr/local/bin/yuicompressor-2.4.7.jar'));
$factory->setFilterManager($fm);
// The Asset Manager allows us to keep our assets organized.
$am = new AssetManager();
$factory->setAssetManager($am);
// The cache-busting worker prefixes every css with what amounts to a version number.
$factory->addWorker(new CacheBustingWorker());
$assetCollection = array();
foreach ($assetGroups as $assetGroup) {
foreach ($assetGroup as $media => $items) {
$fileCollection = array();
foreach ($items as $item) {
// Add this asset to the asset collection.
$fileCollection[] = new FileAsset($item);
}
$assetCollection[] = new AssetCollection($fileCollection);
}
}
$assetCollection = new AssetCollection($assetCollection);
$am->set('base_css', $assetCollection);
// Generate the required assets. Prefixing a filter name with a question mark
// will cause that filter to be omitted in debug mode.
$asset = $factory->createAsset(
array('#base_css'),
array('?yui_css')
);
// Configure an internal file system cache so we don't regenerate this file on every load.
$cache = new AssetCache(
$asset,
new FilesystemCache($this->outputDirectory)
);
// And generate static versions of the files on disk.
$writer = new AssetWriter($this->assetDirectory);
$writer->writeAsset($cache);
This generates two different files, 87229eb-f47a352.css and a37c1589762f39aee5bd24e9405dbdf9. The contents of the files are exactly the same. The 87229eb-f47a352.css file seems to get generated every single time, and the other file is not regenerated unless the contents of the files change (this is what I would like). If I comment out the $writer->writeAsset($cache), no files are written to disk.
What obvious configuration am I missing? I appreciate the help, thank you.
I was able to roughly replicate your code and got the same results.
I was trying to get the same results as what I think you require but ended up writing my own code to cache and serve static files.
It's not complete by any means but it is working. It has the following features:
You can choose to cache files for different pages if you specify $filename
You can choose to create versions of your released files or delete previous versions
A cached file will be generated to your target folder only if changes have made to a source file
You just need to put the code in to a class or function and return the url to serve.
Hope it helps :)
<?php
use Assetic\Factory\AssetFactory;
use Assetic\AssetManager;
use Assetic\FilterManager;
use Assetic\Asset\AssetCollection;
use Assetic\Asset\FileAsset;
use Assetic\Filter\JSMinFilter;
// JavaScript Collection
$js_collection[] = new FileAsset(SCRIPT_PATH . 'jquery.js');
$js_collection[] = new FileAsset(SCRIPT_PATH . 'production.js');
if (file_exists(SCRIPT_PATH . $page_info['name'] . '.js')) {
$js_collection[] = new FileAsset(SCRIPT_PATH . $page_info['name'] . '.js');
}
// CSS Collection
$css_collection[] = new FileAsset(STYLE_PATH . 'theme.css');
if (file_exists(STYLE_PATH . $page_info['name'] . '.css')) {
$css_collection[] = new FileAsset(STYLE_PATH . $page_info['name'] . '.css');
}
// The Filter Manager allows us to organize filters for the asset handling.
$fm = new FilterManager();
$fm->set('js', new JSMinFilter());
$js = new AssetCollection (
$js_collection
);
$js->setTargetPath(SCRIPT_PATH . 'static');
$css = new AssetCollection (
$css_collection
);
$css->setTargetPath(STYLE_PATH . 'static');
$am = new AssetManager();
$am->set('js', $js);
$am->set('css', $css);
//** TO DO: put the below in a class and return the static file names **//
// options
$seperator = '-';
$filename = $page_info['name'];
$versions = false;
// get a list of all collection names
$collections = $am->getNames();
// get each collection
foreach ($collections as $collection_name) {
// get the collection object
$collection = $am->get($collection_name);
// ensure file types are identical
$last_ext = false;
foreach ($collection as $leaf) {
$ext = strtolower(pathinfo($leaf->getSourcePath(), PATHINFO_EXTENSION));
if (!$last_ext || $ext == $last_ext) {
$last_ext = $ext;
} else {
throw new \RuntimeException('File type mismatch.');
}
}
// get the highest last-modified value of all assets in the current collection
$modified_time = $collection->getLastModified();
// get the target path
$path = $collection->getTargetPath();
// the target path must be set
if (!$path) {
throw new \RuntimeException('Target path not specified.');
}
// build the filename to check
$file = ($filename) ? $filename . $seperator . $modified_time . '.' . $ext : $modified_time . '.' . $ext;
$cached_file = $path . '/' . $file;
// the file doesn't exist so we need to minify, dump and save as new cached file
if (!file_exists($cached_file)) {
// create the output dir if it doesnt exist
if (!is_dir($path) && false === #mkdir($path, 0777, true)) {
throw new \RuntimeException('Unable to create directory ' . $path);
}
// apply the filters
if ($fm->has($collection_name)) {
$collection->ensureFilter($fm->get($collection_name));
}
// If not versioned, delete previous version of this file
if (!$versions) {
if ($filename) {
foreach (glob($path . '/' . $filename . $seperator . '*.' . $ext) as $searchfile) {
#unlink($searchfile);
}
} else {
foreach (glob($path . '/*.' . $ext) as $searchfile) {
#unlink($searchfile);
}
}
}
// put the contents in the file
if (false === #file_put_contents($cached_file, $collection->dump())) {
throw new \RuntimeException('Unable to write file ' . $cached_file);
}
}
// return the cached file
echo 'output: ' . $cached_file . '<br>';
}
exit;
?>
Related
I'm saving files locally in Laravel, however I'm having issues getting the right URL and accessing the files.
I've setup a symlink with Artisan:
php artisan storage:link
When saving, I add public/ to the name, so the files are placed in the /storage/app/public/ directory, which works.
if ($request->hasFile('files')) {
$files = array();
foreach ($request->file('files') as $file) {
if ($file->isValid()) {
$name = time() . str_random(5) . '.' . $file->getClientOriginalExtension();
Storage::disk('public')->put($name, $file);
$files[] = $name;
}
}
if (count($files) > 0) {
$response->assets = json_encode($files);
}
}
The name is stored in the database
["1524042807kdvws.pdf"]
Then the assets are returned as part of a JSON object via my API for Vue
if (count($response->assets) > 0) {
$assets = array();
foreach (json_decode($response->assets, true) as $asset) {
$assets[] = asset($asset);
}
$responses[$key]->assets = $assets;
}
Which returns http://127.0.0.1:8000/1524042807kdvws.pdf but that 404s. I've gotten myself a little confused I think, so any pointers or help would be appreciated.
So I found my answer on another post
I needed to wrap the $file in file_get_contents();
Storage::disk('public')->put($name, $file);
and instead of asset() I used:
Storage::disk('public')->url($asset['file']);
Check this docs. https://laravel.com/docs/5.5/filesystem#the-public-disk
As it shows there instead of
$name = 'public/' . time() . str_random(5) . '.' . $file->getClientOriginalExtension();
you can just have
$name = 'time() . str_random(5) . '.' . $file->getClientOriginalExtension();
Storage::disk("public")->put($name, $file); // assuming you have the public disk that comes by default
Then when you want to get an url, you can use the asset function
asset('storage/foo.txt');
I need to take backup of code for my Project, but the condition is :-
I generate a Patch folder through SVN, which has files structured in the same way as it is in the main Project folder (the patch has lesser files than the main project). I want to write a code which reads the main project and picks only those files which are present in the patch and saves it in a new backup folder.
The code which i wrote is :-
/*Patch Folder */
$frmFoldr = 'patch_test/';
$basepath = '/var/www/html/TestingBackupCron/';
/*The Folder where files are to be backed up it would use basepath and toFoldr folder name. */
$toFoldr = 'axisdirectcheck/';
/* Read/Copy File from this folder. */
$prodMainFolder = '';
$prodBasePath = '/var/www/html/TestingBackupCron/sijucheckfiles/';
$dir_iterator = new RecursiveDirectoryIterator($basepath . $frmFoldr);
$iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file) {
$readDir = strstr($file->getPathname(), $frmFoldr);
$tofileminpath = str_replace($frmFoldr, "", $readDir);
$fromExPath = $prodBasePath . $tofileminpath;
$toExPath = $basepath . $toFoldr . $tofileminpath;
if (strpos($fromExPath, '.php') || strpos($fromExPath, '.js') || strpos($fromExPath, '.css')) {
if (file_exists($fromExPath)) {
copy($fromExPath, $toExPath);
print_r('Files copied to ' . $toExPath . ".\n");
}else{
print_r($fromExPath." ::: Read path not found.\n");
}
}
}
The above code gives me the error "failed to open stream: No such file or directory". I think copy doesn't create folders. Please help guys.
Found a solution. Below code would create folders first and then on the next loop it would write the copied files onto those folders.
public function run($args) {
/*Patch Folder */
$frmFoldr = 'patch_test/';
$basepath = '/var/www/html/TestingBackupCron/';
/*The Folder where files are to be backed up it would use basepath and toFoldr folder name. */
$toFoldr = 'axisdirectcheck/';
/* Read/Copy File from this folder. */
$prodMainFolder = '';
$prodBasePath = '/var/www/html/TestingBackupCron/sijucheckfiles/';
if (file_exists($basepath . $frmFoldr)) {
$dir_iterator = new RecursiveDirectoryIterator($basepath . $frmFoldr);
$iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
} else{
print_r("Read Directory '$basepath$frmFoldr' not Found. Please check the read directory filename.\n");
exit;
}
$fromDir = array();
$sendToArray = array();
/* this foreach would create folders inside the path ($toFoldr) specified */
foreach ($iterator as $file) {
$readDir = strstr($file->getPathname(), $frmFoldr);
$tofileminpath = str_replace($frmFoldr, "", $readDir);
$fromExPath = $basepath . $readDir;
$toExPath = $basepath . $toFoldr . $tofileminpath;
$sendToArray[] = $tofileminpath;
if (strpos($file, '/.')) {
if (!file_exists($toExPath)) {
$oldmask = umask(0);
mkdir("$toExPath", 0777, true);
umask($oldmask);
}
}
}
/* this foreach would copy files from PROD/UAT and paste inside the path($toExPath) specified */
foreach ($sendToArray as $fPath) {
$fromExPath = $prodBasePath . $fPath;
$toExPath = $basepath . $toFoldr . $fPath;
if (strpos($fromExPath, '.php') || strpos($fromExPath, '.js') || strpos($fromExPath, '.css')) {
if (file_exists($fromExPath)) {
copy($fromExPath, $toExPath);
print_r('Files copied to ' . $toExPath . ".\n");
}else{
print_r($fromExPath." ::: Read path not found.\n");
}
}
}
}
Thanks..
Running Apache 2.2 with PHP 5.3 on Windows 8. Trying to get the PHP class ImapMailbox to download attachments, but each time I getMail(), the attachments value is empty on every email that has attachments.
All the rest of the email info is downloaded correctly.
I've looked through the class code but can't identify where the problem might be.
Here is my current code:
$mailbox = new ImapMailbox('{testsite.com:110/pop3/novalidate-cert}INBOX', 'testemail#testsite.com', 'MyPaSs', ATTACH_DIR, 'utf-8');
$mails = array();
foreach($mailbox->searchMailbox('SUBJECT "test attach" SINCE "' . date('m/d/Y', strtotime('-1 week')) . '"') as $mailId) {
$mail = $mailbox->getMail($mailId);
$mails[] = $mail;
}
After dumping the $data var in getMail(), it appears there are attachments in winmail.dat format. The code cannot get to these because no attachmentId value is being assigned due to an empty 'ifid' value. Decoding the winmail.dat attachments can be done, but only if they are detected and written to file.
Any ideas how create a workaround in the ImapMailbox code for this?
Here is what I wrote that fixes this problem.
At the beginning of initMailPart() method, add the following:
static $altAttachmentId = 0;
At the end of the IF block for if($this->attachmentsDir) { add the following where the closing } bracket is:
} elseif (!empty($params['fileName']) || !empty($params['filename']) || !empty($params['name'])) { // Process attachments that are not inline.
// Check if need to decode TNEF (Winmail.dat) file.
if ($partStructure->ifsubtype && $partStructure->subtype == 'MS-TNEF') {
require_once 'path_to_your/tnef_decoder.php';
$Tnef = new tnef_decoder;
$un_tnef = $Tnef->decompress($data);
$attached_files = array();
foreach ($un_tnef as $f) {
if (!empty($f['name']) && !empty($f['stream'])) {
$attachment = new IncomingMailAttachment();
$attachment->id = $altAttachmentId;
$attachment->name = $f['name'];
$attachment->filePath = $this->attachmentsDir . DIRECTORY_SEPARATOR . preg_replace('~[\\\\/]~', '', $f['name']);
$mail->addAttachment($attachment);
if (file_exists($attachment->filePath) && md5($f['stream']) != md5_file($attachment->filePath)) {
$attachment->filePath = $this->attachmentsDir . DIRECTORY_SEPARATOR . preg_replace('~[\\\\/]~', '', $mail->id . '_' . $altAttachmentId . '_' . $f['name']);
}
file_put_contents($attachment->filePath, $f['stream']);
$altAttachmentId++;
}
}
} else {
if (!empty($params['filename'])) {
$fileName = $params['filename']; // Account for random camel-case mistake on element.
} elseif (!empty($params['fileName'])) {
$fileName = $params['fileName'];
} else {
$fileName = $params['name'];
}
$attachment = new IncomingMailAttachment();
$attachment->id = $altAttachmentId;
$attachment->name = $fileName;
$attachment->filePath = $this->attachmentsDir . DIRECTORY_SEPARATOR . preg_replace('~[\\\\/]~', '', $mail->id . '_' . $altAttachmentId . '_' . $fileName);
$mail->addAttachment($attachment);
file_put_contents($attachment->filePath, $data);
$altAttachmentId++;
}
}
Note that you must include the tnef_decoder.php file found in the Roundcube Webmail package for the TNEF decoding to work. I got inspiration for the TNEF solution here.
This modification will process all TNEF encoded files in a Winmail.dat file and any other attachment that is not attached inline. Watch your memory usage on large files.
It also won't overwrite existing files that are the same name if they are not exactly the same.
I wonder whether someone may be able to help me please.
I'm using Aurigma's Image uploader software to allow users to upload images for locations they visit. The information is saved via the script shown below:
<?php
//This variable specifies relative path to the folder, where the gallery with uploaded files is located.
//Do not forget about the slash in the end of the folder name.
$galleryPath = 'UploadedFiles/';
require_once 'Includes/gallery_helper.php';
require_once 'ImageUploaderPHP/UploadHandler.class.php';
/**
* FileUploaded callback function
* #param $uploadedFile UploadedFile
*/
function onFileUploaded($uploadedFile) {
$packageFields = $uploadedFile->getPackage()->getPackageFields();
$username=$packageFields["username"];
$locationid=$packageFields["locationid"];
global $galleryPath;
$absGalleryPath = realpath($galleryPath) . DIRECTORY_SEPARATOR;
$absThumbnailsPath = $absGalleryPath . 'Thumbnails' . DIRECTORY_SEPARATOR;
if ($uploadedFile->getPackage()->getPackageIndex() == 0 && $uploadedFile->getIndex() == 0) {
initGallery($absGalleryPath, $absThumbnailsPath, FALSE);
}
$locationfolder = $_POST['locationid'];
$locationfolder = preg_replace('/[^a-z0-9_\-\.()\[\]{}]/i', '_', $locationfolder);
if (!is_dir($absGalleryPath . $locationfolder)) {
mkdir($absGalleryPath . $locationfolder, 0777);
}
$dirName = $_POST['folder'];
$dirName = preg_replace('/[^a-z0-9_\-\.()\[\]{}]/i', '_', $dirName);
if (!is_dir($absGalleryPath . $dirName)) {
mkdir($absGalleryPath . $dirName, 0777);
}
$path = rtrim($dirName, '/\\') . '/';
$originalFileName = $uploadedFile->getSourceName();
$files = $uploadedFile->getConvertedFiles();
// save converter 1
$sourceFileName = getSafeFileName($absGalleryPath, $originalFileName);
$sourceFile = $files[0];
/* #var $sourceFile ConvertedFile */
if ($sourceFile) {
$sourceFile->moveTo($absGalleryPath . $sourceFileName);
}
// save converter 2
$thumbnailFileName = getSafeFileName($absThumbnailsPath, $originalFileName);
$thumbnailFile = $files[1];
/* #var $thumbnailFile ConvertedFile */
if ($thumbnailFile) {
$thumbnailFile->moveTo($absThumbnailsPath . $thumbnailFileName);
}
//Load XML file which will keep information about files (image dimensions, description, etc).
//XML is used solely for brevity. In real-life application most likely you will use database instead.
$descriptions = new DOMDocument('1.0', 'utf-8');
$descriptions->load($absGalleryPath . 'files.xml');
//Save file info.
$xmlFile = $descriptions->createElement('file');
$xmlFile->setAttribute('name', $_POST['folder'] . '/' . $originalFileName);
$xmlFile->setAttribute('source', $sourceFileName);
$xmlFile->setAttribute('size', $uploadedFile->getSourceSize());
$xmlFile->setAttribute('originalname', $originalFileName);
$xmlFile->setAttribute('thumbnail', $thumbnailFileName);
$xmlFile->setAttribute('description', $uploadedFile->getDescription());
//Add additional fields
$xmlFile->setAttribute('username', $username);
$xmlFile->setAttribute('locationid', $locationid);
$xmlFile->setAttribute('folder', $dirName);
$descriptions->documentElement->appendChild($xmlFile);
$descriptions->save($absGalleryPath . 'files.xml');
}
$uh = new UploadHandler();
$uh->setFileUploadedCallback('onFileUploaded');
$uh->processRequest();
?>
In additon to the original script I've added code that creates a folder, with it's name based on the current 'locationid'. This is shown below.
$locationfolder = $_POST['locationid'];
$locationfolder = preg_replace('/[^a-z0-9_\-\.()\[\]{}]/i', '_', $locationfolder);
if (!is_dir($absGalleryPath . $locationfolder)) {
mkdir($absGalleryPath . $locationfolder, 0777);
}
What I like to incorporate, is a check that looks to see whether there is a folder already setup with the current 'locationid' value, if not create the folder. I'm ceratianly no expert in PHP, but I know that to check to see whether a file exists, the if(file exists....) can be used, but I just wondered whether someone could tell me please how I can implement this check for the folder name?
Many thanks
Chris
I think is_dir() is what you are looking for.
UPDATE:
The code you have:
if (!is_dir($absGalleryPath . $locationfolder)) {
mkdir($absGalleryPath . $locationfolder, 0777);
}
Does exactly what you want. It checks for the folder and if it does not exist then it creates one for you (with CHMOD 777). Don't see what your question is then...
I wonder whether someone could help me please.
I'm using Image Uploader from Aurigma, and to save the uploaded images, I've put this script together.
<?php
//This variable specifies relative path to the folder, where the gallery with uploaded files is located.
//Do not forget about the slash in the end of the folder name.
$galleryPath = 'UploadedFiles/';
require_once 'Includes/gallery_helper.php';
require_once 'ImageUploaderPHP/UploadHandler.class.php';
/**
* FileUploaded callback function
* #param $uploadedFile UploadedFile
*/
function onFileUploaded($uploadedFile) {
$packageFields = $uploadedFile->getPackage()->getPackageFields();
$userid = $packageFields["userid"];
$locationid= $packageFields["locationid"];
global $galleryPath;
$absGalleryPath = realpath($galleryPath) . DIRECTORY_SEPARATOR;
$absThumbnailsPath = $absGalleryPath . 'Thumbnails' . DIRECTORY_SEPARATOR;
if ($uploadedFile->getPackage()->getPackageIndex() == 0 && $uploadedFile->getIndex() == 0) {
initGallery($absGalleryPath, $absThumbnailsPath, FALSE);
}
$dirName = $_POST['folder'];
$dirName = preg_replace('/[^a-z0-9_\-\.()\[\]{}]/i', '_', $dirName);
if (!is_dir($absGalleryPath . $dirName)) {
mkdir($absGalleryPath . $dirName, 0777);
}
$path = rtrim($dirName, '/\\') . '/';
$originalFileName = $uploadedFile->getSourceName();
$files = $uploadedFile->getConvertedFiles();
// save converter 1
$sourceFileName = getSafeFileName($absGalleryPath, $originalFileName);
$sourceFile = $files[0];
/* #var $sourceFile ConvertedFile */
if ($sourceFile) {
$sourceFile->moveTo($absGalleryPath . $sourceFileName);
}
// save converter 2
$thumbnailFileName = getSafeFileName($absThumbnailsPath, $originalFileName);
$thumbnailFile = $files[1];
/* #var $thumbnailFile ConvertedFile */
if ($thumbnailFile) {
$thumbnailFile->moveTo($absThumbnailsPath . $thumbnailFileName);
}
//Load XML file which will keep information about files (image dimensions, description, etc).
//XML is used solely for brevity. In real-life application most likely you will use database instead.
$descriptions = new DOMDocument('1.0', 'utf-8');
$descriptions->load($absGalleryPath . 'files.xml');
//Save file info.
$xmlFile = $descriptions->createElement('file');
$xmlFile->setAttribute('name', $_POST['folder'] . '/' . $originalFileName);
$xmlFile->setAttribute('source', $sourceFileName);
$xmlFile->setAttribute('size', $uploadedFile->getSourceSize());
$xmlFile->setAttribute('originalname', $originalFileName);
$xmlFile->setAttribute('thumbnail', $thumbnailFileName);
$xmlFile->setAttribute('description', $uploadedFile->getDescription());
//Add additional fields
$xmlFile->setAttribute('userid', $userid);
$xmlFile->setAttribute('locationid', $locationid);
$xmlFile->setAttribute('folder', $dirName);
$descriptions->documentElement->appendChild($xmlFile);
$descriptions->save($absGalleryPath . 'files.xml');
}
$uh = new UploadHandler();
$uh->setFileUploadedCallback('onFileUploaded');
$uh->processRequest();
?>
What I'd like to do is replace the files element of the filename and replace it with the username, so each saved folder and associated files can be indentified to each user.
I've added a username text field to the form which this script saves from
I think I'm right in saying that this is line that needs to change $descriptions->save($absGalleryPath . 'files.xml');.
So amongst many attempts I've tried changing this to $descriptions->save($absGalleryPath . '$username.xml, $descriptions->save($absGalleryPath . $username '.xml, but none of these have worked, so I'm not quite sure what I need to change.
I just wondered whether someone could perhaps have a look at this please and let me know where I'm going wrong.
Many thanks
'$username.xml' will be interpreted as $username.xml, you need to use "$username.xml". Single quotes "disable" the variable use inside strings.
What you are tryiing can be a bad idea, as you are making so a username can't contain 'special characters' like "/". Perhaps is not a problem if you aready have a rule that stop "/" being part of a username.