Determining when smarty created a cache file - php

I've got a cms, each page stores the time that it was last updated in a database. I've got caching set up in smarty (3.1), but I want to be able to clear the cache and force it to create a new cache file if the page was updated since the last saved cache file, but to do that I need to know when the cached file was created.
Is there a way of getting the timestamp of the cached file?
Thanks

I have recently answered a similar question: Smarty cache site properties in database
<?php
// fill these if you do cache grouping and or have different compiles of the same template
$template = 'foobar.tpl';
$cache_id = null;
$compile_id = null;
$smarty = new Smarty();
$tpl = $smarty->createTemplate($template, $cache_id, $compile_id);
if ($tpl->isCached() && $tpl->cached->timestamp < $yourTimestampFromDB) {
$smarty->clearCache($template, $cache_id, $compile_id);
}

I'm not sure Smarty has anything internal for this. But look at filemtime() and filectime for determining when a file was last modified and changed respectively.
From php.net:
$filename = 'somefile.txt';
if (file_exists($filename)) {
echo "$filename was last changed: " . date("F d Y H:i:s.", filectime($filename));
}
Difference between modified-time and change-time:
Note: In most Unix filesystems, a file is considered changed when its inode data is changed; that is, when the permissions, owner, group, or other metadata from the inode is updated. See also filemtime() (which is what you want to use when you want to create "Last Modified" footers on web pages) and fileatime().

Related

Download file from FTP while keeping the original "last change" date

I've build an FTP class in PHP with a function to download files from the FTP server.
This is the function so far
public function downloadData($serverFile, $localPath)
{
$fileName = basename($serverFile);
$file = $localPath.$fileName;
$download = false;
if(!file_exists($file))
{
// try to download $server_file and save to $local_file
if(ftp_get($this->connection_id, $file, $serverFile, FTP_BINARY)) {
$download = true;
}
}
return $download;
}
Basically it works fine, but when saving the data the "last change date" of the file is set to the current date/time. I somehow want to prevent this, because the original date is important for my needs.
Is there a way to keep the original modified date of the file?
It sounds like you believe there's something overwriting the timestamp. There's not. The timestamp is simply not transferred at all during an FTP download. So the local file has last modification time matching the transfer time (= the last time the local file was modified).
But you can of course explicitly set the timestamp after the download finishes.
Use ftp_mdtm to retrieve the timestamp of source file on FTP server.
Use touch to set the timestamp of target local file.
touch($file, ftp_mdtm($this->connection_id, $serverFile));
You cannot stop the system from updating the modified date when modifying a file. However, it depends drastically on why you need the creation date?
Unfortunately if you are running on Linux/Unix you cannot access the creation date information as only the last modified date is stored. However for Windows you can use filectime and it will return the creation time

Check for new files in a folder

