Guy Incognito

(Another!) Image upload script issue thread

Recommended Posts

Posted (edited)

I'm trying to implement a front-end image upload form for user profile pictures, to a field called 'profile_picture'. The code is based on the various examples found around these forums but isn't yet 100% right.

The form successfully submits the image to the server and updates the field in the dashboard. When you submit the firm, the page reloads and uploads the image but the template still loads the old image path (now broken path as the old image has been removed).

I can only get the new image to show if I hit enter in the address bar forcing the page to reload.

Any ideas? Is it a caching issue, or something to do with the order of the script? It makes no difference if I call the image after the upload form.

<?php
//Display current user image
	$userImg = $user->profile_picture->first();
	echo '<img src="'.$userImg->url.'">';

    $upload_path = $config->paths->assets . "files/avatar_uploads/"; 

    $f = new WireUpload('userimage'); 
    $f->setMaxFiles(1);
    $f->setMaxFileSize(1*1024*1024);
    $f->setOverwrite(true);
    $f->setDestinationPath($upload_path);
    $f->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif'));

    if($input->post->form_submit) {
        if(!is_dir($upload_path)) {
            if(!wireMkdir($upload_path)) throw new WireException("No upload path!");
        }

        $files = $f->execute(); 
    
        if ($f->getErrors()) {    
            foreach($files as $filename) @unlink($upload_path . $filename);
            foreach($f->getErrors() as $e) echo $e;
        } else {
            $user->of(false);
            $user->profile_picture->removeAll(); // wirearray  (line added by @horst: explanation is three posts beneath)
            $user->profile_picture = $upload_path . $files[0];
            $user->save();
            $user->of(true);
            @unlink($upload_path . $files[0]);
        }
    }

?>
<form class="forum-form" accept-charset="utf-8" action="./" method="post" enctype="multipart/form-data" >
    <input type="file" id="attach" name="userimage" accept="image/jpg,image/jpeg,image/gif,image/png" /> 
    <input type="submit" name="form_submit" value="Submit"/> 
</form>


 

Edited by Guy Incognito
Tidied up code snippet

Share this post


Link to post
Share on other sites
Posted (edited)

oops, no too fast 😁

Edited by flydev
wrong
  • Haha 1

Share this post


Link to post
Share on other sites

I guess it's a caching issue. Instead of 

action="./"

I would add a pseudo query string to the form target (timestamp or random characters).

Share this post


Link to post
Share on other sites
15 minutes ago, dragan said:

I guess it's a caching issue. Instead of 

action="./"

I would add a pseudo query string to the form target (timestamp or random characters).

This was my original guess. Query string is a good idea but doesn't seem to make any difference. 😕 I've tried as follows:

action="./?<?=substr(base64_encode(mt_rand()), 0, 15);?>"

 

Share this post


Link to post
Share on other sites
Posted (edited)

ok this time is good, you need to put your markup after the if condition.

 

<?php
//Display current user image
    $upload_path = $config->paths->assets . "files/avatar_uploads/"; 

    $f = new WireUpload('userimage'); 
    $f->setMaxFiles(1);
    $f->setMaxFileSize(1*1024*1024);
    $f->setOverwrite(true);
    $f->setDestinationPath($upload_path);
    $f->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif'));

    if($input->post->form_submit) {
        if(!is_dir($upload_path)) {
            if(!wireMkdir($upload_path)) throw new WireException("No upload path!");
        }

        $files = $f->execute(); 
    
        if ($f->getErrors()) {    
            foreach($files as $filename) @unlink($upload_path . $filename);
            foreach($f->getErrors() as $e) echo $e;
        } else {
            $user->of(false);
            $user->profile_picture->removeAll(); // wirearray  (line added by @horst: explanation is three posts beneath)
            $user->profile_picture = $upload_path . $files[0];
            $user->save();
            $user->of(true);
            @unlink($upload_path . $files[0]);
        }
    }

// here
$userImg = $user->profile_picture->first();
echo '<img src="'.$userImg->url.'">';

?>

<form class="forum-form" accept-charset="utf-8" action="./" method="post" enctype="multipart/form-data" >
    <input type="file" id="attach" name="userimage" accept="image/jpg,image/jpeg,image/gif,image/png" /> 
    <input type="submit" name="form_submit" value="Submit"/> 
