Jump to content

Update a file (document or image) without losing its reference elsewhere


Guy Verville
 Share

Recommended Posts

I am so far impressed by Processwire and still learning it (well, it is so easy!). I will certainly propose this CMS to my future clients. One thing is puzzling me, though, is file references. I have numerous clients who make references throughout their pages.

Say, for example, that a PDF or an image is found in three pages. In Concrete5, since there is a file manager, it is easy to replace a file without losing the reference to it, because there is a replace command. Then, you are sure that at all the references of that file has not changed throughout the site.

I don't see this in Processwire. I understand that I can reference a file coming from another page. But to just replace it (for example, the document has to be updated because of a typo), the only solution I see is to go to the asset directory and change the document there. This is not very user friendly for a regular user.

Perhaps an example would be more clear. I am making a gardening site. Each page can contain 20 photos of flowers, which are tagged and documented. Then, somewhere else, a reference may be made to one photo specific photo.

Now, that photo, which is included in a list of twenty other ones, has to be updated. I could delete the file, upload another one and rewrite the information. But the reference is now lost where the other image is cited. Right?

  • Like 1
Link to comment
Share on other sites

Welcome to the forums Guy!

There isn't assets manager in pw (although Soma is building one: http://processwire.com/talk/topic/3219-images-manager-alpha/). PW way is to attach images to pages and reference to those pages instead.

So one way to solve your need might be to have template called "image", which would have single image field and other metadata related to image (like tags and description). Then you would reference to those image-pages instead of image directly. This would definitely keep things DRY, but it might not be the best solution in usability wise. I haven't yet used Soma's images manager, but it might offer even better UI here. If I have understood it correctly, it works just about the same under the hood.

Link to comment
Share on other sites

Hi, thank your for your answer. Companies sites are often document centric, so it is important to have a good asset manager. Perhaps PW is just not the best solution for that type of website. I'm puzzled why, if there are add, and delete methods, there is no replace one.  I am no PHP or jQuery guru, and certainly not a PW module shaman, but it seems to be a simple trick to do.

The image or file has a its reference. Click the replace button, a dialog appears to ask for the new file, and voilà. No need to have page for every file (which is a real PITA).

My two cents, for what it is worth ;-)

Link to comment
Share on other sites

if the filename doesn't change you wouldn't lose the reference.

So if you stored all of the PDF files in a files field on a page called 'PDF files', you would be able to easily link to them from TinyMCE: 

of you need to replace the file, just delete it first and upload the replacement file with the same name.

you probably wouldn't want the filename to change anyway since it's possible that some other sites might link to it.

If you stored each PDF in it's own page under a parent page called PDF Folder (for example), and use a file field set to accept only 1 file, you could use the title or name field to control the filename, by using a hook to rename the uploaded file, if you were worried about users messing up the referral links.

Link to comment
Share on other sites

Hello Macrura,

I understand your points, but, for me, this is killing the beautiful way PW is working for inserting files. I am disciplined enough to rename a file exactly like the precedent one, but this would not be necessarily the case with future clients and (sometimes) dumb employees. Also, file names have to changed in certain cases (for organizational purposes, for example).

Why a new method called replace seems out of reach? I wonder. PW is all about elegant simplicity. Clients are not geeks, and they want simplicity too. Anyway, what you suggest are good workarounds, but there are just that, workarounds, and I hope they are temporary ones.

This has to be taken into account when proposing a CMS (PW for the joy of toying with it, Concrete5 for the real liberty it gives to the client?). We'll see. But PW is certainly now, for me, a good choice for future projects.

Link to comment
Share on other sites

i don't really get what replace would do. when you replace a file in concrete 5 does it rename the uploaded file to match the one already there?

that would be the same as using the page idea i proposed above, and in that scenario, you would additionally have the flexibility of attaching custom fields to the page and consequently the file, such as a description, author, tags, related files, preview image, or anything else; 

it also seems very simple to me - it would seem that PW would quite ideal for setting up a document management system...

Link to comment
Share on other sites

Hello and welcome Guy Verville,

I definitly get what you say and I agree to it. If you can work with the images- or file inputfields in a project, you don't want change to a completly different concept.

It is beautyful simple working with the file-inputfields, (also for sometimes dump employees :) )

(@Macrura:) And it would be very useful and straightforward to have a replace link that let you upload a new file for an existing one.

Replace means that an existing file gets deleted and a new one would be stored there with the exact filename as the previous one, regardless of what file the person selects on his/her computer for the upload. So with the upload there should be at least only allowed to select a single file with the same filename-extension.

So, there are also (many) scenarios where it is better to go with the "single-file per page solution", but if it suites fine with the file- and images-inputfields, the replace-link is definitly missing!

  • Like 2
Link to comment
Share on other sites

