Jump to content

Sort order by last date modified


jimboppin

Recommended Posts

hi there, im making a media page on my static site that has no database, i have managed to put this code together so that i can add text files into a directory and show all files content on a page..

 

my problem is i cant work out how to get it all in order, it seems that by default the order is alphabetical and i need it to be by the last modified date...

any help would be great as im a bit stuck

 

my function:

function get_media($media_dir) {
    $directory = PAGES_BASEDIR.$media_dir;
    $dir = opendir($directory);
    while (($file = readdir($dir)) !== false) {
        $filename = $directory . $file;
        $type = filetype($filename);
        if ($type == 'file') {
            $contents = file_get_contents($filename);
            $items = explode('¬', $contents);
            $media_title = basename($filename);
            $media_title = basename($filename, ".txt");
            if (file_exists($filename)) {
                $date_time = date ("F d Y H:i:s", filemtime($filename));
            }
            foreach ($items as $media) {
                THEMENEWSTOP($media_title);
                echo ($media);
                THEMENEWSBOTTOM($date_time);
            }
        }
    }
    closedir($dir);
}

Thanks

Edited by jimboppin
Link to comment
Share on other sites

readdir() returns the entries in the order that they are stored in the directory.

 

to do what you want will require sorting by the raw filemtime() value. to do this, you would store the filenames and filemtime in an array, with the filename as the array index/key and the filemtime as the array value. you would then use either asort() or arsort() to sort the data by the filemtime values, then loop over the sorted data to display the information.

 

i also recommend just using glob(), rather than all that opendir/readdir/filetype logic, to get the starting list of the files into an array.

Link to comment
Share on other sites

You may find it better to store the date and contents in the array (with filename as the key). In which case a simple asort() will not work, you will need a custom sort function.

 

For example

$files['file1.txt']  = [    'date' => '2017-01-03',
                            'content' => 'aaa'
                            ];
$files['file2.txt']  = [    'date' => '2017-01-01',
                            'content' => 'bbb'
                            ];
$files['file3.txt']  = [    'date' => '2017-01-02',
                            'content' => 'ccc'
                            ];
$files['file4.txt']  = [    'date' => '2017-01-04',
                            'content' => 'ddd'
                            ];

uasort($files, function ($a, $b) {
                    return strcmp ($a['date'], $b['date']);
                });

foreach ($files as $filename => $fdata) {
    // process the output
}

Link to comment
Share on other sites

hi, here is what i have managed to come up with and this is working. however is it valid and clean?

function get_media($media_dir) {
    $directory = PAGES_BASEDIR.$media_dir;
    $files = array();
    $files = glob($directory."*.txt");
    usort($files, function($x, $y) {
        return filemtime($x) < filemtime($y);
    });
    foreach ($files as $media) {
        $media_title = basename($media);
        $media_title = basename($media, ".txt");
        if (file_exists($media)) {
            $date_time = date ("F d Y H:i:s", filemtime($media));
        }
        THEMENEWSTOP($media_title);
        require_once $media;
        THEMENEWSBOTTOM($date_time);
    }
}

thanks

Link to comment
Share on other sites

Including a text file with require_once is suicidal, because this turns the text into code which gets executed. Anybody with expected or unexpected access to those files can execute arbitrary commands on your server.

 

Even echoing the content will make the application wide open to cross-site scripting attacks. If you want plain text, you need to escape the file content:

$content = file_get_contents(...);
echo htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');

You should definitely reconsider your application infrastructure. I know that flat-file application are all the rage right now, but implementing this correctly -- i. e. without blowing up your server -- is a lot more work than simply using a proper database.

Link to comment
Share on other sites

hi thankyou for the advice, its just a small project im working on, theres no edit or delete funtionality going into it...

 

i have implemented what you suggested here

function get_media($media_dir) {
    $directory = PAGES_BASEDIR.$media_dir;
    $files = array();
    $files = glob($directory."*.txt");
    usort($files, function($x, $y) {
        return filemtime($x) < filemtime($y);
    });
    foreach ($files as $media) {
        $content = file_get_contents($media);
        $media_title = basename($media);
        $media_title = basename($media, ".txt");
        if (file_exists($media)) {
            $date_time = date ("F d Y H:i:s", filemtime($media));
        }
        THEMEMEDIATOP($media_title);
        echo htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
        THEMEMEDIABOTTOM($date_time);
    }
}

but its showing up the html in the page now is there a way to auto apply the html so i can just create a text document from within windows and just upload it no worries...

 

i changed this

return filemtime($x) - filemtime($y); 

but it just changed it back to ABC and not last date modified...

 

thanks

Link to comment
Share on other sites

