Modx REST APi questions

like this ?
public $allowedMethods = array(‘GET’);
public function beforeDelete() { return false; }
public $classKey = ‘modResource’;

if yes then its not working. still i can post from postman.

and yeah! the image url is solved now. however hard coded version. Because I dont know how to do it from system settings. :smiley:

Where did you read the instruction for inserting allowed methods? Sorry I don’t have access to a MODX site to check at the moment.

You should be able to return false on any of the other methods just as you did with delete ie:

public function beforePost() { return false; }
public function beforePut() { return false; }
public function beforeDelete() { return false; }
1 Like

Check marks post here few posts above. He suggested 3 methods for restricting.
Let me try yours again.

This works. Now no one can post. Just me. :smiley:

One thing im still confused with is that I am calling https://website.com/rest/resources?parent=6
where 6 is my id for blog container so with this call im getting children. But how to get only one children from here ? Like calling https://website.com/rest/resources?parent=6/13 where 13 is child post of blog container id 6. This call not returning child id 13.

This was the code you and @markh helped with -

 protected function prepareListQueryBeforeCount(xPDOQuery $c) {
            if ($parent = (int)$this->getProperty('parent')) {
                $c->where(['parent' => $parent]);
            }

Not sure what you’re trying to do exactly but usually you would do the first call with ?parent=6 which returns the child resources and then place that information into a component on your front end application, using the id of each resource as the unique identifier. Then if your user clicks on a child resource you make another API call passing the id of that resource along to fetch any data related to that one resource.

wouldn’t just https://website.com/rest/resources/13 do it?

yes but I want from container/folder. Like blog is a container/parent and its posts are child pages/posts.

Yes it returns child resources by calling ?parent=6 but I want to open one child from this parent. like ?parent=6/3 where 3 is child post/page.

So that when user click on single item from list of posts, they can open full page. I hope you understand.

I do but this is something you handle in the front end of your application as I said :slight_smile:

To reiterate first you do a call to &parents=6 to return all the child resources belonging to the parent and then map the object to output a list of links using the id as a unique identifer for each item. Then when a user clicks on a link you make another api call passing along the id of that resource the user has requested and return just he data for that resource/id.

1 Like

@mayanktaker replying here rather than PM as others may find it useful, though not really MODX related.

I can only give you an answer for a React application, which I think is very similar to Vue/Angular. So usually in your app you’ll make one call to the the api to fetch all resources of a parent ie:

// Call API and store results in state
    axios.get(`https://****.in/rest/resources?parent=6`)
	    .then(res => this.setState({
	        posts: res.results,
	    }))
	    .catch(err => console.log(err));

You’ll then retrieve the JSON object in your app which you then map over ie:

<ul>
    {this.state.posts.map((post) => {
        return <li key={post.id}><Link to={`/posts/${post.id}`}>{post.pagetitle}</Link> </li>
    })}
</ul>

In the link you’re passing the id of the post into the link. So on your single post page you can then access that and make another api call to the specific post ie:

componentDidMount() {
	// Call API passing in the single ID
	axios.get(`https://****.in/rest/resources?parent=${this.props.match.params.id}`)
	    .then(res => this.setState({
	        postData: res.results,
	    }))
	    .catch(err => console.log(err));
}

From here you can now access the post data using this.state.postData. Above example uses axios but you can do this with just fetch too.

1 Like

Thank you for the reply. I got it working.
Here is my Angular code if anyone is looking for :

modxPagee: Observable<any>;
	dataModxPagee: any = [];
	filterDataModxPagee: any = [];
	
	//for infinite-scroll
	lastId:number = 0;
	firstLoad:number = 5;
	perPage:number = 10;
	
	@ViewChild("IonInfiniteScroll",{static: false}) infiniteScroll: IonInfiniteScroll;
	
	
	
	/**
	* ModxPageePage:getItems()
	**/
	getItems(){
		this.modxPagee = this.modxPageeService.getItems();
		this.modxPagee.subscribe(data => {
			this.dataModxPagee = data.results ;
			this.lastId = 0;
			let newData : any = [];
			for (let item of data.results) {
				if(this.lastId <= (this.firstLoad -1) ) {
					newData[this.lastId] = item;
					//console.log(this.lastId);
					this.lastId++;
				}
			}
			this.filterDataModxPagee = newData;
		});
	}

I am about to achieve all the basic needs for a News App. I just want the last help in this topic for the Tags.
As we know I am using Tagger Tags as categories for Blog. And with the help of @markh , we get the posts by categories. Now I just want the list of Tags for the home/navigation page of the App.
So we can see the list of all the available Tags ( Categories) and when user click of a category , for example a user click on Entertaiment tag/category then it lists all the posts of Entertainment category.

So I want this last help from you guys … I want list of Tags in REST api and list of posts for each tag when we browse the tag in Rest Api.

Like this maybe ? - > categories?category=entertainment or categories/entertainment
and entertainment/{post}

Please help. :slight_smile:

Thanks <3

Are you still angry with my foolish words ? :(:lying_face:

Hi @mayanktaker, I’m sure no one is angry! :wink:

I think it’s more to do with not being sure what you’re after exactly. Can you explain a bit more?

What exactly do you need help with? An xPDO function for returning tags?

1 Like

I need this :
List and Tags. Then…
A Tagger Tag > Resources connected with this tag.
Like Entertainment Tag > All Resources under this tag.
This all in REST API.

Well, judging by earlier posts, you understand how to make an api endpoint.

You just need to know how to return the correct results from the endpoint, right?

So you would want two sets of results if I understand you correctly…

  1. A list of all tags
  2. A list of all resources relating to a given tag.

Is that right?

Yes exactly!!!

Ok well I’m not a computer at the moment but I’m happy to write up some xPDO queries for you in a few hours.
They’re not hard once you get used to it.

Looking at Tagger’s schema https://github.com/modxcms/Tagger/blob/9bb82f8d1647ba01a5819071a4f1be637a6ba34b/core/components/tagger/model/schema/tagger.mysql.schema.xml

The queries should be something along the lines of:

// Get a list of tag objects - this one is very straight forward.
public function getTags() {
    $tg = $this->modx->getService(
        'tagger',
        'Tagger',
        $this->modx->getOption('tagger.core_path', null, $this->modx->getOption('core_path').'components/tagger/').'model/tagger/',$scriptProperties
    );
    if (!($tg instanceof Tagger)) return false;
    return $tg->modx->getCollection('TaggerTag');
}

And then in the endpoint where you want related resources you could use:

// Pass a tag id in and get a list of resource objects
public function getTagResources($tagId) {
    $tg = $this->modx->getService(
        'tagger',
        'Tagger',
        $this->modx->getOption('tagger.core_path', null, $this->modx->getOption('core_path').'components/tagger/').'model/tagger/',$scriptProperties
    );
    if (!($tg instanceof Tagger)) return false;
    $c = $tg->modx->newQuery('modResource');
    $c->innerJoin('TaggerTagResource','TagResource','TagResource.resource = modResource.id');
    $c->innerJoin('TaggerTag','Tag','Tag.id = TagResource.tag');
    $c->where([
        'Tag.id'  =>  $tagId
    ]);
    $c->select('*');
    return $tg->modx->getCollection('modResource',$c);
}

Please note I haven’t tested these and they probably need a bit of altering but it should get you started.
Also, it’d be good practice to put the getService call elsewhere. Perhaps in the initialization section of the class.
Remember these return objects. You could then loop through the results and call toArray() or toJSON() on them as well.

Update :

I am trying to add Authentication and got stuck!!

<?php
/**
 * Found at: Controllers/Auth.php
 *
 * Handle requests to [URL]/Controllers/Auth. Automagically handles login / log-out requests (basic auth) - should only be used over https
 */
class APIAuth extends modRestController {

    public $classKey = 'modUser';
    public $defaultSortField = 'id';
    public $defaultSortDirection = 'ASC';

    public function verifyAuthentication() {

        if ($this->request->method != 'get') Throw new Exception('Method Not Allowed', 405); // Only allow GET requests to the AUTH controller

        if ($this->modx->user || $this->modx->user->id >= 1) { // If user is logged in & user passes the "logout" param than log them out
            if ($_GET['logout']) {  
                $this->modx->runProcessor('security/logout',array(
                                'login_context' => $this->getProperty('loginContext', $this->modx->context->get('key')),
                                'add_contexts' => $this->getProperty('contexts',''),
                            ));
            } 

        }
        if (!$this->modx->user || $this->modx->user->id < 1) {  // If not logged in & user passes a username & password preform basic auth by running login processor
            $c = array(     
                'username' => $_GET['username'],
                'password' => $_GET['password'],
            );
            $this->modx->runProcessor('security/login',$c);

        }


        if (!$this->modx->user || $this->modx->user->id < 1) return false;  //finally do a check to see if user is logged in or not & either send back a true or false
        return true;
    }


    protected function prepareListQueryBeforeCount(xPDOQuery $c) { // If user is logged in return their basic user info


            $c->where(array(
                'id' => $this->modx->user->id
            ));

            return $c;  

    }  


} 

Class ‘modRestController’ not found in H:\WAMP\www\myvirtualhost\modxtest1\rest\Controllers\Auth.php on line 7

How do I add this APIAuth in Rest/index.php ? Which way ?