Custom API V8 creation in SuiteCRM8

I’m trying to create a custom api v8 in suitecrm8. Trying to hit an endpoint which will call a controller and do some specific task as per my requirement. But as soon as I give my controller path of custom folder. It gives slim runtime error, couldn’t find the controller.
Please help.

I’ve figured out how to create custom API, how to call them in SuiteCRM8, API/V8.
But I still didn’t understood how to extend the api routes, controller, services. I’ve gone through the documentation many times but it is no use.
If anyone is figured out how to extend please let me know.

One thing I’d like to add the documentation is a total useless when it comes to extending any option or try to do some custom activity in suitecrm. Whatever I did that I’ve figured out by cracking my head for days.

#customapi #suitecrm8 #api #V8

If you’re in SuiteCRM 8, you’re probably better off working with the new GraphQL API.

I know “API V8” sounds like it’s the API of SuiteCRM V8, but it isn’t…

Is there any documentation on how to use GraphQL with SuiteCRM V8? I have looked but can’t seem to find much.

Following this https://github.com/lionixevolve/GraphQLSuiteCRM I seem to be facing a couple of issues. Running locally:

https://crm_suitecrm8.dev loads the CRM as expected.

https://crm_suitecrm8.dev/index.php/api/graphql gives me:

vhosts file:

<VirtualHost *:443>
    ServerName crm_suitecrm8.dev
    DocumentRoot "C:/xampp/htdocs/crm_suitecrm8/public"
    <Directory C:/xampp/htdocs/crm_suitecrm8/public>
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>

.htaccess

<IfModule mod_rewrite.c>
    Options +SymLinksIfOwnerMatch
    Options -Indexes
    Options -MultiViews
    RewriteEngine On
    RewriteBase /public/legacy/

Any thoughts/advice?

1 Like

No docs yet… but the core SuiteCRM v8 uses the API everywhere, so the trick is to copy existing code from core.

That Github repo was an older solution to use GraphQL before SuiteCRM v8 came out - it is a different GraphQL, I don’t think it’s good to use that, going forward.

I have a barely-working-example I worked on a year ago; I don’t remember anything from it, and if you can’t get it to work, I probably won’t be able to help you. But here it goes:

Create file
extensions/MyProject/core/backend/Process/Service/MyProjectSiteProcessHandler.php

with these contents

<?php

namespace App\Extension\MyProject\core\backend\Process\Service;

use ApiPlatform\Core\Exception\InvalidArgumentException;
use App\Process\Entity\Process;
use App\Process\Service\ProcessHandlerInterface;
use App\Engine\LegacyHandler\LegacyHandler;
use BeanFactory;

class MyProjectSiteProcessHandler extends LegacyHandler implements ProcessHandlerInterface
{
    protected const MSG_OPTIONS_NOT_FOUND = 'Process options are not defined';
    protected const PROCESS_TYPE = 'myproject-site-process';

    /**
     * @inheritDoc
     */
    public function getProcessType(): string
    {
        return self::PROCESS_TYPE;
    }

    /**
     * @inheritDoc
     */
    public function requiredAuthRole(): string
    {
        return 'ROLE_USER';
    }

    /**
     * @inheritDoc
     */
    public function getHandlerKey(): string
    {
        return self::PROCESS_TYPE;
    }

    /**
     * @inheritDoc
     */
    public function configure(Process $process): void
    {
        //This process is synchronous
        //We aren't going to store a record on db
        //thus we will use process type as the id
        $process->setId(self::PROCESS_TYPE);
        $process->setAsync(false);
    }

    /**
     * @inheritDoc
     */
    public function validate(Process $process): void
    {
        if (empty($process->getOptions())) {
            throw new InvalidArgumentException(self::MSG_OPTIONS_NOT_FOUND);
        }

        $options = $process->getOptions();

        if (empty($options['action'])) {
            throw new InvalidArgumentException(self::MSG_OPTIONS_NOT_FOUND);
        }

        if (empty($options['first_name']) || empty($options['last_name']) ) {
            throw new InvalidArgumentException(self::MSG_OPTIONS_NOT_FOUND);
        }
    }

    /**
     * @inheritDoc
     */
    public function run(Process $process)
    {
        $this->init();
        $new = BeanFactory::newBean("Leads");
        // might be necessary to call StartLegacyApp to load user, controller etc

        $process->setStatus('success');
        $process->setMessages([
            'LBL_RECOVER_PASSWORD_SUCCESS'
        ]);

        ['first_name' => $new->first_name, 'last_name' => $new->last_name] = $process->getOptions();
        $ret = $new->save();
        $this->close();
    }
}

Now, I can’t find any records of how I called that custom API entry-point :frowning:

But I think this is part of it:

{
  "input": {
    "type": "myproject-site-process",
    "options": {
      "action": "create-lead",
      "first_name": "Test lead",
      "last_name": "From API"
    }
  }
}

It should create a new Lead with provided data.

I think this doesn’t handle authentication very well, but it’s a start. If you have problems, try calling some API endpoint from Core code until you get things right. For example, the one from Core which I used to copy this one: core/backend/Process/LegacyHandler/ResetPasswordHandler.php

@pgr Thanks for the time you have spent on this. I can’t say that I am much further forward. I am actually trying to call GraphQL from Postman but I wonder if this is even possible.

I have tried your code but can’t be sure I have it in the correct place or the endpoint to call it. I can’t get the debugger to launch so it is not being hit. Should it be in extensions or core

image

I found an email with instructions on how to test the above code, let’s try it…

Go to this test address:
http://yourSiteURL/docs/graphql

And put this in the first box:

mutation createProcess($input: createProcessInput!) {
  createProcess(input: $input) {
    process {
      _id
      status
      async
      type
      messages
      data
      __typename
    }
    clientMutationId
    __typename
  }
}

and in the variables (at the bottom of screen, make sure it’s not obscured by Symfony debug toolbar), this:

{
  "input": {
    "type": "myproject-site-process",
    "options": {
      "action": "create-lead",
      "first_name": "Test lead",
      "last_name": "From API"
    }
  }
}

Can you get something going from this? Remember you have to login to the UI first in a different tab.

As far as breakpoints are concerned, I am not sure, but maybe you can find something by having a look at my stack when breaking inside MyProjectSiteProcessHandler.run()

@rgreen I’m not using GraphQL API in suitecrm8. I’ve achieved my work using custom api via suitecrm only. I’m very new to the suitecrm.
If you want to do the way I did then I can help. Let me know if I can help.

Thanks, and sorry for the delay. This has been sidelined for a while. I am fine with API in general but was hoping to get looking at GraphQL. I will get back to it soon.