but its showing up the html in the page now is there a way to auto apply the html so i can just create a text document from within windows and just upload it no worries...

 

So your “text files” are actually HTML documents? Then you should stop pretending like they're text files.

 

Give them a proper “.html” extension, double-check the file permissions (they must be read-only), then echo the raw content.

Edited by Jacques1
Link to comment
Share on other sites

not realy, i didont look at it like that... i wanted to use a txt file just because there just articles that consist of <br /> etc nothing big... could i not whitelist some of these ? commonly used html tags?

 

and the server im on is windows so im not sure how the file permissions work... i only see black blocks and xxx in filezilla rather then 755 etc..

Link to comment
Share on other sites

not realy, i didont look at it like that... i wanted to use a txt file just because there just articles that consist of <br /> etc nothing big

 

Sounds like you want Markdown rather than HTML.

 

 

 

and the server im on is windows so im not sure how the file permissions work... i only see black blocks and xxx in filezilla rather then 755 etc..

 

 

Then ask the person who maintains the server. If that's you, look up how the permissions work, because that's kinda important.

Link to comment
Share on other sites

hi, i have decided to change my files to html and changed the code, is this safe?

function get_media($media_dir) {
    $directory = PAGES_BASEDIR.$media_dir;
    $files = array();
    $files = glob($directory.'*.html');
    usort($files, function($x, $y) {
        return filemtime($x) < filemtime($y);
    });
    foreach ($files as $media) {
        $content = file_get_contents($media);
        $clean_content = htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
        $clean_content = strip_tags($content, '<br><p><a><img><h1><h2><h3><h4>');
        $media_title = basename($media);
        $media_title = basename($media, '.html');
        if (file_exists($media)) {
            $date_time = date ('F d Y H:i:s', filemtime($media));
        }
        THEMEMEDIATOP($media_title);
        echo $clean_content;
        THEMEMEDIABOTTOM($date_time);
    }
}

thanks

Link to comment
Share on other sites

is this safe?

 

Given that strip_tags() is the worst possible choice and that you're struggling with the file permissions: no.

 

So what happened with Markdown?

 

If you want to filter your HTML in addition to or instead of using Markdown, there's HTML Purifier. The strip_tags() function is not an option for anything but joke applications, as the manual clearly says.

Link to comment
Share on other sites

markdown is here :)  i hope iv got it right

