Basic Application Development: Part Three

File uploading and importing, front end helpers

Let's work with how you would get a file from within a custom form like our single page. PHP File uploading works pretty simply, but concrete5 has a very powerful file manager that can do quite a bit. You can run custom routines based on the file type, auto generate thumbnails, group files into sets to work with them programmatically, etc. 

We will modify our single page form to include another form input called "my_image" using the form helper to include a file input like so: 

<?php echo $form->file('my_image'); ?>

In our form elements, we'll need to also include an enctype anytime we are uploading files. You add that like so: 

<form method="post" action="<?php echo $this->action('update_color'); ?>" enctype="multipart/form-data">

Now let's upload a file through our form. When we hit save on this, it's going to go into the update_color function and run that, but now we will make it output the files array so that we can make sure that our file input is working. We will include this in our update color function: 

print_r($_FILES); 
exit;

This should output an associative array that looks like this:

Array ([my_image] => Array ([name] => my_file.jpg [type] => image/jpg [tmp_name] => /private/var/tmp/phpg3yVZC [error] => [size] => 5011)) 

Good, it's working. Keep this open in another window, we'll use some of the information in this array in the next step. Now we will delete the print function and exit and replace them with the concrete5 file importer. This automatically imports the file into the concrete5 file manager.

To do this, we'll include the file/importer library into our update_color function, create a new File Importer objet, and use it to import the file. Here's how that will look:

Loader::library('file/importer');
$fi = newFileImporter();
$pathToFile = $_FILES['my_image']['tmp_name'];
$nameOfFile = $_FILES['my_image']['name];
$myFileObject = $fi->import($pathToFile, $nameOfFile);

This function returns an object, which is analogous to the file object in the file manager. Let's run this now. Now, you can see the image is included in our file manager. We can now edit all the properties we have available to use through the CMS. We can also add attributes to the file, so there are plenty of robust features we can now take advantage of using the file importer. 

Let's try another example. Let's say we want to add a user attribute that is an image that includes their favorite color. Before we do this, we need to enable file attributes for users. We do that by heading to System and Settings > Attribute sets, and add Image/File as an attribute we can use for users by ticking the box for "user" in that row. Now let's head back to user attributes and add an image/file attribute called "favorite_color_picture" for the handle, and name it Favorite Color Picture. Now in the user attributes, you can find this attribute and use the file picker to apply an image to users. 

Now, in our update_color function, let's move our file import code chunk up into the if clause prior to the "favorite_color" attribute being set. In addition, we will add another setAttribute function for the attribute favorite_color_picture to save our file object against the user. This will look like so: 

public function update_color() {
	if ($this->myUI instanceOf UserInfo) {
		$fi = newFileImporter();
		$pathToFile = $_FILES['my_image']['tmp_name'];
		$nameOfFile = $_FILES['my_image']['name];
		$myFileObject = $fi->import($pathToFile, $nameOfFile);
		$this->myUI->setAttribute('favorite_color', $this->post('color'));
		$this->myUI->setAttribute('favorite_color_picture', $myFileObject);
		}
	$this->redirect('/my_favorite_color');
}

An important thing to note here is that we are just passing setAttribute the file object directly. setAttribute knows what to do with a file object in the context of setting a file attribute, so this all works seamlessly. Now when we run this, we can see that this image is added to the file manager, and is also applied to the correct user as the attribute favorite_color_picture. 

Let's talk about some of the more exotic form helpers. Let's add an instance of the color picker to our on_start function: 

$hcolor = Loader::helper('form/color');
$this->set('hcolor', $hcolor);

Now in our single page, instead of the text field for favorite color, we will include the color picker: 

<?php echo $hcolor->output('color', 'Favorite Color'); ?>

You can see that it takes two parameters, the first being the name of the field, and the second being the label which is visible to our users. 

Let's try it out. Now you can see on our single page, we have a color picker that we can use to pick our favorite color. This will save the hex code for the color you picked, so we don't even need to modify our saving functionality. We can now set our color picker to prepopulate that user's favorite color by passing in a third parameter to our color picker in our single page like so: 

<?php echo $hcolor->output('color', 'Favorite Color', $favoriteColor'); ?>

Now your color picker should be working! You will need to be logged in currently for it to function properly. We will go over loading the proper javascripts and stylesheets for it to work for users without edit bar access in part four. 

color-picker.jpg

Placing files in sets

We can place our uploaded photos for favorite color into a file set programmatically so that we can easily search for those files. First let's create a file set called Favorite Color Pics. Now, in our code, we can add functionality to the update_color function right after we import the file to check that the uploaded file is indeed an object and place it in a set:

if (is_object($myFileObject)) {
	Loader::model('file_set');
	$fs = FileSet::getByName('Favorite Color Pics');
	$fs->addFileToSet($myFileObject); 
}

Note that we are loading from the models directory in our root. This is so concrete5 can check to see if you have a model override in place and use that instead in case you have made modifications to that model. If you are ever wondering about the exact method to call for model functions, you can always peruse the functions detailed in the model file itself, in this case concrete/core/models/file_set.php. Now you can see that the picture is applied to the user, and has been saved in the file manager. We can also search by our new set, and see that our new photo has been added to the Favorite Color Pics set. Equally as cool, we can also search for "Files in no sets", meaning if we didn't want all of our user added images to be intermixed with our system files, we can exclude those from our search pretty easily. 

Uploaded Files and Permissions

When you allow file upload, you can make that file be saved in a location out of the web root, or have it password protected, optionally. The uploader ID is also logged, as well as users who edit files. If you enable advanced permissions on your site, you can control who has access to edit files in the file manager to a very granular degree in the File Manager Permissions area of the dashboard.  You can also configure a file uploader user so that file up loaders can only see their own uploaded files. 

Regarding permission checks, you can set up code that runs permission checks and/or sets permissions for your files and file sets programmatically or you can set permissions up at the UI level as well to achieve similar results. 


Recent Discussions on this Topic

Date picker not working in my web application

Hi I am working in the web application development using concrete5.6.1.2 the application is work when the concrete logged in the admin. for ex: i am using core concrete files in my application are [code][/code] [code][/code] but after sign out…

seperate login...

I am new to concrete5. How to set separate login for my application. concrete5 already gives the login page. But i want to use it as site editing admin. I need a another login to my application. If the application is open the home page should open af…

How to set my custom login page as startup page?

I'm creating an application using concrete5. I'm beginner of concrete5. So, how to set the login page to my application. I want to use concrete5's core login page as site editing login. If an end user open my application, at first it should show m…

Application Flow

hi, i just read the page about the application flow (http://www.concrete5.org/documentation/introduction/the-dispatcher-understanding-the-concrete-applic/). I am actually developping (or trying to do it !) a web app integrated with C5. My applicatio…