Execute PHP Code via Ajax Call in drupal module - php

I was trying to convert this into a Drupal module so that I can check PHP code instantly on my site for debugging purposes. I saw this Firefox add on which allows you to execute PHP on the fly but admin log in is necessary, so far I did everything , have one form and set up ajax calls , but if I pass a string like:
preg_match($pat,$str,$matches);
print_r($matches);
How to execute this in backend?
EDIT
To load the form:
$items['localphp'] = array(
'page callback' => 'executePHP',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
function executePHP(){
$output = drupal_get_form('executePHP_form');
return $output;
}
Ajax callback function:
$items['runPHP'] = array(
'page callback' => 'getResult',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
function getResult(){
$code = $_POST['code'];
//I need help here how to execute $code i.e the php code and return back result
echo $code;
}
JS function
function executePHP(baseurl){
var code = $("#edit-code").val();
$.ajax({
type : "POST",
url : baseurl+'runPHP',
data : 'code='+code,
async : true,
cache : false,
success : function (res) {
$("#edit-result").html(res);
},
error : function (res) {
alert("error");
}
});
return false;
}

FYI, the Devel module has a feature that allows admins to run custom PHP code from their page. The Devel module has a block with a ton of features useful for debugging.
For a custom module, without seeing any of your other code, I can tell you what I have done to achieve AJAX in a Drupal module:
In JavaScript make an AJAX request to a url on your site. Add a menu item with the specified path inside of hook_menu() as 'type' => MENU_CALLBACK that points to a function in your module. This function should do all the processing you need, then return the results to JavaScript to do what you want with it there.

Related

Yii2 CKeditor not initialized when requested via ajax

I am trying to add a from with a CKeditor widget imbedded via an AJAX request. The request itself works fine and returns the general partial view as I want it. Except for the Ckeditor widget, a normal textbox is return instead.
When the item is added to the group and the page is reloaded, the same partialView is being rendered (in a foreach with all group-items) and this time the CKeditor is nicely in place.
Posted my controller, initialization of the CKeditor and Scipt with AJAX request below. (The CKeditor is inlcuded in the _ContentItemHtml view)
I have taken a look at this, but I cannot call any CKeditor functions from JS since it is loaded as a widget.
Controller Action
public function actionCreateHtml($contentitemgroupid)
{
$model = new ContentItemHtml();
if (isset(Yii::$app->request->post()['ContentItemHtml'])) {
$item = Yii::$app->request->post()['ContentItemHtml'];
$model->contentitemgroupid = $contentitemgroupid;
$model->title = $item['title'];
$model->body = $item['body'];
$model->save();
// return $this->redirect(['edit', 'id' => $model->contentitemgroupid]);
}
else
return $this->renderPartial('_ContentItemHtml', ['model' => $model]);
}
Active form in view:
echo $form->field($model, 'body')->widget(CKEditor::className(), [
'preset' => 'custom',
'clientOptions' => [
'height' => 200,
'toolbarGroups' => [
['name' => 'basicstyles', 'groups' => ['basicstyles', 'cleanup']],
['name' => 'paragraph', 'groups' => ['templates', 'list']],
['name' => 'mode']]
]])->label(false);
Script.js
$('#addNewContentItem').on('click', function (e) {
e.preventDefault();
var url = 'create-' + $('#itemSelector').val().toLowerCase() + '?contentitemgroupid=' + $('#itemSelector').attr('contentitemgroupid');
$.ajax({
type: 'POST',
url: url,
cache: false,
success: function(res) {
$('.contentItemsManager').append('<div class="ContentItemContainer row">' + res + '</div>');
AddSaveEventListener();
AddSaveMediafileEventListener();
AddRemoveEventListener();
}
});
});
Use renderAjax instead of renderPartial. From the docs:
[renderAjax] Renders a view in response to an AJAX request.
This method is similar to renderPartial() except that it will inject into the rendering result with JS/CSS scripts and files which are registered with the view. For this reason, you should use this method instead of renderPartial() to render a view to respond to an AJAX request.

ajax not posting, always a blank post

I'm going nuts with this. I am requesting ajax call in several places, and none of these ajax calls are working correctly lately. Today I decided to start fresh on a new section with ajax call. It's the same thing with all the other ones. It's been days that ajax data is not posting to controller - always blank.
Here is one of them. I am trying to allow users to vote up/down on click on CButtonColumn {up}{down}. This view grid "_vote.php" is generated through renderPartial using TbTabs. On renderpartial I did set to true on the last param.
Okay, next the grid. Here it is:
<?php $this->widget('bootstrap.widgets.TbGridView', array(
'type'=>'condensed',
'id'=>'vote',
'dataProvider'=>$dataProvider,
'template'=>"{items}",
'ajaxUpdate'=>true,
'columns'=>array(
array(
'class'=>'CButtonColumn',
'template' => '{up} {down}',
'buttons' => array(
'up' => array(
'label'=>'<i class="fa fa-thumbs-up"></i>',
'imageUrl'=>false,
'url'=>'Yii::app()->createUrl("prod/votecommentup", array("id"=>$data->primaryKey))',
'click'=>' function(){
$.fn.yiiGridView.update("vote", {
type:"POST",
url:$(this).attr("href"),
success:function(data) {
$.fn.yiiGridView.update(vote);
}
}',
),
'down'=> array(
'label'=>'<i class="fa fa-thumbs-down"></i>',
'imageUrl'=>false,
'url'=>'Yii::app()->createUrl("prod/votecommentdown", array("id"=>$data->primaryKey))',
'click'=>' function(){
$.fn.yiiGridView.update("vote", {
type:"POST",
url:$(this).attr("href"),
success:function(data) {
$.fn.yiiGridView.update(vote);
}
}',
),
),
),
),
)); ?>
Okay... next, the url "prod/votecommentup", which is the nearly identical as votecommentdown. Here it is:
public function actionVoteCommentUp($id){
$model = $this->loadModel($id);
if(isset($_POST['VoteThis']))
{
$model->attributes=$_POST['VoteThis'];
$model->prototype_review_id = $id;
$model->user_id = Yii::app()->user->user_id;
$model->vote = "Y";
echo CJSON::encode(array('status'=>'saved'));
}echo CJSON::encode(array('status'=>'not post')); //always give me a no post
}
I recommend testing your calls through something like Postman App for chrome. This will give you the ability to debug your API/AJAX calls independent of your view. Once you have ensured the API/AJAX is functioning correctly, you can then integrate it into the view. This allows you to decouple the debugging process and hopefully make things more transparent as to what is functional and what is not.

Example of calling CakePHP function from jQuery

I am new to CakePHP and I am trying to figure you how to make an asynchronous call from a CakePHP view to a function in the controller. I would like the controller function to return a string and have the view display this string. I would also like to to do this without using helpers. I have been trying to find examples on the web but have been unable to do so. Does anyone have a simple example? I am also using jQuery.
Thanks
CakePHP has a built-in JS Helper to help write aJax functions. The only catch is to include jquery in your head or cake will throw jQuery errors. Heres more information http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html
Your Form:
<?php
echo $this->Form->create('User', array('default'=>false, 'id'=>'YourForm'));
echo $this->Form->input('username');
echo $this->Form->submit('Check Username');
echo $this->Form->end();
?>
The Ajax Function: ('update'=>'#na') is the id of the element you want to update in your view.
<?php
$data = $this->Js->get('#YourForm')->serializeForm(array('isForm' => true, 'inline' => true));
$this->Js->get('#YourForm')->event(
'submit',
$this->Js->request(
array('action' => 'checkUsername', 'controller' => 'user'),
array(
'update' => '#na',
'data' => $data,
'async' => true,
'dataExpression'=>true,
'method' => 'POST'
)
)
);
echo $this->Js->writeBuffer();
?>
The Function in User Controller
function checkUsername(){
$this->autoRender = false;
$username = $this->User->find('first', array('conditions'=>array('User.username'=>$this->request->data['User']['username'])));
if ( $username == true )
echo 'Username is taken';
else
echo 'Username is not taken';
}
EDIT**
*If you want to use jQuery to do this and not the CakePHP Helper you can use aJax to call an action, then update your element like below*
$('#element').on('click', function() {
$.ajax({
url : '/controller/action',
type: 'POST',
success : function(response){
$('#elementToUpdate').html(response);
}
});
}
});
In your Controller Action you can return the "string" you would like to show in the view
function action(){
$string = 'Show this in the view';
return $string;
}
The above example would be executed when you "Click" an element with an id of "element" then upon "Success" would change element with id of "elementToUpdate" to the String "Show this in the view" Since it was returned from the controller action.

Cakephp Js helper

I am working with Js helper to help me replace the contents of a "div" in my index.ctp with contents of another file changeto.ctp .
This application has a few check boxes with corresponding images. When I select a checkbox, the setting is stored in the database and the corresponding image is to be displayed. Similarly when unchecked, it is to be removed from the database and the image should disappear.
I am using the Js helper for this :
my changeto.ctp is subset of my index.ctp and has access to same variables and loads without any problems (except that any click/change events are just not responded to. The names of the Ids of the checkboxes are exactly same).
My index file contains the following Js code at the bottom of all Html:
$this->Js->get($change_checkbox1 )->event('click',
$this->Js->request(array(
'controller'=>'testing',
'action'=>'changeto'
), array(
'update'=>'#changeDiv',
'async' => true,
'method' => 'post',
'dataExpression'=>true,
'data'=> $this->Js->serializeForm(array(
'isForm' => false,
'inline' => true
))
))
);
This is generating the following Jquery/javascript
$(document).ready(function () {$("#ck0_1_8").bind("click", function (event) {$.ajax({async:true, data:$("#ck0_1_8").closest("form").serialize(), dataType:"html", success:function (data, textStatus) {$("#changeDiv").html(data);}, type:"post", url:"\/mytest-site\/options\/testing"});
return false;});
}
My controller has a function called
changeto()
{
$this->layout = 'ajax';
}
the first time I click on this the checkbox this works without any problem. However any subsequent clicks don't work. The javascript is not even being called.
My questions are :
Any ideas ?
Will it help if I somehow ask cakephp to use on() / live() insead of bind() .If yes how ?
Thanks!!
Solved this by editing a cakephp core file:
lib/Cake/View/Helper/JqueryEngineHelper.php
line 184:
change
return sprintf('%s.bind("%s", %s);', $this->selection, $type, $callback);
to
return sprintf('%s.live("%s", %s);', $this->selection, $type, $callback);
cake version 2.2.2
You have to use on instead of bind as they suggest in this question .live() vs .bind()
That's what I did was create my own Helper on View/Helper add the following method:
public function onEvent($selector, $type, $callback, $options = array()) {
$defaults = array('wrap' => true, 'stop' => true);
$options = array_merge($defaults, $options);
$function = 'function (event) {%s}';
if ($options['wrap'] && $options['stop']) {
$callback .= "\nreturn false;";
}
if ($options['wrap']) {
$callback = sprintf($function, $callback);
}
return sprintf('$(document).on("%s", "%s", %s);', $type, $selector, $callback);
}
And use that method from my views:
echo $this->MyJs->onEvent('#creditcards', 'change', $eventCode, array('stop' => false));

Drupal module jQuery PHP script location issue

I am developing a module which has a jQuery script with some AJAX code. The ajax code calls a php script located in the same location as the jQuery script.
My problem is, AJAX appends the domain name in front of the PHP script name and of course, my script does not exist at that location and so the process breaks.
The AJAX code is as follows:
$(document).ready(
function(){
$.ajax({
url: "/testscript.core.php",
asych: false,
success: function($data){
$('textarea#edit-simplechat-messages').text( $data );
}
});
}
);
And the following is the link that shows up in firebug:
http://testsite.co.uk/testscript.core.php
Again, the jQuery script and the php script are in the same directory.
I thought the forward slash before my php script name would eliminate the domain name but it did not work.
Use
Drupal.settings.basePath
url: Drupal.settings.basePath+'your file path',
This link might be useful
http://www.akchauhan.com/how-know-base-path-of-drupal-in-javascript/
EDIT :
Or you can use this approach if you are creating your own custom module then follow these steps
1] First create your module, Here my module name is "mymodule", So i created a file name mymodule.module
<?php
function mymodule_init() {
drupal_add_js(drupal_get_path('module', 'mymodule') . '/mymodule.js');
// this call my js file when module is initialized.
}
function mymodule_menu(){
$items = array();
$items['mypath'] = array(
'title' => t('To get series of the selected brand'),
'page callback' => 'mymodule_page',
'page arguments' => array(1),
// get test_parameter from url, which is your first argument
//http://domain.com/mypath/test_parameter
// here mypath is arg(0), and test_parameter is arg(1)
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
return $items;
}
function mymodule_page($termID){
return drupal_json(array('message'=> $itemID));
}
2] Secondly create js file with the same name so name it mymodule.js under the same module file.
// $Id$
Drupal.behaviors.mymodule = function (context) {
var $basepath = Drupal.settings.basePath;
$('selector').change(function(e){
$.ajax({
type: 'POST',
url: $basepath+'mypath/test_parameter',
// test_parameter :value you are sending to you module.
dataType:'json',
cache:false,
beforeSend:function(){
},
success:function(data){
alert(data.message);
},
complete:function(){
},
error:function(xhr, status, error){
}
});
});
}
Notice in js file i have used mypath. your js file will call this path which is defined in the hook_menu().
the way it is now it looks like your problem is the slash before the file name.. that means "domain web root"

Categories