function get_media($media_cat) {
    global $Parsedown;
    if (isset($_GET['id'])) {
        $media_id = htmlentities($_GET['id'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
    }
    if (isset($media_id)) {
        if ($media_id == $media_cat) {
            $media_dir = 'Media/'.$media_cat.'/';
            $directory = PAGES_BASEDIR.$media_dir;
            $files = array();
            $files = glob($directory.'*.txt');
            usort($files, function($x, $y) {
                return filemtime($x) < filemtime($y);
            });
            foreach ($files as $media) {
                $content = file_get_contents($media);
                $media_title = basename($media);
                $media_title = basename($media, '.txt');
                if (file_exists($media)) {
                    $date_time = date ('F d Y H:i:s', filemtime($media));
                }
                THEMEMEDIATOP($media_title);
                echo $Parsedown->text($content);
                THEMEMEDIABOTTOM($date_time);
            }
        }
    }
}

also can you point me in the right direction for windows security regarding the files...

Link to comment
Share on other sites

You need

$Parsedown->setMarkupEscaped(true);

to disable embedded HTML markup.

 

 

 

also can you point me in the right direction for windows security regarding the files...

 

I already did that:

 

Then ask the person who maintains the server. If that's you, look up how the permissions work, because that's kinda important.

 

I neither use Windows nor have access to your server, so I cannot fix the permissions for you.

Link to comment
Share on other sites

i have this in my mainfile

require_once INCLUDES_BASEDIR.'_parsedown.php';
$Parsedown = new Parsedown();
$Parsedown->setMarkupEscaped(true);

and this is another update on my function to collect news or announcements etc

function get_media($media_cat, $display_recent) {
    global $Parsedown;
    if (isset($_GET['id'])) {
        $media_id = htmlentities($_GET['id'], ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
    }
    if (isset($media_id)) {
        if ($media_id == $media_cat) {
            $display_recent = null;
        }
    }    
    $media_dir = 'Media/'.$media_cat.'/';
    $directory = PAGES_BASEDIR.$media_dir;
    $files = array();
    $files = glob($directory.'*.txt');
    usort($files, function($x, $y) {
        return filemtime($x) < filemtime($y);
    });
    $recent_content = array_slice($files, 0, $display_recent);
    foreach ($recent_content as $media) {
        $content = file_get_contents($media);
        $media_title = basename($media);
        $media_title = basename($media, '.txt');
        if (file_exists($media)) {
            $date_time = date ('F d Y H:i:s', filemtime($media));
        }
        THEMEMEDIATOP($media_title);
        echo $Parsedown->text($content);
        THEMEMEDIABOTTOM($date_time);
    }
}

then i just add this into a page i want to show my content

<?php get_media('News', 2);?>

other then the permissions is this all ok now? i will look into the permissions

thanks

Link to comment
Share on other sites

 

You may find it better to store the date and contents in the array (with filename as the key). In which case a simple asort() will not work, you will need a custom sort function.

 

For example

$files['file1.txt']  = [    'date' => '2017-01-03',
                            'content' => 'aaa'
                            ];
$files['file2.txt']  = [    'date' => '2017-01-01',
                            'content' => 'bbb'
                            ];
$files['file3.txt']  = [    'date' => '2017-01-02',
                            'content' => 'ccc'
                            ];
$files['file4.txt']  = [    'date' => '2017-01-04',
                            'content' => 'ddd'
                            ];

uasort($files, function ($a, $b) {
                    return strcmp ($a['date'], $b['date']);
                });

foreach ($files as $filename => $fdata) {
    // process the output
}

hi im trying to implement this to my code as i found out that if i backup my site then upload it all my news is reset and gets mixed up..

how do i format my txt file so this can read it and sort it out?

 

i imagin somthing like this...

date>27/02/2017 6:48pm
anything after the above line is content


some contentsome contentsomesome contentsome
some contentsome contentsome
some contentsome content

some contentsome content
some contentsome content


some contentsome contentsome content

 heres the function...

function get_media($media_cat, $display_recent) {
	global $Parsedown, $media_id;
	if (isset($media_id)) {
		if ($media_id == $media_cat) {
			$display_recent = null;
		}
	}
	$directory = MEDIA_BASEDIR.$media_cat.'/';
	$files = array();
	$files = glob($directory.'*.txt');
	
	uasort($files, function ($a, $b) {
			return strcmp ($a['date'], $b['date']);
		});


	$recent_content = array_slice($files, 0, $display_recent);
	foreach ($recent_content as $media => $fdata) {
		$content = file_get_contents($fdata);
		$media_title = basename($fdata);
		$media_title = basename($fdata, '.txt');
		if (file_exists($fdata)) {
			$date_time = date ('F d Y H:i:s', filectime($fdata));
		}
		THEMEMEDIATOP($media_title, $media_cat);
		echo $Parsedown->text($content);
		THEMEMEDIABOTTOM($date_time);
	}
}

thanks again

Link to comment
Share on other sites

sorry i see how that works now, i was hopeing to be able to just upload a txt file no worries, and to do that the only thing i can think of is to put the date and time in the first line of the text file and then read the first line to sort by date

 

first line being line[0]

 

i know how to read the first line im just stuck how to use it in the uasort function

 

thanks

Link to comment
Share on other sites

Just use a database already.

 

You've now spent three days on this trivial task, you constantly get stuck, and it will be even worse when you have to do complex tasks. So why continue this route? The entire thread could be boiled down to a single SQL query:

$media = $databaseConnection->query('
    SELECT
        title,
        content,
        category,
        creation_time
    FROM
        media
    ORDER BY
        creation_time DESC
    -- add LIMIT if needed
');
foreach ($media as $medium)
{
    // parse and display $medium
}

That's it. No glob(), no uasort(), no array_slice(), no filectime(), no file_get_contents(). Just standard SQL.

 

Even publishing will be simpler, because you don't have to upload anything. Make yourself a simple password-protected admin script and use that to manage your texts.

 

Maybe the server already has a MySQL installation. If it doesn't, you can always use SQLite which stores the entire database in a single file.

Link to comment
Share on other sites

Hi, thankyou for reply,

 

i do have sqli, i was on that track but i couldont work out how to get it secure when posting username and password etc

 

i dont want my username or password sniffed out when its going thru to the script, i honestly would need help to get me going on somthing like that, i would need a secure basic sql login and then how to post to the database securley when adding data to it... this is what made me try and make it more simple because i live in notepad++ and filezilla it just made sence to me.

 

im willing to learn if some one is willing to help me get going with it i can self teach the rest but security makes me on edge

Link to comment
Share on other sites

thanks i know its alot better to have a database but its alot more work when i can just make a little function to collect a text file and its contents, also the speed difference sql and txt files is just stupidly fast so for a site that dose not require users or admin i would much rather stick to this function.

 

sorry to take 2 steps back, if you cant or dont want to help me thats fine i can seek help some where else, no affence.

 

i just need to read the first line that will have a date format on it.. read it and arange by that date from the top line then output while ignoring the first line for content.

 

thanks again.

Edited by jimboppin
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.