Jump to content

module intercept ajax call


Manol
 Share

Recommended Posts

Hello.

    I would like to make an ajax call and get some data back.

    The way I use to do it is, make a call from javascript to a url that would be a pw page that uses the template that would return the data, like this:

Define a page under /web-service/get-page that uses getpage.php template

Javascript (angularjs)

            $http({url: '/web-service/get-page/', method: "POST", data: { pageId: pageId }} )
                .success(function(response){
                    deferred.resolve(response);
            });

PHP template ( getpage.php )

<?php 

 
	/**
	 * datos enviados mediante JSON
	 * @return [type] [description]
	 */
	function getPost(){
		$request = file_get_contents('php://input');
		return json_decode($request,true);
	}
	$getPost = getPost();
	$pageId = $getPost['pageId'];


		$pagina = wire('pages')->get($pageId);

		$array = array(); 

        // fields to be avoided
        $avoid = array("FieldtypeFieldsetOpen", "FieldtypeFieldsetClose","FieldtypeFieldsetTabOpen","FieldtypeFieldsetTabClose");

		foreach($pagina->fields as $field) {
			if (!in_array($field->type, $avoid)) {
				// si el campo no esta vacio
				if( htmlentities($pagina->get($field->name)) )
					$array[$field->name] = htmlentities($pagina->get($field->name));
			}
		}
		echo json_encode($array);

?>

My question is: 

   How can I avoid creating a template and defining a page that uses it?

   I wish to intercept the ajax call from a module and return the data from that module without creating templates and pages.

   Is that possible?

Thank you.

Link to comment
Share on other sites

How can I avoid creating a template and defining a page that uses it?

See options #1 (post to script outside PW directories) and 3 (post to same page) here: https://processwire.com/talk/topic/407-processing-contact-forms/?p=3106

 I wish to intercept the ajax call from a module and return the data from that module without creating templates and pages.

If you go with option #3 you can intercept right within same page, call your module, do your stuff and return the data

Btw, in case you were not aware...https://processwire.com/talk/topic/225-how-to-work-with-ajax-driven-content-in-processwire/

if($config->ajax) {
    // page was requested from ajax
    // can optionally include external php scripts
    // call your module and do stuff
}
Edited by kongondo
  • Like 5
Link to comment
Share on other sites

Probably what I'm asking for is simpler than what I've exposed in the lines above.

Just need to catch an ajax call from a pw module and return some data back. .The ajax call can come from a mobile device or other website located in a different server.

Thank you

Link to comment
Share on other sites

You can with a autoload module in the init() method, use the wire("config")->ajax and maybe check for post values etc and return output then exit()

if(wire("config")->ajax){
    if(wire("input")->post->something){
        echo "hello";
        exit;
    }

}
  • Like 2
Link to comment
Share on other sites

Still not getting there.

1.- Javascript (angularjs)

$http.post('http://mywebpage/user/', {name:'manol'}).
  success(function(data) {
  	console.log(data);
  }).
  error(function(data) {
  	console.log(data);
  });

2.- and I wish to get json data back

# PW MODULE       

  $array = array();
  $array['name'] = wire("user")->name;
  $array['language'] = wire("user")->language->title;
  $event->return = json_encode($array);

3.- Which hook or whatever should I use?, http://mywebpage/user/ doesn't correspond to any template.

Link to comment
Share on other sites

You can create a web-accessible php file anywhere on your server and bootstrap ProcessWire from there, without creating a page as far as PW is concerned. An example:

<?php
/* This file is nowhere in particular and not a template or anything. */

require_once("./cms/processwire/index.php"); 

$name = $wire->input->post->name;

if ($wire->input->post->name == 'manol') {
	$m = $wire->modules->get('CoolModule')
	die($m->welcome($name));
}

die('Hello anyway.');

I have no experience with this, so I can’t tell you about potential drawbacks, if there are any.

Another way to avoid creating a “page” would be to allow urlSegments for your root page and handle the input there. It would look like any other page but it won’t disturb anyone’s aesthetic sensibilities in the admin backend.

  • Like 1
Link to comment
Share on other sites

(On mobile, haven’t tested) Maybe try hooking into ___PageNotFound() in ProcessPageView. It gives you the requested URL, so you can check if that’s what your module expects and process it. That way your module could remain self-contained. If $input isn’t populated at that point, you should always be able to go through $_POST.

  • Like 1
Link to comment
Share on other sites

I just tested it and I think this is what you want. Here’s a complete demo module:

