Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

Custom upload directory


Go to End


11 Posts   5415 Views

Avatar
JoshuaLewis

Community Member, 81 Posts

9 November 2009 at 9:05pm

Edited: 09/11/2009 9:08pm

Is the process described in this archived thread the best way enable the use of custom upload directories with a FileIFrameField in the cms or is there an easier fix that won't make it difficult to update the silverstripe?

Note - I'm using Silverstripe 2.3.3 with r317 of DataObjectManager.

Avatar
ajshort

Community Member, 244 Posts

9 November 2009 at 9:10pm

Yes, you can checkout either the 2.4 branch or trunk from svn (I recommend using the 2.4 branch for stability), and then use the $folderName argument to the constructor. This was broken in the 2.3 series.

Avatar
JoshuaLewis

Community Member, 81 Posts

10 November 2009 at 12:06pm

Edited: 10/11/2009 12:16pm

Thanks, would that be the 2.4 installer found here? : http://svn.silverstripe.com/open/phpinstaller/branches/2.4

Avatar
JoshuaLewis

Community Member, 81 Posts

10 November 2009 at 4:05pm

I'm using DataObjectManager and relying on functionality from it that is more critical than the custom directories. UncleCheese said he hasn't got the module stable with trunk or the 2.4 branch.

So what other options do I have?

Avatar
Double-A-Ron

Community Member, 607 Posts

15 November 2009 at 5:49pm

Subscribe

I am currently needing the same thing. I have taken UncleCheese's gallery module (that uses DOM) and checked out how it creates and saves images to directories organised by album name.

It must be possible as he was able to achieve it for Gallery. I have managed to get my page type to create it's own directory when saved using this on the main page class (My Page is called "Publications")

/**
  * Overload OnBeforWrite to create or set the Folder ID for this Publication
  * This is done as we are automatically storing the issue PDFs in a custom directory for tidyness
  */
  function onBeforeWrite() {
    parent::onBeforeWrite(); 
    
    if(isset($_POST['URLSegment'])) {
      if($this->FolderID) {
        $this->Folder()->setName($_POST['URLSegment']);
        $this->Folder()->Title = $_POST['URLSegment'];

        $this->Folder()->write();
      }
      else {
        $folder = Folder::findOrMake('publications/'.$_POST['URLSegment']);
        $this->FolderID = $folder->ID;
        $this->write();
      }
    }
  }

Be sure that your Page has_one Folder first ofcourse. The above code with create the directory if it doesn't already exist and save the FolderID to your page.

Next step is to get the files saved to that path from a FileIFrameField. So I'm picking through ImageGalleryManager (Which extends ImageDataObjectManager). I can see how he's doing it, however he uses ImageField for uploading images, not the IFrame variation, so I'm not sure if it's even possible at this stage.

Aaron

Avatar
Double-A-Ron

Community Member, 607 Posts

15 November 2009 at 7:17pm

Edited: 15/11/2009 10:57pm

Well, I decided to can this hack due to deadline. What I have done instead is used FileDataObjectManager instead of DataObjectManager after looking at this doc: http://doc.silverstripe.org/doku.php?id=modules:dataobjectmanager (about 1/2 way down).

I still use the code above to create the directory when my page is made (not sure if the next lot of code would do a findOrMake()).

Note:
My page is "Publications" (magazines) - Extends Page
Publications has_many "PublicationIssues" (monthly releases) - Extends DataObject
PublicationIssues has_one "DigitalCopy", which is the File.

Then, in the same Page class, instead of:

// Setup the Issues table Dataobject manager
    $issues = new DataObjectManager(
      $this,
      'PublicationIssues',
      'PublicationIssue',
      array('Name' => 'Name','ReleaseDate'=>'ReleaseDate'),
      'getCMSFields_forPopup'
    );
    $issues->setAddTitle('PDF Issue');

I use:

