Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID

Saasy vs form vs ??

edited April 2013 in Framework

I'm building a site that has lots of user interaction and user management requirements. Users will be able to upload photos, create reviews, comment on other reviews, etc. It looks like a lot of the functionality you've built into the saasy app would be relevant, but it's not software as a service, just a plain old website.

I started building the "create your account" form using the form app, but the specs indicate a profile photo, which the form app, I think, doesn't handle yet. Then I looked at the saasy readme and the create account mockup there is very similar to the one I'm building.

Any advice for me? Not sure if I should start from saasy, from form, or from some other app or library...


  • I would look at extending the built-in user app in the same way this post describes extending the blog app:

    The override feature of both apps was intended for people to override with their own functionality, such as custom user details pages or signup forms that require additional fields.

    Saasy sounds like it might be overkill, although it doesn't hurt to try it out and see how close it comes to what you need.

  • Thanks, I'll try extending the user app. The thing that gives me pause about saasy is the private subdomain aspect.

  • edited April 2013

    OK, I set up my custom signup form.

    To add a drag-and-droppable profile image, would the best way be to copy, paste, and tweak the code from apps/filemanager/views/index.html?

  • That's probably easiest. The code is mainly here:

    Other than that it's pretty much just calling $page->add_script ('/apps/filemanager/js/jquery.filedrop.js'); and adding a <div id="filemanager-dropzone"></div> to the page.

  • Thanks. I think there's one too many }s in that block. Should I include the corresponding $.filemanager_init = function (options) { at the top?

  • Ah yes, you're right. You should only need the filedrop stuff I believe, although you'll need to modify some of the references to the filemanager stuff outside of it.

  • Is there a cool filedrop set_value: #image_id function like there is for filebrowser?

  • I'm afraid not, although it is integrated into the filebrowser (but that's meant for admins only).

  • Hmm. What's the best way to update the profile image after the drag and drop? Just wait until they post the form?

  • I believe filedrop wants to upload the image right away, so you may have to implement a separate case for that in addition to the fallback for plain old uploads, but you'd have to look at the filedrop docs to be sure.

  • Looks like something like this might work:

    I'll try it and let you know.

  • edited April 2013

    OK, I have the front-end working, at least in chromium.

    HTML (simplified):

    <div id="filemanager-dropzone">
        <label>{"Profile photo"}<br />
        <img id="profile-preview" src="{{photo}}" /><br />
        <input type="file" name="profile_photo" id="profile-photo" />
        <input type="hidden" name="profile_file" id="profile-file" />

    Javascript (excerpts):

        uploadStarted: function (i, file, len) {
            // Set the preview
        uploadFinished: function (i, file, res, time) {
                document.getElementById("profile-file").value =;
                document.getElementById("profile-photo").style.visibility = "hidden";
    function createImage(file) {
        var image = document.getElementById("profile-preview");
        var reader = new FileReader();
        reader.onload = function(e){
            // holds the DataURL which
            // can be used as a source of the image:
            image.src =;
        // Reading the file as a DataURL. When finished,
        // this will trigger the onload function above:

    On the back end I'm thinking that if profile_file is set I'll use that, otherwise profile_photo.

  • Re: the blog post : I found that I also needed to add myapp/forms/signup.php

  • How to kill your site: change user/update in app.user.conf.php but don't actually create the new handler...

    (No matter how much memory you give it...)

    Allowed memory size of 2365587456 bytes exhausted (tried to allocate 16384 bytes) in /path/to/lib/Controller.php on line 443
  • Actually, I had created it but not removed the $res = $this->override ('user/update'); lines.

  • Ah yes, infinite loop! Just added a fix to check for that now.

  • Any reason not to check for a custom handler override in user/delete? I want to delete the user's uploaded images when the account is deleted.

  • Can I use custom fields when they're creating the account? I guess not, because admin/util/extended requires admin.

  • For public-facing handlers, you'll need to implement your own inputs that map to your extended fields I'm afraid.

    And there is a hook you can use with the user/delete handler to add additional post-delete actions like erasing associated data.

  • OK, I switched to custom fields and it's working well with my handlers.

    In apps/admin/views/util/extended.html, I was wondering, would you be averse to showing a thumbnail of the image if the field is an image? Something like this on line 68?

            {% if file_exists($data->field->value) && getimagesize($data->field->value) %}<img src="/{{field->value|quotes}}" style="max-height: 100px; max-width: 100px;" /><br />{% endif %}

    I will check out the post-delete hook, thanks.

  • Forgot to mention, I get a javascript error when I click the "Browse" button next to the image field:

      Error: TypeError: $.filebrowser is not a function
      Source File: /user/edit?id=1
      Line: 81
  • Re: post-delete hook, I'm confuddled. apps/user/handlers/delete.php executes $u->remove before it calls $this->hook ('user/delete', $_GET)

    How can my handler determine the image to delete if the user record is already gone from the db?

  • First, I love the image preview! I tweaked it a bit to update the preview when a new file is selected, and I just pushed it to github.

    And I think I found a fix for the $.filebrowser is not a function error, so let me know if the latest commit fixes it for you as well.

    Also in the master branch, there's a small change to how the delete hooks are called so that they pass all the data of the deleted item to your hook handler's $data array. Let me know how that works.

  • Re: image preview -- glad you like it! I'm wondering -- I had a "/" before the path because I'm storing the value returned by Image::Resize, which doesn't return the initial "/". Without it, my image doesn't show because we're at /user/edit

    I think this might be part of a larger question about image best practices, which you started to address earlier. For instance, until yesterday I had assumed that Image::Resize resized the image sent to it instead of creating a copy of it, but I'm not sure that I need to keep the original image, since client uploads from their fancy digital cameras tend to be huge...

    $.filebrowser is not a function error is fixed and delete tweak works -- thanks!

  • Generally, I store the leading / when I reference a file link, since I just store the returned value from the $.filebrowser dialog. Probably easiest to switch to doing that too, for compatibility with the helpers.

    Image::resize stores a separate version in case you want to resize for a variety of sizes, and to avoid non-destructive edits. I haven't had a chance to prototype any of the new image idea yet, but they'll probably default to non-destructive too with a keep_original=false option to enable automatic clean-up.

  • Re: leading /: would it make sense for Image::resize to return that, too, so that it's compatible with $.filebrowser?

  • I guess now we also have to think about compatibility, since Image::resize is used in a bunch of places already, but I haven't really found it to be an issue. It's been easy enough to just do '/' . Image::resize ($obj->photo) in PHP or src="/{{photo|Image::resize}}" in templates.

    I think once the new image stuff is implemented it will provide a nice wrapper around the little stuff like this so there's a more "standard" way to go about it.

  • Re: adding a slash in templates -- I did, but someone took it out! ;) (Just messing with you -- I'll add it when I save the path.)

    Speaking of saving paths to Image::Resized images: is it safe to do that? In other words, do images in /cache/thumbs/ stick around, or is there a cache cleanup that happens periodically?

  • Haha touché ;P

    I've been thinking about the cache folder situation a bit, since people may assume it to be for ephemeral data only, which means a simple rm -Rf cache/* shouldn't break anything on the site. There isn't any automatic cleanup at least, since most cached elements automatically regenerate if the modification time of the original file is changed or the cache timeout has passed.

    When I first wrote Image::resize, I was storing the original file path and just using it in the template via {{photo|Image::resize}} which would never break since the clobbered thumbnail would just be regenerated.

    A partial solution might be to add a ./elefant clear-cache command that would do more of a rm cache/*.php cache/datastore/* and maybe add a --full switch to convert it to a full rm -Rf cache/*.

    That combined with the new Image API hopefully making it easier to automatically move files to S3-style services ought to ensure resized images are fairly well guarded.

Sign In or Register to comment.