Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reposting pull request for postLink bootstrap modal #17

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/nbproject/
134 changes: 134 additions & 0 deletions Test/Case/View/Helper/Bs3FormHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1095,4 +1095,138 @@ public function testInputGroup() {
);
$this->assertTags($result, $expected);
}

/**
* testPostLink method
*
* @return void
*/
public function testPostLink() {
$result = $this->Form->postLink('Delete', '/posts/delete/1', array(), array('confirm' => 'Confirm?'));
$expected = array(
array('form' => array('method' => 'post', 'action' => '/posts/delete/1','name' => 'preg:/post_\w+/', 'id' => 'preg:/post_\w+/', 'style' => 'display:none;')),
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
'/form',
array('a' => array('href' => '#', 'onclick' => 'event.returnValue = false; return false;', 'data-toggle' => 'modal', 'data-target' => 'preg:/#post_\w+-modal/')),
'Delete',
'/a',
array('div' => array('class' => 'modal fade text-left','id' => 'preg:/post_\w+\-modal/','tabindex' => '-1','role' => 'dialog','aria-labelledby' => 'preg:/#post_\w+-label/','aria-hidden' => 'true')),
array('div' => array('class' => 'modal-dialog')),
array('div' => array('class' => 'modal-content')),
array('div' => array('class' => 'modal-header')),
array('button' => array('type' => 'button','class' => 'close','data-dismiss' => 'modal','aria-hidden' => 'true')),
'×',
'/button',
array('h4' => array('class' => 'modal-title','id' => 'preg:/#post_\w+-label/')),
'Confirmation Dialog',
'/h4',
'/div',
array('div' => array('class' => 'modal-body')),
'Confirm?',
'/div',
array('div' => array('class' => 'modal-footer')),
array('button' => array('type' => 'button','class' => 'btn btn-default','data-dismiss' => 'modal')),
'No',
'/button',
array('a' => array('href' => '#','class' => 'btn btn-primary','onclick' => 'preg:/document\.post_\w+\.submit\(\)\;/')),
'Yes',
'/a',
'/div',
'/div',
'/div',
'/div'
);
$this->assertTags($result, $expected);

$result = $this->Form->postLink('Delete', '/posts/delete/1', array('escape' => false), '\'Confirm\' this "deletion"?');
$expected = array(
array('form' => array('method' => 'post', 'action' => '/posts/delete/1','name' => 'preg:/post_\w+/', 'id' => 'preg:/post_\w+/', 'style' => 'display:none;')),
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
'/form',
array('a' => array('href' => '#', 'onclick' => 'event.returnValue = false; return false;', 'data-toggle' => 'modal', 'data-target' => 'preg:/#post_\w+-modal/')),
'Delete',
'/a',
array('div' => array('class' => 'modal fade text-left','id' => 'preg:/post_\w+\-modal/','tabindex' => '-1','role' => 'dialog','aria-labelledby' => 'preg:/#post_\w+-label/','aria-hidden' => 'true')),
array('div' => array('class' => 'modal-dialog')),
array('div' => array('class' => 'modal-content')),
array('div' => array('class' => 'modal-header')),
array('button' => array('type' => 'button','class' => 'close','data-dismiss' => 'modal','aria-hidden' => 'true')),
'×',
'/button',
array('h4' => array('class' => 'modal-title','id' => 'preg:/#post_\w+-label/')),
'Confirmation Dialog',
'/h4',
'/div',
array('div' => array('class' => 'modal-body')),
'\'Confirm\' this "deletion"?',
'/div',
array('div' => array('class' => 'modal-footer')),
array('button' => array('type' => 'button','class' => 'btn btn-default','data-dismiss' => 'modal')),
'No',
'/button',
array('a' => array('href' => '#','class' => 'btn btn-primary','onclick' => 'preg:/document\.post_\w+\.submit\(\)\;/')),
'Yes',
'/a',
'/div',
'/div',
'/div',
'/div'
);
$this->assertTags($result, $expected);

$result = $this->Form->postLink('Delete', '/posts/delete', array('data' => array('id' => 1)));
$this->assertContains('<input type="hidden" name="data[id]" value="1"/>', $result);

$result = $this->Form->postLink('Delete', '/posts/delete/1', array('target' => '_blank'));
$expected = array(
array('form' => array('method' => 'post', 'target' => '_blank', 'action' => '/posts/delete/1','name' => 'preg:/post_\w+/', 'id' => 'preg:/post_\w+/', 'style' => 'display:none;')),
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
'/form',
array('a' => array('href' => '#', 'onclick' => 'preg:/document\.post_\w+\.submit\(\)\; event\.returnValue \= false\; return false\;/')),
'Delete',
'/a',
);
$this->assertTags($result, $expected);

$result = $this->Form->postLink(
'Title',
array('controller' => 'items', 'action' => 'delete', 10),
array('class' => 'btn btn-danger', 'escape' => false),
array('text' => 'Confirm thing', 'title' => 'Thing Title')
);
$expected = array(
array('form' => array('method' => 'post', 'action' => '/items/delete/10','name' => 'preg:/post_\w+/', 'id' => 'preg:/post_\w+/', 'style' => 'display:none;')),
array('input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST')),
'/form',
array('a' => array('href' => '#', 'class' => 'btn btn-danger','onclick' => 'event.returnValue = false; return false;', 'data-toggle' => 'modal', 'data-target' => 'preg:/#post_\w+-modal/')),
'Title',
'/a',
array('div' => array('class' => 'modal fade text-left','id' => 'preg:/post_\w+\-modal/','tabindex' => '-1','role' => 'dialog','aria-labelledby' => 'preg:/#post_\w+-label/','aria-hidden' => 'true')),
array('div' => array('class' => 'modal-dialog')),
array('div' => array('class' => 'modal-content')),
array('div' => array('class' => 'modal-header')),
array('button' => array('type' => 'button','class' => 'close','data-dismiss' => 'modal','aria-hidden' => 'true')),
'&times;',
'/button',
array('h4' => array('class' => 'modal-title','id' => 'preg:/#post_\w+-label/')),
'Thing Title',
'/h4',
'/div',
array('div' => array('class' => 'modal-body')),
'Confirm thing',
'/div',
array('div' => array('class' => 'modal-footer')),
array('button' => array('type' => 'button','class' => 'btn btn-default','data-dismiss' => 'modal')),
'No',
'/button',
array('a' => array('href' => '#','class' => 'btn btn-primary','onclick' => 'preg:/document\.post_\w+\.submit\(\)\;/')),
'Yes',
'/a',
'/div',
'/div',
'/div',
'/div'
);
$this->assertTags($result, $expected);
}
}
125 changes: 125 additions & 0 deletions View/Helper/Bs3FormHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,131 @@ protected function _detectFormStyle($options) {

return $options;
}