</form>

 

avatar.gif.36a218232f6922fd847c54738ce05b52.gif

 

and if you want to avoid a warning in imageExtra, then you should assign a title to the picture_profile field :

[...]
$user->profile_picture->title = ''; // or whatever
$user->save()
[...]

 

Edited by flydev
working example
  • Like 1

Share this post


Link to post
Share on other sites

It's not the Browser cache or something, but the PW page cache in memory. You'd need to reload the $user after your upload and saving image...

$u = $users->get($user->id);
if($u->profile_picture) {
    $userImg = $u->profile_picture;
    echo '<img src="'.$userImg->url.'">';
}

Anyway I would recommend to redirect to the page after submit, but then you need to handle errors differently. Like this you would upload the form with a refresh or going back.

Also I would rethink the upload folder to be in a folder not accessible from public for security reasons. You can simply use a folder in "site/assets/cache/.uploads" as . folders will get blocked by PW .htaccess.

Also you could move the part with the WireUpload into your if($input->post->form_submit) { .... as it's not needed before that.

 

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites
17 minutes ago, Soma said:

It's not the Browser cache or something, but the PW page cache in memory. You'd need to reload the $user after your upload and saving image...


$u = $users->get($user->id);
if($u->profile_picture) {
    $userImg = $u->profile_picture;
    echo '<img src="'.$userImg->url.'">';
}

Anyway I would recommend to redirect to the page after submit, but then you need to handle errors differently. Like this you would upload the form with a refresh or going back.

Also I would rethink the upload folder to be in a folder not accessible from public for security reasons. You can simply use a folder in "site/assets/cache/.uploads" as . folders will get blocked by PW .htaccess.

Also you could move the part with the WireUpload into your if($input->post->form_submit) { .... as it's not needed before that.

 

Ah perfect thanks - all makes perfect sense now you've spelled it out to me - reloading the user object solves the issue 🙂 

And yes - addressing the security issues above is in my todo list - this was just a prototype based on examples on this forum and it was bugging the hell out of me why the image wouldn't load first time! 

 

  • Like 1

Share this post


Link to post
Share on other sites
3 hours ago, Guy Incognito said:

Also I would rethink the upload folder to be in a folder not accessible from public for security reasons. You can simply use a folder in "site/assets/cache/.uploads" as . folders will get blocked by PW .htaccess.

I'm just experimenting with your idea @Soma as I hadn't thought about this approach for securing the upload folder before. Using the path as you described throws an error though, even if I manually create the .folder.

Error: Exception: No upload path!

Should PW automatically handle this path or does it need me to configure this folder somewhere? Or perhaps the server doesn't allow the .folders?

Share this post


Link to post
Share on other sites

Can someone please help me, I am using the same code as mentioned above with some additional security check; even though the result is successful the image file is not being stored in the avatar folder within site/asset.

<?php namespace ProcessWire;

error_reporting(E_ALL);
ini_set('display_errors', 1);

ob_start();
require_once('/var/www/rajibde/index.php');
ob_end_clean();

$input = wire('input');
$sanitizer = wire('sanitizer');
$config = wire('config');
$session = wire('session');

$upload_path = $config->paths->assets . 'avatar/';
chmod($upload_path, 0777);

if ($input->post && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {

	$user = $session->get('memberName');

	$img = $input->post->image;
	
	list($type, $img) = explode(';', $img);
	list(, $img)      = explode(',', $img);
	list($type,) = explode('/',$type);

	$img = base64_decode($img);

	//$img = implode($img,'.',$type);

	$img = $img . '.' . $type;
	
	//print_r('Successful' . $img);

	$f = new WireUpload($img); 
	$f->setMaxFiles(1);
	$f->setMaxFileSize(1*1024*1024);
	$f->setOverwrite(true);
	$f->setDestinationPath($upload_path);
	$f->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif'));

	if(!is_dir($upload_path)) {
		if(!wireMkdir($upload_path)) throw new WireException("No upload path!");
	}

	$files = $f->execute();
	echo $files[0];

	if ($f->getErrors()) {    
		foreach($files as $filename) @unlink($upload_path . $filename);
			foreach($f->getErrors() as $e) echo $e;
	}
	else {
		//Save the photo to the avatar field
		$u = $users->get($user->id);
		$u->of(false);
		$u->avatar = $upload_path . $files[0];
		//echo $u->avatar;
		$u->save();
		$u->of(true);
		@unlink($upload_path . $files[0]);
		print_r('Successful' . $img . $files[0]);
		echo 'Cropped image uploaded successfully.';
	}
}
else {
	echo '<div class="w3-row-padding w3-wide w3-text-red w3-text-jumbo"><strong>Unauthorised access. Your access to this site might be permanently blocked if tresspassing continues</strong></div>';
	die();
}

?>

 

Share this post


Link to post
Share on other sites
38 minutes ago, Raj said:

Can someone please help me, I am using the same code as mentioned above with some additional security check; even though the result is successful the image file is not being stored in the avatar folder within site/asset.

Does the user field get updated successfully?

I’m not in front of my computer at the moment to check but from my memory the file doesn’t stay in the upload folder it gets moved to the folder where all your site image uploads go.

Share this post


Link to post
Share on other sites
49 minutes ago, Guy Incognito said:

Does the user field get updated successfully?

I’m not in front of my computer at the moment to check but from my memory the file doesn’t stay in the upload folder it gets moved to the folder where all your site image uploads go.

Yes, only with the upload location but the file name and extension is missing.... In other words "echo files[0]" doesn't yield any value.

Share this post


Link to post
Share on other sites
8 minutes ago, Raj said:

Yes, only with the upload location but the file name and extension is missing.... In other words "echo files[0]" doesn't yield any value.

Still only on my iPad at mo so just guessing but don’t you need todo something like $files[0]->url to get the complete path?

Share this post


Link to post
Share on other sites

Path is getting populated and stored in DB but the file name and extension is missing in DB. Even the image file doesn't get stored in the upload location -> site/assets/avatar. 😔 And I am not able to figure out why it is not saving the image

Share this post


Link to post
Share on other sites

@ryan could please help me on this. I am stuck here and not able to move forward even after spending hours together to understand what and where it is going wrong.

Share this post


Link to post
Share on other sites

Nothing too obvious. Maybe if you can provide a complete code example of your setup, form and scripts it would be possible to help. Why is this a boostrap file with ob_start and ob_end_clean? And sending the form with ajax? This seems it is not a regular setup.

I would test your form getting send and the getting through. I think the problem is not the image not getting saved but not even getting uploaded whatever.

Share this post


Link to post
Share on other sites

This is the code that is responsible for invoking the AJAX call.

<?php namespace ProcessWire;

$session = wire('session');

?>
<span class="w3-col m5">

    <div id="upload_img" class="w3-margin w3-border-teal w3-round w3-opacity-min w3-display-container" style="border-style: groove;">
        <!--<i class="fa fa-edit w3-xxxlarge w3-hover-red w3-round-large w3-display-bottomright" style="font-weight:bolder;"></i>-->
    </div>

    <div class="w3-margin">
        <label class="w3-button w3-blue-gray w3-border w3-border-green w3-round-large w3-wide w3-bar uploadimg" style="font-weight:bolder;"><span><i class="fa fa-cloud-upload fa-lg w3-left">&nbsp;|</i></span>Upload Avatar<input type="file" id="upload" accept="image/*" class="avatar"></label>
        <!--<a class="w3-button w3-blue-gray w3-border w3-border-green w3-round-large w3-wide w3-bar actionUpload"><span><i class="fa fa-cloud-upload fa-lg w3-left">&nbsp;|</i>Change Avatar</span><input type="file" id="upload" value="Choose Image" accept="image/*"></a>-->
        <button class="w3-button w3-blue-gray w3-border w3-border-green w3-round-large w3-wide w3-bar actionDone" style="font-weight:bolder;"><i class="fa fa-check-circle-o fa-lg w3-left">&nbsp;|</i>Done</button>
    </div>
</span>

and this is the AJAX query which is responsible for calling the upload.php page

$('#upload').on('change', function () { 
	var reader = new FileReader();
	
	reader.onload = function (e) {
		$uploadCrop.croppie('bind', {
			url: e.target.result
		}).then(function(){
			console.log('jQuery bind complete');
		});
		$('.actionDone').toggle();
      		$('.uploadimg').toggle();
	}
	reader.readAsDataURL(this.files[0]);
});

$('.actionDone').on('click', function (ev) {

	$('.actionDone').toggle();
      	$('.uploadimg').toggle();

	$uploadCrop.croppie('result', {
		type: 'canvas',
		size: 'viewport'
	}).then(function (response) {
		$.ajax({
			url: '/site/templates/upload.php',
			type: "POST",
			data: {"image":response},
			success: function (data) {
				if (data == 'Cropped image uploaded successfully') {
					html = '<img src="' + response + '" id="img_resp" />';
					$("#upload_img").html(html);
				}
				else {
					$("body").append("<div class='upload-error'>" + data + "</div>");
				}
			}
		});
	});
});

Finally this is code in upload.php file that is responsible for uploading the image.

<?php namespace ProcessWire;

error_reporting(E_ALL);
ini_set('display_errors', 1);

ob_start();
require_once('/var/www/rajibde/index.php');
ob_end_clean();

$input = wire('input');
$sanitizer = wire('sanitizer');
$config = wire('config');
$session = wire('session');

$upload_path = $config->paths->assets . 'avatar/';
chmod($upload_path, 0777);

if ($input->post && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {

	$user = $session->get('memberName');

	$img = $input->post->image;
	$log->message("image ->" . $img);
	
	list($type, $img) = explode(';', $img);
	list(, $img)      = explode(',', $img);
	list($type,) = explode('/',$type);

	$img = base64_decode($img);

	//$img = implode($img,'.',$type);

	$img = $img . '.' . $type;
	$log->message("IMG TYPE ->" . $img);

	$f = new WireUpload($img); 
	$f->setMaxFiles(1);
	$f->setMaxFileSize(2*1024*1024);
	$f->setOverwrite(true);
	$f->setDestinationPath($upload_path);
	$f->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif'));

	if(!is_dir($upload_path)) {
		if(!wireMkdir($upload_path)) throw new WireException("No upload path!");
	}

	$files = $f->execute();

	if ($f->getErrors()) {    
		foreach($files as $filename) unlink($upload_path . $filename);
			foreach($f->getErrors() as $e) echo $e;
	}
	else {
		$log->message("1 ->" . $_FILES);
		//Save the photo to the avatar field
		$u = $users->get($user->id);
		$log->message("2 ->" . $u);
		$u->of(false);
		$u->avatar = $upload_path . $files[0];
		$log->message("3 ->" . $u->avatar);
		$u->save();
		$u->of(true);
		unlink($upload_path . $files[0]);
		print 'Cropped image uploaded successfully';
	}
}
else {
	echo '<div class="w3-row-padding w3-wide w3-text-red w3-text-jumbo"><strong>Unauthorised access. Your access to this site might be permanently blocked if tresspassing continues</strong></div>';
	die();
}

?>

 

Share this post


Link to post
Share on other sites

I dont think this is working. Theres no form and input fields.

Edit: And you can`t call a php in templates folder directly in PW. Why don't you just do it using a real page?

Share this post


Link to post
Share on other sites
54 minutes ago, Soma said:

I dont think this is working. Theres no form and input fields.

Edit: And you can`t call a php in templates folder directly in PW. Why don't you just do it using a real page?

Hello Soma,

Input field is there in the html form...here is the code , please see after <span> field in the below code -> 

Could you help guide what you meant by "Why don't you just do it using a real page?" please?

<label class="w3-button w3-blue-gray w3-border w3-border-green w3-round-large w3-wide w3-bar uploadimg" style="font-weight:bolder;"><span><i class="fa fa-cloud-upload fa-lg w3-left">&nbsp;|</i></span>Upload Avatar<input type="file" id="upload" accept="image/*" class="avatar"></label>

Share this post


Link to post
Share on other sites

I mean to use a PW page (/some/url/) with its template file to handle all that instead of pointing directly to a .php file. You can't call a .php in templates folder, it would have to be somewhere in the webroot.

Share this post


Link to post
Share on other sites
2 hours ago, Soma said:

I mean to use a PW page (/some/url/) with its template file to handle all that instead of pointing directly to a .php file. 

Sure Soma, let me try that 🙂

with re to "You can't call a .php in templates folder, it would have to be somewhere in the webroot." not sure if I am doing it the correct way...all my PHP files are actually residing in site/templates folder, after saving them in this folder I add them as template using the Admin page and access them...and most of my validation pages are called by ajax method defined in custom JS files...

I am actually very new to CMS and PHP; learning on my own with abundant help from this forum and Google 🙂

If it doesn't take much time or there is already a page on this, can you help me understand the best way to build a custom site in processwire with custom styles and JS...mainly around where do I place my custom php files...how to utilize processwire to it's capactiy.

 

Share this post


Link to post
Share on other sites

Im sorry i cant make a full from 0 course of how to build with php html js css and PW. Theres plenty of guides and tutorials around here.

It's just you dont need to request a php file in a form. Youd just use the current page url as the action url. Them have your processing code in the template file that page uses. 

Why dont you start with a simple form without ajax? Once you have that down you can still try to use ajax.I never done a image upload with ajax so not even sure it would work the way you try it.

Maybe someone else had the time to give further advise or links.

Share this post


Link to post
Share on other sites

@Raj I second @Soma‘s advice. There’s a lot of great PW tutorials listed here:

https://processwire.com/docs/tutorials/

You don’t sound like you’re a million miles away from what you’re looking to achieve and as per Soma’s comment I would just reload your script to check for submission rather than worrying about Ajax upload.

Definitely recommend checking the tuts above out, it’s where I started with PW and I’ve not looked back!

I’ve found PW to be the easiest CMS to get to grips with and it’s also really pushing my PHP skills to new places too :-) because the core is so well organised it allows you to be more creative with what you want to do.

Share this post


Link to post
Share on other sites

I can understand Soma, but thank you for your guidance...probably I missed to read through the Docs section properly, let me redo 🙂

Share this post


Link to post
Share on other sites
22 hours ago, Guy Incognito said:

@Raj I second @Soma‘s advice. There’s a lot of great PW tutorials listed here:

https://processwire.com/docs/tutorials/

You don’t sound like you’re a million miles away from what you’re looking to achieve and as per Soma’s comment I would just reload your script to check for submission rather than worrying about Ajax upload.

Definitely recommend checking the tuts above out, it’s where I started with PW and I’ve not looked back!

I’ve found PW to be the easiest CMS to get to grips with and it’s also really pushing my PHP skills to new places too 🙂 because the core is so well organised it allows you to be more creative with what you want to do.

Agree with you mate. I have already started going through the doc section once again, hopefully this time I will get the right essence. 🙂

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Xonox
      Hi,
       
      I'm trying to upload images from a folder into a page. I need to replace the images instead of adding. The image field already has the replace existing images turned on, but it doesn't seem to be enough.
       
      My code:
      foreach($files as $file) { if(substr($file, 0, 1) != '.' && $file != '.' && $file != '..') { // Get SKU $file_sku = substr($file, 0, 9); // Check for book $book = $pages->get('sku=' . $file_sku); if(!$book->id) { // Book doesn't exist } else { // Upload image into book !!! THIS CODE ADDS FILE INSTEAD OF REPLACING. HOW CAN I REPLACE? $book->book_images->add($upload_directory . '/' . $file); // Delete file unlink($upload_directory . '/' . $file); } // Save book if($book->id) $book->save(); } }  
      What am I missing?
    • By bot19
      Hey guys,
      Today I was uploading images and ran into an image I couldn't upload. This has never happened before since I got images uploading working.
      I had a dig around the forum but couldn't find anything relevant.
      Initially I thought it was due to the size ~1.3mb, but I had uploaded something bigger after and it was fine (~1.7mb). There are no size or dimension restrictions on this image field.
      After looking at the image some more, I realised its dimensions was HUGE: ~5300px
      There must be some sort of limit somewhere throwing an error due to this dimension size? Because after I resized the image down to 2560px, it uploaded fine.
      What does everyone think? I kind of just want to know. See below for more info. Thanks!
      Uploading the smaller file, everything is fine. If you look at the response, you can see:
      [{"error":false,"message":"Added file: mock-email-marketing-and-newsletters-smaller.png","file":"\/procwire\/site\/assets\/files\/1189\/mock-email-marketing-and-newsletters-smaller.png","size":340797,"markup":"<li id='file_551ac1043f1cbbe0b909dab963a1f28c' class='ImageOuter gridImage ui-widget'><div class='gridImage__tooltip'><table><tr><th>Dimensions<\/th><td>2560x2560<\/td><\/tr><tr><th>Filesize<\/th><td>333&nbsp;kB<\/td><\/tr><tr><th>Variations<\/th><td>0<\/td><\/tr><\/table><\/div>\n\t\t\t<div class='gridImage__overflow'>\n\t\t\t\t<img src=\"\/procwire\/site\/assets\/files\/1189\/mock-email-marketing-and-newsletters-smaller.0x260.png?nc=1512803364\" alt=\"\" data-w=\"2560\" data-h=\"2560\" data-original=\"\/procwire\/site\/assets\/files\/1189\/mock-email-marketing-and-newsletters-smaller.png?nc=10\" \/>\n\t\t\t<\/div>\n\t\t\t\n\t\t\t\t<div class='gridImage__hover'>\n\t\t\t\t\t<div class='gridImage__inner'>\n\t\t\t\t\t\t<label for='' class='gridImage__trash'>\n\t\t\t\t\t\t\t<input class='gridImage__deletebox' type='checkbox' name='delete_crm_feature_img_repeater1189_551ac1043f1cbbe0b909dab963a1f28c' value='1' title='Delete' \/>\n\t\t\t\t\t\t\t<span class='fa fa-trash-o'><\/span>\n\t\t\t\t\t\t<\/label>\n\t\t\t\t\t\t<a class='gridImage__edit'>\n\t\t\t\t\t\t\t<span>Edit<\/span>\n\t\t\t\t\t\t<\/a>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\n\t\t\t\t<div class='ImageData'>\n\t\t\t\t\t<h2 class='InputfieldImageEdit__name'><span contenteditable='true'>mock-email-marketing-and-newsletters-smaller<\/span>.png<\/h2>\n\t\t\t\t\t<span class='InputfieldImageEdit__info'>333&nbsp;kB, 2560&times;2560 <\/span>\n\t\t\t\t\t<div class='InputfieldImageEdit__errors'><\/div>\n\t\t\t\t\t<div class='InputfieldImageEdit__buttons'><small><button type='button' data-href='\/procwire\/admin123\/page\/image\/edit\/?id=1189&file=1189,mock-email-marketing-and-newsletters-smaller.png&rte=0&field=crm_feature_img' class='InputfieldImageButtonCrop ui-button ui-corner-all ui-state-default pw-modal-large pw-modal' data-buttons='#non_rte_dialog_buttons button' data-autoclose='1' data-close='#non_rte_cancel'><span class='ui-button-text'><span class='fa fa-crop'><\/span> Crop<\/span><\/button><button type='button' data-href='\/procwire\/admin123\/page\/image\/variations\/?id=1189&file=mock-email-marketing-and-newsletters-smaller.png&modal=1&varcnt=varcnt_crm_feature_img_repeater1189_551ac1043f1cbbe0b909dab963a1f28c' class='ui-button ui-corner-all ui-state-default pw-modal-large pw-modal' data-buttons='button'><span class='ui-button-text'><span class='fa fa-files-o'><\/span> Variations <span class='ui-priority-secondary'>(0)<\/span><\/span><\/button><\/small><\/div>\n\t\t\t\t\t<div class='InputfieldImageEdit__core'><div class='InputfieldFileDescription'><label for='description_crm_feature_img_repeater1189_551ac1043f1cbbe0b909dab963a1f28c' class='detail'>Description<\/label><input type='text' name='description_crm_feature_img_repeater1189_551ac1043f1cbbe0b909dab963a1f28c' id='description_crm_feature_img_repeater1189_551ac1043f1cbbe0b909dab963a1f28c' value='' \/><\/div><\/div>\n\t\t\t\t\t<div class='InputfieldImageEdit__additional'><\/div>\n\t\t\t\t\t<input class='InputfieldFileSort' type='text' name='sort_crm_feature_img_repeater1189_551ac1043f1cbbe0b909dab963a1f28c' value='2' \/>\n\t\t\t\t\t<input class='InputfieldFileReplace' type='hidden' name='replace_crm_feature_img_repeater1189_551ac1043f1cbbe0b909dab963a1f28c' \/>\n\t\t\t\t\t<input class='InputfieldFileRename' type='hidden' name='rename_crm_feature_img_repeater1189_551ac1043f1cbbe0b909dab963a1f28c' \/>\n\t\t\t\t<\/div>\n\t\t\t<\/li>","replace":true,"overwrite":0}]
      Uploading the original file, something happens and there is no response (see Content-Length: 0)

      Which in turn must trigger this issue in the JS.

      No response.

    • By Kiwi Chris
      Forms are an essential part of most websites, and it's no surprise that there's an excellent premium module Form Builder but what if you're on a zero budget for whatever reason?
      It is possible to build forms quickly and easily by making use of a couple of free modules and the admin UI to give you a great deal of flexibility and speed of development, particularly if you need multiple forms on a website with different fields.
      1. First you're going to need to install a couple of modules:
      Form Template Processor
      Fieldtype Select External Option
      2. For each form that you want to display, create a template without a template file and add fields to it as you normally would. (eg I have formContact, formRegister etc)
      Tip: under the Advanced tab in the setup for each template, I add a tag Forms so that all my forms templates are nicely grouped together in admin.
      3. Create a new field of type Select External Option and call it formTemplate
      In the section Create options from any database table select
      templates as the source table id as the Option Value name as the Option Label 4. Create a new template file and call it renderForm.php (or whatever else you like)
      Add an email field to this form - This will be the email address that forms get submitted to. Add the formTemplate field you previously created to this form. This will allow you to select which of the templates you previously created such as formContact, formRegister etc you want to render. Add any other fields as usual that you want to render on the page. Add the following PHP code to the template file. $recipient = $page->email; $form = $modules->get('FormTemplateProcessor'); $form->template = $templates->get($page->formTemplate->label); // required $form->requiredFields = array('contactName', 'contactEmail', 'contactMesssage'); //Optional: This can be improved by having a field in the page template with a CSV list of required fields eg $form->requiredFields = explode(',', $page->requiredFields) $form->email = $recipient; // optional, sends form as email. FormTemplateProcessor can also save forms to the database. $content .= $form->render(); //generate the form to display. Note: this doesn't actually render the form at this point, but you have it in the $content variable ready to output wherever you want in your template.
      Add any template HTML or other PHP code and echo $content; wherever you want to render the form.
      5. Create a page using the renderForm template, and provide an email address, and select a form that you want to display.
      6. Use CSS to style the form as required.
      7. View your new page, and check that the form renders correctly.
      8. You can modify the templates you created at step 2 or create new ones as required if your requirements for what fields forms display changes.
      Note: The Form Template Processor module can also save form input as pages, and the FieldType Select External Option can be set up with filtering, so this solution can probably be refined further.
    • By gonzz
      Hi i'm having a recurrent problem I found on this forum: when using the image uploader I get the following error on console "Unexpected token < in JSON". But I couldn't solve it with any of the other proposed solutions:
      setting debug to true setting $config->uploadTmpDir = dirname(__FILE__) . '/assets/uploads/'; setting uploadTmpDir in php.ini  
      BUT This problem only appears for non superuser users (ie editors).
      Running on a Digitial Ocean Server with NGINX and PHP 7.1. Version is ProcessWire 3.0.62
      Note: Im using Fredi plugin, but i doubt that's the problem because I'm using it in other sites with no problem
       
      Any idea how i could solve this (even with non ajax image upload) I need to sort this as fast and simple as possible
      Thanks in advance
    • By cleanboy
      Hey all,
      Mods; please feel free to move this if it is in the incorrect place although I thought this was the best place for it.
      Kinda new to processwire but getting the hang of it....I am trying to build a payment form with the Stripe platform but failing miserably....I really hope someone can help!
      So I am building my form with the PW API and also following through this documentation here: https://stripe.com/docs/elements and here: https://stripe.com/docs/charges
      My form is pretty basic just for testing purposes right now:
      <form id="payment-form" class="pusher" name="payment-form" method="post" action="./#booking-form"> <?php $tokenName = $this->session->CSRF->getTokenName(); $tokenValue = $this->session->CSRF->getTokenValue(); echo '<input type="hidden" id="_post_token" name="' . $tokenName . '" value="' . $tokenValue . '"/>'; $out = ""; $out .= '<div id="card-number"></div> <div id="card-errors"></div>'; // create a new form field (also field wrapper) $form = $modules->get("InputfieldForm"); $form->action = "./"; $form->method = "post"; $form->attr("id+name",'payment-form'); // First Name $field = $modules->get("InputfieldText"); $field->skipLabel = true; $field->attr('id+name','name'); $field->attr('placeholder','Full Name'); $field->required = 1; $form->append($field); // append the field to the form // create email field $field = $modules->get("InputfieldEmail"); $field->attr('id+name','email'); $field->attr('placeholder','Email'); $field->required = 1; $form->append($field); // append the field // oh a submit button! $submit = $modules->get("InputfieldSubmit"); $submit->attr("value","SUBMIT"); $submit->attr("id+name","submit"); $submit->attr("class","cta white"); $form->append($submit); if($input->post->submit) { // user submitted the form, process it and check for errors $form->processInput($input->post); if($form->getErrors()) { // the form is processed and populated // but contains errors $out .= $form->render(); } else { foreach($input->post as $key => $value) echo htmlentities("$key = $value") . "<br />"; } } else { foreach($form->children as $input){ $out .= "<div class='col-sm-6'>{$input->render()}</div>"; } } echo $out; ?> </form> That alone works fine and returns all of the fields values after I click submit which is great...now we add the javascript:
      //Stripe var stripe = Stripe('pk_test_*****************'); var elements = stripe.elements(); // Custom styling can be passed to options when creating an Element. var style = { base: { // Add your base input styles here. For example: fontSize: '16px', lineHeight: '24px' } }; // Create an instance of the card Element var card = elements.create('card', {style: style}); // Add an instance of the card Element into the `card-element` <div> card.mount('#card-number'); card.addEventListener('change', function(event) { var displayError = document.getElementById('card-errors'); if (event.error) { displayError.textContent = event.error.message; } else { displayError.textContent = ''; } }); // Create a token or display an error when the form is submitted. var form = document.getElementById('payment-form'); form.addEventListener('submit', function(event) { event.preventDefault(); stripe.createToken(card).then(function(result) { if (result.error) { // Inform the user if there was an error var errorElement = document.getElementById('card-errors'); errorElement.textContent = result.error.message; } else { // Send the token to your server stripeTokenHandler(result.token); } }); }); function stripeTokenHandler(token) { // Insert the token ID into the form so it gets submitted to the server var form = document.getElementById('payment-form'); var hiddenInput = document.createElement('input'); hiddenInput.setAttribute('type', 'hidden'); hiddenInput.setAttribute('name', 'stripeToken'); hiddenInput.setAttribute('value', token.id); form.appendChild(hiddenInput); // Submit the form form.submit(); } This gives an error in the console: Uncaught (in promise) TypeError: form.submit is not a function. 
      This is because our submit input has the name "submit". Ok thats cool...I can change that but once I do the page essentially refreshes and the form just shows again and it doesnt give me the values it did before....I guess it isnt posting? either way after I submit the form after changing the name of the submit button the form just loads again and anything inside: if($input->post->submit) doesnt seem to execute...so what gives?
      If anybody here has done this before with PW 3+ I would really love an example of how to use this to the point of sending information to Stripe.
      I have installed Stripe with composer and it would appear that I can refer to it in Processwire just fine...my problem is just getting to the point where I need to refer to it which is after the submit.
      I have seen the PaymentStripe module but tbh the documentation on that is somewhat lacking and im not even sure it works with the latest version of stripe? Im also not sure how to integrate that into a form either unless you use something along the lines of the example code provided after the form has been submitted but I cant even seem to submit the form to even try that and im not really sure why.
      Here is the PaymentStripe module page for those wondering: https://modules.processwire.com/modules/payment-stripe/
      Any help would be greatly appreciated!
      Cleanboy