Forms and scrapbook

Permalink 1 user found helpful
I am trying to save a form to a scrapbook and use that in the template. Here is what I have tried:
1. Created a simple form - 1 question, text box, Reply - "Thanks"
2. Tested it and it updates the form page in the dashboard and sends out an email notification.
3. Saved it to the dashboard 'Default Page stuff'.
4. Added it to the template with the following:
[code]<?php
$b = Block::getByName('Default Page stuff 331');
$bv = new BlockView();
echo $bv->render($b, 'view');
?> [\code]

When I use the form this way, the page refreshes when pressing the submit button, but I get no submission. Is this possible? Or is there another way to easily put a form on many pages? Thanks.

sceva
 
sceva replied on at Permalink Reply
sceva
If no one has an answer to the question, maybe someone can point me in the direction of an easy way to put a form onto many pages of the site without adding it to each one.

Thanks.
johndorsay replied on at Permalink Reply
johndorsay
Have you tried creating an external form?
This way you could select it from the add block function.
agedman replied on at Permalink Reply
agedman
I'm sure you already thought of this, but just for the sake of completeness -- you could add the block to the page defaults for the relevant page types.
agedman replied on at Permalink Reply
agedman
I was able to repeat the issue you're seeing. Comparing the <form> tags:
When added to a page area (works):
<form enctype="multipart/form-data" id="miniSurveyView208" class="miniSurveyView" method="post" action="/NewCadbury/index.php?cID=1&amp;bID=208&amp;arHandle=Main&ccm_token=1280085922:cbca029cfc3b3bcd464f3f3fdb059cca&amp;btask=passthru&method=submit_form#1280085409">

When coded into template (broken):
<form enctype="multipart/form-data" id="miniSurveyView209" class="miniSurveyView" method="post" action="/NewCadbury/index.php?cID=1&amp;bID=209&amp;arHandle=&ccm_token=1280085922:cbca029cfc3b3bcd464f3f3fdb059cca&amp;btask=passthru&method=submit_form#1280085409">

The only difference I see is in the 'arHandle' param which is 'Main' in the first case and null in the second.

I'll take a look at the form block and see if there's a good reason the area can't be null...
sceva replied on at Permalink Reply
sceva
John - I started looking into external forms, but don't see much good info in the forums or docs...

aged - Thanks, let me know if you find something!
agedman replied on at Permalink Reply
agedman
No solution, but here's what I've tried so far:

The crux of the problem is that when the form is submitted, the function action_submit_form() in concrete/blocks/form/controller.php is not getting called. The <form> action url is mainly getting constructed by a call to the action() function in concrete/libraries/block_view.php. That function calls getBlockPassThruAction() in concrete/libraries/block.php which in turn calls _getBlockAction() in the same class. _getBlockAction() is expecting the block to have an areaHandle.

So I tried the meathead approach of giving the block an area in the template like this:
<?php
        $as2 = new Area('Sidebar2');
        $b = Block::getByName('Default Page stuff');
        $b->setBlockAreaObject($as2);
        $bv = new BlockView();
        echo $bv->render($b,'view');
?>
That resulted in a <form> tag like this:
<form enctype="multipart/form-data" id="miniSurveyView209" class="miniSurveyView" method="post" action="/NewCadbury/index.php?cID=1&amp;bID=209&amp;arHandle=Sidebar2&ccm_token=1280092334:9287666fcb4a5ce88f65514efe2bfa3f&amp;btask=passthru&method=submit_form#1280085409">
Notice that the arHandle param is set to 'Sidebar2'. But something's still wrong. The controller function action_submit_form() is still not getting called when the button is clicked. I haven't been able to figure out what code is responsible for the actual routing to the function action_submit_form().
agedman replied on at Permalink Best Answer Reply
agedman
OK, I've got a solution -- if you don't mind hacking the core a bit.

First of all, don't do what I tried in the last post -- creating an area in the template and assigning the block to it. Just leave the template like you originally had it.

Next go to line 206 in concrete\startup\process.php. The hack is just to handle the case of an empty 'arHandle' there. Change the code to this:
case 'passthru':
  if (isset($_GET['bID']) && isset($_GET['arHandle'])) {
    if (empty($_GET['arHandle'])) {
      $b = Block::getByID($_GET['bID']);
    } else {
      $a = Area::get($c, $_GET['arHandle']);
      $b = Block::getByID($_GET['bID'], $c, $a);
    }
    // basically, we hand off the current request to the block
    // which handles permissions and everything
    $p = new Permissions($b);
    if ($p->canRead()) {
      $action = $b->passThruBlock($_REQUEST['method']);
    }
  }

Maybe one of the core developers could have a look at this as a possible core modification. It seems reasonable to me that passThru calls should work from hard-coded blocks as well as blocks added to page areas.
sceva replied on at Permalink Reply
sceva
The only issue I have in changing the core is I have to remember to do it again if I update (I think this is correct?) C5 to a newer version.

I have made 3 sites with C5 and am not a php programmer, although I am comfortable with modifying code. So I really appreciate your looking into this. It would have taken me many days to figure this out.
sceva replied on at Permalink Reply
sceva
I just made the changes to process.php as you suggested and it is working perfectly.

Thanks again.
sceva replied on at Permalink Reply
sceva
I spoke too soon. It is only working if I am logged in. If I log out of the website I get no results...
agedman replied on at Permalink Reply
agedman
I should have tried that too.. my bad!

I don't see why it's necessary to have the permissions checked for a hard-coded block (i.e. empty arHandle) -- so it could be done like this instead:

case 'passthru':
  if (isset($_GET['bID']) && isset($_GET['arHandle'])) {
    // Assuming if arHandle is empty the block is hard-coded
    // so permissions check not necessary.  Security risk?
    if (empty($_GET['arHandle'])) {
      $b = Block::getByID($_GET['bID']);
      $action = $b->passThruBlock($_REQUEST['method']);    
  } else {
      $a = Area::get($c, $_GET['arHandle']);
      $b = Block::getByID($_GET['bID'], $c, $a);
      // basically, we hand off the current request to the block
      // which handles permissions and everything
      $p = new Permissions($b);
      if ($p->canRead()) {
        $action = $b->passThruBlock($_REQUEST['method']);

It works now, whether you're logged in or not. I can't say whether it's a security risk or not.
sceva replied on at Permalink Reply
sceva
I forgot to follow up - the code works! I think next time I will just put a link in the template that takes the visitor to a signup page so I will bypass the problem, and I can provide more information. I wanted to do it like this to make it quick and simple.

Thanks.
melat0nin replied on at Permalink Reply
melat0nin
Unfortunately that doesn't work in conjunction with the Ajax Forms addon :(
omfgcookies replied on at Permalink Reply
I'd rather avoid modifying the core so I have another solution. You can request the block from any page id to be used in an area, so you can make a pseudo global block like so:
<?php
    $pseudo_global_block = Page::getByID(1, "ACTIVE");
    $gArea = new Area('Pseudo Global Area');
    $gArea->display($pseudo_global_block);
?>


With this you can add the form to your root page in working condition, and it will remain updated on all other pages.
scalait replied on at Permalink Reply
scalait
I created a bug entry for this.

http://www.concrete5.org/developers/bugs/5-4-1-1/forms-in-global-sc...

Please confirm the bug, so that this issue get's fixed very soon in concrete5's core.