// Setup the Issues table Dataobject manager
    $issues = new FileDataObjectManager(
      $this,
      'PublicationIssues',
      'PublicationIssue',
      'DigitalCopy', // This is the name of the file object in PublicationIssue
      array('Name' => 'Name','ReleaseDate'=>'ReleaseDate'),
      'getCMSFields_forPopup'
    );
    $issues->setAddTitle('PDF Issue');
    $dest = substr_replace(str_replace('assets/','',$this->Folder()->Filename),"", -1);  // DIR is already created. Just get it here.
    $issues->setUploadFolder($dest); // Set the file destination field
    $issues->setUploadLimit(1); // Set the upload limit (We only want one)

The only difference in the process from the original, is that you upload the file first, and enter the other data afterwards.

The glaring downside that may not be any good for you is that editing existing records display's the same FileIframeField that defaults to "Uploads" when you do a "Replace File". Not so bad for us, as these are magazine issues that never change. If an incorrect PDF is uploaded, it's no big deal to delete the original and redo. Worst case scenario we have a few PDFs sitting in the Uploads directory.

Not the perfect solution, but will cover us until 2.4 is stable.

Aaron

Avatar
bummzack

Community Member, 904 Posts

15 November 2009 at 10:03pm

Edited: 15/11/2009 10:12pm

Nice solution there Aaron. Not sure if I would use the URLSegment as folder name though, since users can easily change that and then you'll end up with files for one page, but in different folders? I'd probably use something like 'folder' + PageID, although that's not as readable. Best would probably be an ID based foldername, then change the "Title" of the folder to the URLSegment. Whenever URLSegment changes, change the title of the folder associated with the page.

I'd probably also add the relation to the Folder to the $has_one array.

public static $has_one = array(
	'UploadFolder' => 'Folder'
);

In your DataObjects you could have an onBeforeWrite function that moves the file to the UploadFolder...

protected function onBeforeWrite(){
	// get the file of this DataObject
	$file = $this->MyFileField();

	// get the UploadFolder from the holder of this dataObject
	$folder = $this->HolderPage()->UploadFolder();

	if($file && $folder){
		// check if file isn't stored in folder yet
		if($folder->ID != $file->ParentID){
			// move file to folder
			$file->setParentID($folder->ID);
			$file->write();
		}
	}
	parent::onBeforeWrite();
}

Update If you establish a has_one relation from your Page to an UploadFolder, you can simply create a folder whenever the page is written for the first time (eg. check if it has a folder, if not create one). From that point on you can forget about the issues that might occur when you use URLSegment to determine the upload-folder (since you would use the UploadFolder instead of going the URLSegment route).

Avatar
Double-A-Ron

Community Member, 607 Posts

15 November 2009 at 10:24pm

Edited: 15/11/2009 10:26pm

Not sure if I would use the URLSegment as folder name though, since users can easily change that and then you'll end up with files for one page, but in different folders

Hmmm. I've been SS developing for 14 days straight so my mind might be a muddle on this one. When the page is first created, the very fisrt block of code checks to see if it has a FolderID, if not, it creates the folder using the URLSegment, and assigns the FolderID (from the Files table) to the page.

So I may be wrong, but wouldn't that ID stay the same no matter what the URL is changed to?

E.G.
One of these pages in my case is called MIR Report. The URLSegment is mir-report. On initial save the folder that is created is called /assets/publications/mir-report.

Lets say the ID for that folder is 30. This is assigned to the MIR Report page's FolderID field in the table.

If I change the Title of the page to "Our MIR Reports" and the URL to "our-mir-reports", the FolderID shouldn't be touched. All that it means is that all the files are dropping into a folder that doesn't exactly reflect the URL anymore. Which isn't a biggie for me.

Can you logic check that for me to save my brain from exploding? I will test tomorrow when I get in.

public static $has_one = array(
   'UploadFolder' => 'File'
);

Yes I did that in my Page Type. But based on the ImageGallery module, it was

public static $has_one = array(
   'UploadFolder' => 'Folder' // See Folder - The Files table stores both classes.
);

Ta
Aaron

Go to Top