SImply replacing a file with the same filename isn't usually a good idea because browser caches may not recognize it as a new file. Not to mention, the filename may have significance for the document, containing version numbers or the like. Basically, a replace by filename has a lot of drawbacks. You need a reference separate from the filename. In ProcessWire, that reference can be a page (for single file fields), or tags (for multiple document fields). For document centric sites, I usually have a dedicated space where file links go, rather than trying to manually link them in rich text editor fields. For instance, a sidebar with links to the files.  If I need the links in body copy then I'm going to use a Hanna code there... but prefer to isolate file links to a dedicated and consistent space. If I want to list all the files on the current page with the tag "application" then I'll do this:

<h3>Application Files</h3>
<ul class='files'><?php
foreach($page->files->findTag('application') as $file) {
  echo "<li><a href='$file->url'>$file->description</a></li>";
} 
?></ul>

If I want to pull all files with the tag "2013" (current year) from a page /shared/files/ then I'll do this:

$year = date('Y'); 
$files = $pages->get('/shared/files/')->files->findTag($year); 
if(count($files)) {
  echo "<h3>$year Files</h3><ul class='files'>";
  foreach($files as $file) echo "<li><a href='$file->url'>$file->description</a></li>";
  echo "</ul>";
}

If I have a page that I always want to print a link to the latest application form, rather than using tags, I might keep an individual page dedicated to that file (with a single file field) below my /shared/ page. 

$app = $pages->get('/shared/latest-application/');
if($app->file) {
  echo "<p><a href='$app->file->url'>Download latest application</a></p>";
} 

Any of this code could work just as well in a Hanna code as it could in a template file. The point here is to abstract files away from filenames, to pages or tags (at least on large document centric sites). This scales well, prevents possibility of broken links, and is simple and foolproof for the client. 

  • Like 3
Link to comment
Share on other sites

Hello Ryan,

First of all, my two thumbs up for PW. It is a great piece of work!  I don't agree with the problem of broken links. Having a file system of its own, Concrete5 doesn't create that situation since a file has always one and only reference, whatever name it has (and whatever it is an image or a file). The file has not to be placed in the file system either. The CMS places it there automatically. If a user want to replace such and such, he/she only goes to the file system, or from the place it has put it) and change it. Every reference in the site will be automatically changed, even if he/she has placed it in a text area (the link is not a direct call to that file, but rather to its reference, the user doesn't see this technicality unless he/she open the html view (<a href="/index.php/download_file/view/494/"> <--this suggest a dynamic call to it, if I am correct).

The solution in PW is to place the file on its own page, so the user can easily retrace it, delete the previous link, etc. Then, the reference is kept elsewhere. I am ok with that solution. But I don't see where a replace button can not fit that situation. The file has a reference, no? But you created the beast. Perhaps I just don't get it ^_^

Have a nice day.

Link to comment
Share on other sites

it seems that the concrete5 way is fetching the asset when the link is accessed, you could do that by coding the template for the pages that hold the files to return the file and not the page. then you would need to tell the client to link to the page for the file and not the file itself.. haven't tested this...only issue i can see is that PW might be sending headers also?

<?php
$file = $page->myfile->url;

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}
?>
Link to comment
Share on other sites

it is an interesting topic, and it seems that the way C5 is doing it is to use that 'download_file' function to go and get the file that is being referenced; a 'node' is like a page in PW - so you can mimic this functionality using pages, url segments, get vars or whatever; 

i have one site where we have zip files located outside of the web root (not web accessible) and then a url segment that triggers the fetching of the file from the server and forces the download.

as far as the other element of this discussion, the concept of replacing the file, that's really just an operation, which takes 2 steps in PW and apparently 1 step in C5; it probably wouldn't be that hard to make a module that could load for that file template, which would combine the 2 actions, so if you click a replace link, it would first trash the existing file and then present the new upload dialog...

Link to comment
Share on other sites

it is an interesting topic, and it seems that the way C5 is doing it is to use that 'download_file' function to go and get the file that is being referenced; a 'node' is like a page in PW - so you can mimic this functionality using pages, url segments, get vars or whatever; 

ProcessWire only uses this method if you've enabled the $config->pagefileSecure option in your /site/config.php, and then only for files on access controlled or unpublished pages. 

I'm not a fan of this method of file delivery unless the file needs to be behind a wall for access control. Files are static assets that Apache can deliver without any PHP/MySQL overhead necessary. Delivering files through PHP consumes a lot of unnecessary resources. But if the file needs to be access controlled, then of course it's the way to go. But given that files really shouldn't be delivered by PHP unless necessary for security, these are the issues: 

SImply replacing a file with the same filename isn't usually a good idea because browser caches may not recognize it as a new file. Not to mention, the filename may have significance for the document, containing version numbers or the like.

Basically, I don't think direct file replacement is worth the compromise. Abstracting the file name to a tag (like mentioned in my prev message) is a clean compromise. Single file fields already support replacement (just drag and drop a new version on top of the old), but don't currently retain the filename unless you drop the same filename on top of it. So what I also think may be okay is letting the admin optionally specify a target filename for single-file fields with the file field settings. This would still be a cache concern, but would at least prevent recycling of old filenames.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...