class NotFoundIntercept extends Wire implements Module {
    public static function getModuleInfo() {
        return array(
                    'title' => 'Not Found Intercept ',
                    'version' => 001,
                    'summary' => 'Hooks into pageNotFound so you can handle URLs that don’t belong to any page.',
                    'href' => 'https://processwire.com/talk/topic/8510-module-intercept-ajax-call/',
                    'autoload' => true,
                    );
    }

    public function init() {
        wire()->addHook('ProcessPageView::pageNotFound', $this, 'intercept404');
    }

    protected function intercept404($event) {

        $url = $event->arguments('url');

        if ($url != '/my_pseudo_page/')
            return; //Let pageNotFound() handle it

        header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK', true, 200);

        $name = $_GET['name'];

        if ($name)
            die("Hola $name! Como estas?");
        else
            die("Sup, guest?");
    }
}

Now you can open ejemplo.es/my_pseudo_page/?name=Manol and – provided that page doesn’t exist in PW – it will greet you. Of course, if the front page has urlSegments enabled, it will just accept that instead, and your module won’t be triggered...

  • Like 3
Link to comment
Share on other sites

Fantastic Jan you're my star, it was a really good idea, now:

PwAngular.module

class PwAngular extends WireData implements Module, ConfigurableModule {
...
	public function init() {

        $this->addHook('ProcessPageView::pageNotFound', $this, 'webService');
...

	public function webService($event) {

		// Check if asking for a web service
        $url = $event->arguments('url');
        if ($url != '/web-service/') return; //Let pageNotFound() handle it
		header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK', true, 200);

		// Get post Data
		$request = file_get_contents('php://input');
		$getPost = json_decode($request,true);
		$action = $getPost['action'];

		switch ($action) {
		    case "getPage":							
			$pageId = $getPost['pageId'];
			$event->return =$this->get_Page($pageId);
		        break;		

		}

	}

	protected function get_Page($pageId) {
	

		$pagina = wire('pages')->get($pageId);

		$array = array(); 

        // fields to be avoided
        $avoid = array("FieldtypeFieldsetOpen", "FieldtypeFieldsetClose","FieldtypeFieldsetTabOpen","FieldtypeFieldsetTabClose");

		$array['id'] = $pagina->id;
		
		foreach($pagina->fields as $field) {
			if (!in_array($field->type, $avoid)) {
				// si el campo no esta vacio
				if( htmlspecialchars($pagina->get($field->name)) )
					if($field->type == "FieldtypePage"){
							$buscar = htmlspecialchars($pagina->get($field->name));
							$paginas = $pages->get($buscar); 
							$array[$field->name] = $paginas->title;
						
					}
				else {
					// if textarea do not strip html tags
					if($field->type == "FieldtypeTextarea" || $field->type == "FieldtypeTextareaLanguage" ){$array[$field->name] = $pagina->get($field->name);}
					else {$array[$field->name] = htmlspecialchars($pagina->get($field->name));}					
				}
			}
		}
		return json_encode($array);
	}



my.js

		$http.post('http://ip/web-service/', {action: 'getPage', pageId: 1046 })
		.success(function(data) {
		  	console.debug("success",data);
		})

and BUMP! working.

Link to comment
Share on other sites

You don't really have to hook page not found... just check for ajax and a POST var in the init() of a autload module as I wrote before

...
public function init(){

   if(!$this->config->ajax) return;

   if($this->input->webservice){
       $id = $this->input->id;
       echo json_encode(array("status" => "ok", "data" => $id));
       exit;
   }

}

and you would call a url like your root 

http://domain.com/?mywebservice&id=10

or using post works with same code

  • Like 3
Link to comment
Share on other sites

Hi Soma.

    I've tried your way like you posted yesterday and today but I'm getting back the whole page maybe because my call is

$http.post('http://ip/web-service/', {action: 'getPage', pageId: 1046 })
.success(function(data) {
    console.debug("page",data);
})

  As Jan pointed

$this->addHook('ProcessPageView::pageNotFound', $this, 'webService');

is working for me, maybe is not the best way but it works as expected.

Thank you

Link to comment
Share on other sites

It works.

You might haven't configured all correct.

This in the init() method

public function init() {
    if($this->config->ajax && $this->input->it == "webservice/"){
        if(!$this->input->action) return;
        $out = array(
            "it" => $this->input->it,
            "action" => $this->input->action,
            "pageid" => $this->input->pageid,
            );
        header('Content-type: application/json');
        echo json_encode($out);
        exit();
    }

}

and then this jquery ajax call work just fine

<script>
$(function(){
    $.ajax({url:'/webservice/', data: {action: 'getPage', pageid: 1001}, method: 'post'}).success(function(data){
        console.log("page", data);
    });

}); 

Nothing wrong with the PageNotFound as far as I can tell I'm using both approaches :D

  • Like 3
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...