/**
* Creates an HTML link, but access the URL using the method you specify (defaults to POST).
* Requires javascript to be enabled in browser.
*
* This method creates a `<form>` element. So do not use this method inside an existing form.
* Instead you should add a submit button using FormHelper::submit()
*
* ### Options:
*
* - `data` - Array with key/value to pass in input hidden
* - `method` - Request method to use. Set to 'delete' to simulate HTTP/1.1 DELETE request. Defaults to 'post'.
* - `confirm` - Can be used instead of $confirmMessage.
* - `inline` - Whether or not the associated form tag should be output inline.
* Set to false to have the form tag appended to the 'postLink' view block.
* Defaults to true.
* - `block` - Choose a custom block to append the form tag to. Using this option
* will override the inline option.
* - Other options are the same of HtmlHelper::link() method.
* - The option `onclick` will be replaced.
*
* @param string $title The content to be wrapped by <a> tags.
* @param string|array $url Cake-relative URL or array of URL parameters, or external URL (starts with http://)
* @param array $options Array of HTML attributes.
* @param array $confirmMessage Options for modal dialog (text and title).
* @return string An `<a />` element.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::postLink
*/
public function postLink($title, $url = null, $options = array(), $confirmMessage = array()) {
$options = (array) $options + array('inline' => true, 'block' => null);
if (!$options['inline'] && empty($options['block'])) {
$options['block'] = __FUNCTION__;
}
unset($options['inline']);

$requestMethod = 'POST';
if (!empty($options['method'])) {
$requestMethod = strtoupper($options['method']);
unset($options['method']);
}

if(is_string($confirmMessage)) {
$confirmMessage = array('text' => $confirmMessage);
}
if (!empty($confirmMessage['confirm'])) {
$confirmMessage['text'] = $confirmMessage['confirm'];
unset($confirmMessage['confirm']);
}

$formName = str_replace('.', '', uniqid('post_', true));
$formUrl = $this->url($url);
$formOptions = array(
'name' => $formName,
'id' => $formName,
'style' => 'display:none;',
'method' => 'post',
);
if (isset($options['target'])) {
$formOptions['target'] = $options['target'];
unset($options['target']);
}

$this->_lastAction($url);

$out = $this->Html->useTag('form', $formUrl, $formOptions);
$out .= $this->Html->useTag('hidden', '_method', array(
'value' => $requestMethod
));
$out .= $this->_csrfField();

$fields = array();
if (isset($options['data']) && is_array($options['data'])) {
foreach (Hash::flatten($options['data']) as $key => $value) {
$fields[$key] = $value;
$out .= $this->hidden($key, array('value' => $value, 'id' => false));
}
unset($options['data']);
}
$out .= $this->secure($fields);
$out .= $this->Html->useTag('formend');

if ($options['block']) {
$this->_View->append($options['block'], $out);
$out = '';
}
unset($options['block']);

$url = '#';
$onClick = 'document.' . $formName . '.submit();';
$append = '';
$options['onclick'] = '';

if (!empty($confirmMessage['text'])) {
if (empty($confirmMessage['title']))
$confirmMessage['title'] = __('Confirmation Dialog');
$options['data-toggle'] = 'modal';
$options['data-target'] = "#$formName-modal";
$append .= "<div class=\"modal fade text-left\" id=\"$formName-modal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"#$formName-label\" aria-hidden=\"true\">";
$append .= '<div class="modal-dialog">';
$append .= '<div class="modal-content">';

$append .= '<div class="modal-header">';
$append .= '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>';
$append .= "<h4 class=\"modal-title\" id=\"#$formName-label\">" . $confirmMessage['title'] . "</h4>";
$append .= '</div>';

$append .= '<div class="modal-body">' . $confirmMessage['text'] . '</div>';

$append .= '<div class="modal-footer">';
$append .= '<button type="button" class="btn btn-default" data-dismiss="modal">' . __('No') . '</button>';
$append .= $this->Html->link(__('Yes'), '#', array('class' => 'btn btn-primary', 'onclick' => $onClick));
$append .= '</div>';

$append .= '</div>';
$append .= '</div>';
$append .= '</div>';
} else {
$options['onclick'] = $onClick . ' ';
}
$options['onclick'] .= 'event.returnValue = false; return false;';

$out .= $this->Html->link($title, $url, $options) . $append;
return $out;
}


/**
* Overrides parent method to remove undesirable properties when dealing with bare inputs
Expand Down