I have a php script i run every 5 minutes with Cron from a folder. In the folder there is several images and i add more as time goes.
I was wondering how i can make the php script in the beginning check if NEW files exist after the last time the script was run? If new files exist the script should just go on and if no new files exist then it should not go on. I tried searching around but i cant find anything regarding php.
Anyone that know a quick solution to this problem maybet ?
If the new files are also created with a new timestamp, you can use filemtime() to fetch only files that were created/modified in a specified window of time.
Example:
$files = glob("folder/*.jpg");
$files = array_filter($files, function ($file) { return filemtime($file) >= time() - 5*60; /* modified in the last 5 minutes */ });
if ($files)
{
// there are new files! $files is an array with their names
}
To make sure you won't miss any file, you might want to store the time from last run somewhere, so in case cron delays a second or two and new files were created precisely within that window, you won't lose track of them.
Update for comments:
Now, to store the time from last check, thats up to you to decide how you will do that, you can use database, file, some sort of environment variable etc., but here is an example of how you can do something really simple storing time() in a file:
$last = (int)file_get_contents('folder/timestamp.txt');
file_put_contents('folder/timestamp.txt', time());
$files = glob("folder/*.jpg");
$files = array_filter($files, function ($file) { return filemtime($file) > $last; });
if ($files)
{
// there are new files! $files is an array with their names
}
Just make sure your PHP script can modify folder/timestamp.txt and with this script it will always process new files modified since the last run, no matter how long ago it happened.
Method :
store current time whenever the cron executed in a file or database.
every time when cron starts get the last executed time of the cron from your file or database
count the file which creates after last execution time.
if count greater than 0. process the cron. other wise stop.
You could keep track of the time the script was last run and use filemtime to check if the file was updated or created after your last execution.
http://php.net/manual/en/function.filemtime.php
int filemtime ( string $filename )
Use filemtime() as follows,You will get the added time as date format.
$file_time = date ("F d Y H:i:s.", filemtime($filename);

PHP Script for Monitoring Folder Creation

I want to write one PHP script that will tell me how many folders getting created today( not modified one !! ).
Ex. Suppose if gave the path ( like c:\Data ) so my script must be continuously checking that
give path for if it is new entry of any folder. I have used http://php.net/manual/en/function.date-diff.php. But getting result for modified folders as well.
Quote from #Alin Purcaru:
Use filectime. For Windows it will return the creation time, and for Unix the change time which is the best you can get because on Unix there is no creation time (in most filesystems).
Using a reference file to compare the files age allows you to detect new files whidout using a database.
// Path to the reference file.
// All files newer than this will be treated as new
$referenceFile="c:\Data\ref";
// Location to search for new folders
$dirsLocation="c:\Data\*";
// Get modification date of reference file
if (file_exists($referenceFile))
$referenceTime = fileatime($referenceFile);
else
$referenceTime = 0;
// Compare each directory with the reference file
foreach(glob($dirsLocation, GLOB_ONLYDIR) as $dir) {
if (filectime($dir) > $referenceTime)
echo $dir . " is new!";
}
// Update modification date of the reference file
touch($referenceFile);
Another solution could be to use a database. Any folders that are not in the database are new. This ensures to not catch modified folders.
You might want to try getting your script launched with cron like every one minute and check the difference between directory lists (from before and current I mean), not the dates. It's not a perfect solution, but it will work.
Check directories arays with:
$dirs = array_filter(glob('*'), 'is_dir');
Compare them later with array_diff

Select a file that was created the last minute

Do you know if there is a function in php where it can find all the files in a given directory, that were created the last 1 minute (or in any case at a specified time?).
For example, to select all the txt files that were created the last 10 minutes in a directory..
I hope it's clear what I mean!
Thanx
D.
There is no creation time as such, only modified-time, which will work reliably across operating systems.
The filectime() and filemtime() filesystem functions in PHP will allow
you to check and see when a file has last been changed.
It will return
a timestamp holding the value of the time the file was last altered
You could iterate through the files in the folder, while checking filemtime().
Something like,
foreach (glob("*.txt") as $filename) {
echo filemtime($filename); //echoes timestamp
}
Get all files in directory, loop them through and apply filetime() function to see when they were created/modified. Copy them to another array and do with them what you please.
You can try
$it = new GlobIterator(__DIR__ . "/*.txt");
$last10mis = 600;
$list = array();
foreach ( $it as $file )
(time() - $file->getMTime()) <= $last10mis and $list[] = strval($file);
var_dump($list); // all txt files modified in the last 10mins
There is a function in PHP called filemtime that will return the modified time in a UNIX timestamp.
http://php.net/manual/en/function.filemtime.php
from there, and in the example ont that page, it should be fairly straightforward to apply to your needs.

Unique and temporary file names in PHP?

I need to convert some files to PDF and then attach them to an email. I'm using Pear Mail for the email side of it and that's fine (mostly--still working out some issues) but as part of this I need to create temporary files. Now I could use the tempnam() function but it sounds like it creates a file on the filesystem, which isn't what I want.
I just want a name in the temporary file system (using sys_get_temp_dir()) that won't clash with someone else running the same script of the same user invoking the script more than once.
Suggestions?
I've used uniqid() in the past to generate a unique filename, but not actually create the file.
$filename = uniqid(rand(), true) . '.pdf';
The first parameter can be anything you want, but I used rand() here to make it even a bit more random. Using a set prefix, you could further avoid collisions with other temp files in the system.
$filename = uniqid('MyApp', true) . '.pdf';
From there, you just create the file. If all else fails, put it in a while loop and keep generating it until you get one that works.
while (true) {
$filename = uniqid('MyApp', true) . '.pdf';
if (!file_exists(sys_get_temp_dir() . $filename)) break;
}
Seriously, use tempnam(). Yes, this creates the file, but this is a very intentional security measure designed to prevent another process on your system from "stealing" your filename and causing your process to overwrite files you don't want.
I.e., consider this sequence:
You generate a random name.
You check the file system to make sure it doesn't exist. If it does, repeat the previous step.
Another, evil, process creates a file with the same name as a hard link to a file Mr Evil wants you to accidentally overwrite.
You open the file, thinking you're creating the file rather than opening an existing one in write mode and you start writing to it.
You just overwrote something important.
PHP's tempnam() actually calls the system's mkstemp under the hood (that's for Linux... substitute the "best practice" function for other OSs), which goes through a process like this:
Pick a filename
Create the file with restrictive permissions, inside a directory that prevents others from removing files it doesn't own (that's what the sticky-bit does on /var/tmp and /tmp)
Confirms that the file created still has the restrictive permissions.
If any of the above fails, try again with a different name.
Returns the filename created.
Now, you can do all of those things yourself, but why, when "the proper function" does everything that's required to create secure temporary files, and that almost always involves creating an empty file for you.
Exceptions:
You're creating a temporary file in a directory that only your process can create/delete files in.
Create a randomly generated temporary directory, which only your process can create/delete files in.
Another alternative based on #Lusid answer with a failover of max execution time:
// Max exectution time of 10 seconds.
$maxExecTime = time() + 10;
$isUnique = false;
while (time() !== $maxExecTime) {
// Unique file name
$uniqueFileName = uniqid(mt_rand(), true) . '.pdf';
if (!file_exists(sys_get_temp_dir() . $uniqueFileName)){
$isUnique = true;
break;
}
}
if($isUnique){
// Save your file with your unique name
}else{
// Time limit was exceeded without finding a unique name
}
Note:
I prefer to use mt_rand instead of rand because the first function use Mersenne Twister algorithm and it's faster than the second (LCG).
More info:
http://php.net/manual/en/function.uniqid.php
http://php.net/manual/en/function.mt-rand.php
http://php.net/manual/en/function.time.php
Consider using an uuid for the filename. Consider the uniqid function.
http://php.net/uniqid
You could use part of the date and time in order to create a unique file name, that way it isn't duplicated when invoked more than once.
I recomend you to use the PHP function
http://www.php.net/tempnam
$file=tempnam('tmpdownload', 'Ergebnis_'.date(Y.m.d).'_').'.pdf';
echo $file;
/var/www/html/tmpdownload/Ergebnis_20071004_Xbn6PY.pdf
Or
http://www.php.net/tmpfile
<?php
$temp = tmpfile();
fwrite($temp, "writing to tempfile");
fseek($temp, 0);
echo fread($temp, 1024);
fclose($temp); // this removes the file
?>
Better use Unix timestamp with the user id.
$filename='file_'.time().'_'.$id.'.jepg';
My idea is to use a recursive function to see if the filename exists, and if it does, iterate to the next integer:
function check_revision($filename, $rev){
$new_filename = $filename."-".$rev.".csv";
if(file_exists($new_filename)){
$new_filename = check_revision($filename, $rev++);
}
return $new_filename;
}
$revision = 1;
$filename = "whatever";
$filename = check_revision($filename, $revision);
function gen_filename($dir) {
if (!#is_dir($dir)) {
#mkdir($dir, 0777, true);
}
$filename = uniqid('MyApp.', true).".pdf";
if (#is_file($dir."/".$filename)) {
return $this->gen_filename($dir);
}
return $filename;
}
Update 2020
hash_file('md5', $file_pathname)
This way you will prevent duplications.

Categories