Giter VIP home page Giter VIP logo

graphqlsuitecrm's Introduction

Latest Stable Version Total Downloads Latest Unstable Version License

UPCOMING NEW VERSION SuiteCRM 8 will have GraphQL natively so only bugfixes and minor features!

Current code works well with SuiteCRM rest API. .

But I am already developing next version based on a much stronger PHP-GraphQL library webonyx/graphql. It is coming along nicely, has better performance, and I am using 100% V8 API endpoints (oauth-tokens instead of cookies).

GraphQLSuiteCRM

Use GraphQL instead of REST API to access SuiteCRM data. Production ready. Supports custom modules and custom REST endpoints with or without authentication. Can be integrated with SuiteCRM v8 API to be used with its native authentication.

What it does

This package allows to use GraphQL with SuiteCRM (8.x / 10.x) /SugarCRM (6.5) instead of the Rest API which is not truly REST.

Upong installation a graphql endpoint will be created vendor/lionixevolve/graphqlsuitecrm/rest.php/graphql and you can hit it with queries if you are authenticated on SuiteCRM (using cookies)

There are more undocumented functions in the endpoint, like getting dropdown values.TODO: Document this

Once you send a query to rest.php/graphql it uses a PHP SuiteCRM Graphql schema based on Youshido/GraphQL library to process your query.

This GraphQL library uses SuiteCRM/SugarCRM beans for almost all the actions, so every logic hook you created or workflow, should work as planned.

Set up

composer require lionixevolve/graphqlsuitecrm

This will install the plugin in the vendor folder with all the requirements.

PHP extension php-intl its a requirement, for ubuntu install as sudo apt-get install php-intl

Testing and Usage

GraphiQL is included in the package, to start using it open the web broser in http://localhost/vendor/lionixevolve/graphqlsuitecrm/graphql/GraphiQL/ (adjust localhost to the suitecrm instance location) Use the included GraphiQL to try this

{
  accounts(limit:2) {
    name
  }
}

it will get you the accounts module with the name of each one. Limited to 2. You can also use the offset:2 to paginate.

An advance example - retrieving all the cases by status. Also you can see some schema changes for the assigned_user/created_by users field that let you retrieve further information about the user.


 query cases( $status: String, $limit: String, $offset: String){
                                            cases( status: $status, offset:$offset, limit: $limit, order:"case_number" ){
                                                id
                                                case_number
                                                date_entered
                                                description
                                                status
                                                assigned_user_details{
                                                    id
                                                    first_name
                                                    last_name
                                                    user_name
                                                }
                                                created_user_details {
                                                    id
                                                    first_name
                                                    last_name
                                                    user_name
                                                }
                                                accounts {
                                                    name
                                                    id
                                                    contacts{
                                                        id
                                                    }
                                                }
                                            }
                                        }

As you can see related modules are also retrieved using the plural word of the relation. Accounts/Opportunities, etc.

Extending/Customizing Suitecrm Graphql Schema

The library will load custom files from the graphql folder.

Two main files are loaded

  1. graphql/CustomSuiteCRMSchema.php
  2. graphql/CustomRest.php

the #1 will extend the included schema, for custom modules or even non-suitecrm related queries. the #2 will allow you to create your own REST endpoint calls, we use this for report generation where graphql resultset is not very efficient. (like using aggrid compatible resultset)

A full example of how to extend is below.

Extending the Schema -

Here I am creating support for prospectlist which is not included (yet) in the main library.

This is extracted from a working setup

<?php
//`graphql/CustomSuiteCRMSchema.php`
require_once 'Schema/ProspectlistListType.php';
require_once 'Schema/ProspectlistprospectInputType.php';
require_once 'Schema/ProspectlistType.php';
require_once 'Schema/customAccountType.php';
use Youshido\GraphQL\Execution\ResolveInfo;
use Youshido\GraphQL\Type\Scalar\StringType;

class CustomSuiteCRMSchema
{
    public function buildSchema($config)
    {
        $config->getQuery()->addFields([
            'prospectlists' => [
                'type' => new ProspectlistListType(),
                'args' => argsHelper::entityArgsHelper('ProspectLists'),
                'resolve' => function ($value, array $args, ResolveInfo $info) {
                    return $info->getReturnType()->resolve($value, $args, $info);
                },
            ],
        ]);
        $config->getMutation()->addFields([
            'assignProspectlistprospect' => [
                'type' => new ProspectlistprospectInputType(),
                'args' => ['beanid' => new StringType(), 'beanname' => new StringType(), 'prospectlistid' => new StringType()],
                'resolve' => function ($value, $args, $type) {
                    $result = ProspectlistprospectInputType::resolve($value, $args, $type);
                    return ["id" => $result];
                },
            ],
        ]);
    }

}
<?php
//Schema/ProspectlistsType.php
use Youshido\GraphQL\Type\Object\AbstractObjectType;
use Youshido\GraphQL\Execution\ResolveInfo;

class ProspectlistType extends AbstractObjectType   // extending abstract Object type
{
    public function build($config)  // implementing an abstract function where you build your type
    {
        foreach (argsHelper::entityArgsHelper('ProspectLists') as $field => $type) {
                $config->addField($field, $type);
        }
        
        $config->addField('related_contacts',[
                    'type' => new ContactsListType(),
                    'args' => argsHelper::entityArgsHelper('Contacts'),
                    'resolve' => function ($value, array $args, ResolveInfo $info) {
                         if (!empty($value['related_contacts'])) {
                             $args['ids']=$value['related_contacts'];
                             return ContactsListType::resolve($value, $args, $info);
                         } else {
                             return null;
                         }
                    },
                ]);
        $config->addField('related_accounts', [
                    'type' => new AccountsListType(),
                    'args' => argsHelper::entityArgsHelper('Accounts'),
                    'resolve' => function ($value, array $args, ResolveInfo $info) {
                         if (!empty($value['related_accounts'])) {
                              $args['ids']=$value['related_accounts'];
                             return AccountsListType::resolve($value, $args, $info);
                         } else {
                             return null;
                         }
                    },
                ]);
    }
    private function retrieveProspectlist($id, $info)
    {
        global $sugar_config, $current_user;
        $prospectlistBean = BeanFactory::getBean('ProspectLists');
        $bean = $prospectlistBean->retrieve($id);
        if($info!=null){
            $getFieldASTList=$info->getFieldASTList();
            $queryFields=[];
            foreach ($getFieldASTList as $key => $value) {
                $queryFields[$value->getName()]="";
            }
        }

        $module_arr = array();
        if ($bean->id && $bean->ACLAccess('view')) {
            $all_fields = $bean->column_fields;
            foreach ($all_fields as $field) {
                if (isset($bean->$field) && !is_object($bean->$field)) {
                    $bean->$field = from_html($bean->$field);
                    $bean->$field = preg_replace("/\r\n/", '<BR>', $bean->$field);
                    $bean->$field = preg_replace("/\n/", '<BR>', $bean->$field);
                    $module_arr[$field] = $bean->$field;
                }
            }
            $module_arr['created_user_details'] = $module_arr['created_by'];
            $module_arr['assigned_user_details'] = $module_arr['assigned_user_id'];
            $module_arr['modified_user_details'] = $module_arr['modified_user_id'];
            
            foreach ($bean->get_linked_beans('contacts', 'Contact') as $contact) {
                $module_arr['related_contacts'][] = $contact->id;
            }
            foreach ($bean->get_linked_beans('accounts', 'Account') as $account) {
                $module_arr['related_accounts'][] = $account->id;
            }
            foreach ($bean->get_linked_beans('opportunities', 'Opportunity') as $opportunity) {
                $module_arr['related_opportunities'][] = $opportunity->id;
            }
            return $module_arr;
        } else {
            error_log(__METHOD__.'----'.__LINE__.'----'.'error resolving CallType');
            return;
        }
    }

    public function resolve($value = null, $args = [], $info = null )  // implementing resolve function
    {
        if (isset($args['id']) && is_array($args['id'])) {
            foreach ($args as $key => $nodeId) {
                if (isset($nodeId) && is_array($nodeId)) {
                    foreach ($nodeId as $key => $nodeIdItem) {
                        $resultArray[] = self::retrieveProspectlist($nodeIdItem, $info );
                    }
                } elseif (!empty($nodeId)) {
                    $resultArray[] = self::retrieveProspectlist($nodeId, $info );
                }
            }

            return $resultArray;
        } elseif (!empty($args['id'])) {
            return self::retrieveProspectlist($args['id'],$info);
        }
    }

    public function getName()
    {
        return 'ProspectList'; 
    }
}

<?php
// schema/ProspectlistListType.php

use Youshido\GraphQL\Type\ListType\AbstractListType;


if (!defined('sugarEntry')) {
    define('sugarEntry', true);
}
require_once 'modules/Prospects/Prospect.php';
require_once 'modules/ProspectLists/ProspectList.php';

class ProspectlistListType extends AbstractListType
{
    public function getItemType()
    {
        return new ProspectlistType();
    }

    public function build($config)
    {
        // $config
        // ->addArgument('limit', TypeMap::TYPE_INT)
        // ->addArgument('offset', TypeMap::TYPE_INT);
    }
    public function endswith($string, $test)
    {
        $strlen = strlen($string);
        $testlen = strlen($test);
        if ($testlen > $strlen) {
            return false;
        }
        return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0;
    }
    public function resolve($value = null, $args = [], $info = null)
    {
        global $current_user;
        require_once 'vendor/lionixevolve/graphqlsuitecrm/graphql/Schema/ListHelper.php';
        $list=ListHelper('ProspectLists',$value  , $args , $info );
        $resultArray = [];

        if (is_array($list['list']) && !empty($list['list'])) {

            if ($list['list'][0]->ACLAccess('list')) {
                foreach ($list['list'] as $item) {
                    $resultArray[] = ProspectlistType::resolve(null, ['id' => $item->id], $info);
                }
            } else {
                //no access given
                error_log('no access');
            }
            return empty($resultArray)? null :$resultArray;
        } else {
            return null;
        }
    }
   
}

With these 2 files you will have QUERY support for ProspectLists (mutation os prospectlist itself is missing in this example)

Prospectlists is useful for segmenting audience, contacts, accounts and leads so the following mutation will relate the Bean and the prospect.

<?php
//schema/ProspectlistprospectInputType.php
use Youshido\GraphQL\Type\Object\AbstractObjectType;
use Youshido\GraphQL\Type\Scalar\StringType;

class ProspectlistprospectInputType extends AbstractObjectType   // extending abstract Object type
{
    public function build($config)  // implementing an abstract function where you build your type
    {
        $config->addField('id', new StringType());
    }

    public static function guidv4() //Helper function to imitate mysql GUID
        {
            if (function_exists('com_create_guid') === true)
                return trim(com_create_guid(), '{}');

            $data = openssl_random_pseudo_bytes(16);
            $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
            $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10
            return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
        }
    public function resolve($value = null, $args = [], $type = null)  // implementing resolve function
    {
        //We use the crm Helper to create/save the Bean
        global $db;
        if(!empty($args['beanid']) && !empty($args['prospectlistid']) && !empty($args['beanname']) 
        && ($args['beanname'] =='Accounts' || $args['beanname'] =="Contacts"||$args['beanname']== "Prospects" )
        ){
            $insertQuery="
            INSERT INTO prospect_lists_prospects
            (id, prospect_list_id, related_id, related_type, date_modified)
            VALUES('?', '?', '?', '?', now());
            ";
            $uuid=\ProspectlistprospectInputType::guidv4();
            $resultByStatus = $db->pQuery($insertQuery,  [$uuid, $args['prospectlistid'],$args['beanid'],$args['beanname']]);
            if($resultByStatus=="1"){
                return $uuid;
            }else{
                return null;
            }
        }else{
            return null;
        }
         
    }

    public function getName()
    {
        return 'Prospectlistprospect';
    }
    public function getOutputType()
    {
        return new StringType();  
    }
}

Customizing the Rest endpoint

  • You can extend the rest (made with Slim) requests when the file graphql/CustomRest.php exists on your root suitecrm/lionixcrm folder
$app->post('/newPost', function (\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response){
return $response->withJson(["result"=>"empty - not even tried"]);
}

CORS

If you need support for CORS you may use the graphql/CustomRest.php and include the following snippet


$app->add(new \Eko3alpha\Slim\Middleware\CorsMiddleware([
    'http://www.example.com' => ['GET', 'POST','PUT', 'DELETE','OPTIONS'],
    'https://www.example2.com' => ['GET', 'POST'],
]));

The CORS middleware will take care of allowing the specified hosts to access the API and return valid headers.

GraphiQL

You can use the included GraphiQL here: vendor/lionixevolve/graphqlsuitecrm/graphql/GraphiQL/

Known Issues

  • there is currently an issue with the schema inspector Issue#2
  • Is currently checking ACL edit when saving the bean,

TODO

  • Add missing modules (Quotes/Invoices/ProspectLists/etc)
  • Migrate to the more active webonyx graphqlphp

graphqlsuitecrm's People

Contributors

cumanacr avatar mrbarletta avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

erwasambo amit-t

graphqlsuitecrm's Issues

Relational module Query and mutations

Hello,

I am trying to get relation module data but its not working properly. I have define custom relationship with Notes module i have checked NotesType.php file in schema folder and i have extend code for todoitem(custom module relationship with notes) but its not working.

NoteType.php

<?php

use Youshido\GraphQL\Type\Object\AbstractObjectType;
use Youshido\GraphQL\Type\Scalar\StringType;
use Youshido\GraphQL\Execution\ResolveInfo;
use Youshido\GraphQL\Type\ListType\ListType;
require_once 'argsHelper.php';

class NoteType extends AbstractObjectType   // extending abstract Object type
{
    public function build($config)  // implementing an abstract function where you build your type
    {
        foreach (argsHelper::entityArgsHelper('Notes') as $field => $type) {
                $config->addField($field, $type);
        }
        $config->addField('created_user_details', [
                'type' => new UserType(),
                'resolve' => function ($value, array $args, ResolveInfo $info) {
                    if (!empty($value['created_user_details'])) {
                        $args['id']=$value['created_user_details'];
                        return UserType::resolve($value, $args, $info);
                    } else {
                        return null;
                    }
                 },
         ]);
        $config->addField('assigned_user_details',[
                'type' => new UserType(),
                'resolve' => function ($value, array $args, ResolveInfo $info) {
                    if (!empty($value['assigned_user_details'])) {
                        $args['id']=$value['assigned_user_details'];
                        return UserType::resolve($value, $args, $info);
                    } else {
                        return null;
                    }
                 },
         ]);
        $config->addField('modified_user_details', [
                'type' => new UserType(),
                'resolve' => function ($value, array $args, ResolveInfo $info) {
                    if (!empty($value['modified_user_details'])) {
                        $args['id']=$value['modified_user_details'];
                        return UserType::resolve($value, $args, $info);
                    } else {
                        return null;
                    }
                 },
         ]);
         $config->addField('contact_details', [
                 'type' => new ContactType(),
                 'resolve' => function ($value, array $args, ResolveInfo $info) {
                     if (!empty($value['contact_details'])) {
                         $args['id']=$value['contact_details'];
                         return ContactType::resolve($value, $args, $info);
                     } else {
                         return null;
                     }
                  },
          ]);
         $config->addField('parent_contact', [
                     'type'     => new ContactType(),
                     'args' => argsHelper::entityArgsHelper('Contacts'),
                     'resolve' => function ($value, array $args, ResolveInfo $info) {
                         if (!empty($value['parent_contact'])) {
                             $args['id']=$value['parent_contact'];
                             return ContactType::resolve($value, $args, $info);
                         } else {
                             return null;
                         }
                    },
            ]);
         $config->addField('parent_account', [
                     'type' => new AccountType(),
                     'args' => argsHelper::entityArgsHelper('Accounts'),
                     'resolve' => function ($value, array $args, ResolveInfo $info) {
                          if (!empty($value['parent_account'])) {
                              $args['id']=$value['parent_opportunity'];
                              return AccountType::resolve($value, $args, $info);
                          } else {
                              return null;
                          }
                     },
             ]);
         $config->addField('parent_opportunity', [
                     'type' => new OpportunityType(),
                     'args' => argsHelper::entityArgsHelper('Opportunities'),
                     'resolve' => function ($value, array $args, ResolveInfo $info) {
                          if (!empty($value['parent_opportunity'])) {
                              $args['id']=$value['parent_opportunity'];
                              return OpportunityType::resolve($value, $args, $info);
                          } else {
                              return null;
                          }
                     },
             ]);
        $config->addField('contacts',[
                    'type' => new ContactsListType(),
                    'args' => argsHelper::entityArgsHelper('Contacts'),
                    'resolve' => function ($value, array $args, ResolveInfo $info) {
                         if (!empty($value['contacts'])) {
                             $args['ids']=$value['contacts'];
                             return ContactsListType::resolve($value, $args, $info);
                         } else {
                             return null;
                         }
                    },
                ]);
        $config->addField('accounts', [
                    'type' => new AccountsListType(),
                    'args' => argsHelper::entityArgsHelper('Accounts'),
                    'resolve' => function ($value, array $args, ResolveInfo $info) {
                         if (!empty($value['accounts'])) {
                              $args['ids']=$value['accounts'];
                             return AccountsListType::resolve($value, $args, $info);
                         } else {
                             return null;
                         }
                    },
                ]);
        $config->addField('opportunities', [
                'type'=> new OpportunitiesListType(),
                'args' => argsHelper::entityArgsHelper('Opportunities'),
                'resolve' => function ($value, array $args, ResolveInfo $info) {
                     if (!empty($value['opportunities'])) {
                         $args['ids']=$value['opportunities'];
                         return OpportunitiesListType::resolve($value, $args,$info);
                     } else {
                         return null;
                     }
                 },
         ]);
         $config->addField('ti_todoitems_notes', [
            'type'=> new Ti_todoitemsListType(),
            'args' => argsHelper::entityArgsHelper('ti_todoitems_notes'),
            'resolve' => function ($value, array $args, ResolveInfo $info) {
                 if (!empty($value['ti_todoitems_notes'])) {
                     $args['ids']=$value['ti_todoitems_notes'];
                     return Ti_todoitemsListType::resolve($value, $args,$info);
                 } else {
                     return null;
                 }
             },
     ]);
    }
    private function retrieveNote($id, $info)
    {
        global $sugar_config, $current_user;
        $noteBean = BeanFactory::getBean('Notes');
        $note = $noteBean->retrieve($id);
        if($info!=null){
            $getFieldASTList=$info->getFieldASTList();
            $queryFields=[];
            foreach ($getFieldASTList as $key => $value) {
                $queryFields[$value->getName()]="";
            }
        }
        $module_arr = array();
        if ($note->id && $note->ACLAccess('view')) {
            $all_fields = $note->column_fields;
            foreach ($all_fields as $field) {
                if (isset($note->$field) && !is_object($note->$field)) {
                    $note->$field = from_html($note->$field);
                    $note->$field = preg_replace("/\r\n/", '<BR>', $note->$field);
                    $note->$field = preg_replace("/\n/", '<BR>', $note->$field);
                    $module_arr[$field] = $note->$field;
                }
            }
            $module_arr['created_user_details'] = $module_arr['created_by'];
            $module_arr['assigned_user_details'] = $module_arr['assigned_user_id'];
            $module_arr['modified_user_details'] = $module_arr['modified_user_id'];
            switch ($module_arr['parent_type']) {
                case 'Contacts':
                    $module_arr['parent_contact'] = $module_arr['parent_id'];
                    $module_arr['parent_account'] = '';
                    $module_arr['parent_opportunity'] = '';
                    $module_arr['parent_case'] = '';
                    $module_arr['parent_email'] = '';
                    break;
                case 'Accounts':
                    $module_arr['parent_account'] = $module_arr['parent_id'];
                    $module_arr['parent_contact'] = '';
                    $module_arr['parent_opportunity'] = '';
                    $module_arr['parent_case'] = '';
                    $module_arr['parent_email'] = '';
                    break;
                case 'Opportunities':
                    $module_arr['parent_opportunity'] = $module_arr['parent_id'];
                    $module_arr['parent_contact'] = '';
                    $module_arr['parent_account'] = '';
                    $module_arr['parent_case'] = '';
                    $module_arr['parent_email'] = '';
                    break;
                case 'Cases':
                    $module_arr['parent_opportunity'] = $module_arr['parent_id'];
                    $module_arr['parent_contact'] = '';
                    $module_arr['parent_account'] = '';
                    $module_arr['parent_case'] = $module_arr['parent_id'];
                    $module_arr['parent_email'] = '';
                    break;
                case 'Emails':
                    $module_arr['parent_opportunity'] = '';
                    $module_arr['parent_contact'] = '';
                    $module_arr['parent_account'] = '';
                    $module_arr['parent_case'] = '';
                    $module_arr['parent_email'] = $module_arr['parent_id'];
                    break;
                case 'ti_todoitems_notes':
                    $module_arr['parent_opportunity'] = '';
                    $module_arr['parent_contact'] = '';
                    $module_arr['parent_account'] = '';
                    $module_arr['parent_case'] = '';
                    $module_arr['parent_email'] = '';
                    $module_arr['parent_email'] = '';
                    break;    

                default:
                    $module_arr['parent_opportunity'] = '';
                    $module_arr['parent_contact'] = '';
                    $module_arr['parent_account'] = '';
                    $module_arr['parent_case'] = '';
                    $module_arr['parent_ti_todoitems_note'] = '';
                    break;

                }
                if(isset($queryFields) && array_key_exists('ti_todoitems_notes',$queryFields)){
                    $module_arr['ti_todoitems_notes'] =  array();
                    foreach ($note->get_linked_beans('ti_todoitems_notes', 'ti_todoitems_notes') as $contact) {
                        $module_arr['ti_todoitems_notes'][] = $contact->id;
                    }
                }
                if(isset($queryFields) && array_key_exists('contacts',$queryFields)){
                    $module_arr['contacts'] =  array();
                    foreach ($note->get_linked_beans('contacts', 'Contact') as $contact) {
                        $module_arr['contacts'][] = $contact->id;
                    }
                }
                if(isset($queryFields) && array_key_exists('accounts',$queryFields)){
                    $module_arr['accounts'] = array();
                    foreach ($note->get_linked_beans('accounts', 'Account') as $account) {
                        $module_arr['accounts'][] = $account->id;
                    }
                }
                if(isset($queryFields) && array_key_exists('opportunities',$queryFields)){
                    $module_arr['opportunities'] =  array();
                    foreach ($note->get_linked_beans('opportunities', 'Opportunity') as $opportunity) {
                        $module_arr['opportunities'][] = $opportunity->id;
                    }
                }
                $module_arr['contact_details'] =  array();
                if(isset($queryFields) && array_key_exists('contact_details',$queryFields)){
                        $module_arr['contact_details'] = $note->contact_id;
                }
            return $module_arr;
        } else {
            return null;
        }
    }

    public function resolve($value = null, $args = [], $info = null)  // implementing resolve function
    {
        if (isset($args['id']) && is_array($args['id'])) {
            foreach ($args as $key => $noteId) {
                // error_log(__LINE__.print_r($args,1));
                if (isset($noteId) && is_array($noteId)) {
                    foreach ($noteId as $key => $noteIdItem) {
                        $resultArray[] = self::retrieveNote($noteIdItem, $info);
                    }
                } elseif (!empty($noteId)) {
                    $resultArray[] = self::retrieveNote($noteId, $info);
                }
            }

            return $resultArray;
        } elseif (!empty($args['id'])) {
            return self::retrieveNote($args['id'],$info);
        }
    }

    public function getName()
    {
        return 'Note';  // important to use the real name here, it will be used later in the Schema
    }
}

Would you please suggest to get pass paramater of custom realtion module query and also provide Mutation example .

Thanks

How to get records by descending order?

How to get records by descending order from graphql query. I tried to use order parameter with the field but it gave me records by ascending orders.

Thanks

Provide Proper documentation how to use this libary

Hello,

How too uses this library and check queries and mutation using graphql tools. I had just put library in vendor folder. Would you please let me know steps how to test queries and mutation.

Thanks

How to pass value in SuiteCRMSchema file

Hello,

I have to pass value from rest.php to SuiteCRMSchema.php when declaring an object of that class. I tried to pass value from rest.php but It gives me an error. So how can I pass value from rest.php file to SuiteCRMSchema.php?

Please give me a solution.

Thanks.

Unable to load db manager

Upon integrating GraphqlSuiteCRM in our project ,we added new schemas and generated new mapping using doctrine .The issue happens when we try to regenerate entities using the command :

php vendor/bin/doctrine orm:generate-entities --regenerate-entities --no-backup ./

we get the following error : Cannot load DB manager .
I would appreciate it if you could provide me more infos about this issue .
Thank you

GraphiQL no schema available

Using GraphiQL, i can query sugarcrm modules and i get results but in the documentation explorer no schema is available .
I was just wondering to what this issue could be related ? .
Thank you

How to Improve Query and mutations Performance.

Hello,

We have created so many custom query and mutations and we have write custom files for queries and mutations but its take more time. Would you please suggest how to improve performance for query and mutation.

Are there any settings in your library or tools to measure query/mutation performance?

Thanks

Give error when return relational table field

Hello,
I am creating a custom schema to get data from 2 relational tables. But when I am returning relational table field from graphql query at that time it will give me field not found error. Please suggest me a solution for how to return relational table field value using graphql and suite CRM.

use Youshido\GraphQL\Type\ListType\AbstractListType;

if (!defined('sugarEntry')) {
    define('sugarEntry', true);
}


class KanbanTodoitems extends AbstractListType
{
    public function getItemType()
    {
        return new Ti_todoitemsType();
        
    }

    public function build($config)
    {
    }
    public function endswith($string, $test)
    {
        $strlen = strlen($string);
        $testlen = strlen($test);
        if ($testlen > $strlen) {
            return false;
        }
        return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0;
    }
    public function resolve($value = null, $args = [], $info = null)
    {
        global $current_user;
        $kanbanid =  $args['kanban_ref'];

        require_once 'vendor/lionixevolve/graphqlsuitecrm/graphql/Schema/ListHelper.php';
        global $db;
        $Query = "SELECT ti.id, ti.name, ti.contact_id_c, ti.todolist_id, ti.lession_id, ti.due_date, ti.priority, ti.status,pj.id as project_id, pj.agent_id, c.first_name, hlc.todorepeattype_c, ti.role FROM ti_todoitems ti LEFT JOIN contacts c ON c.id = ti.contact_id_c LEFT JOIN proj_project pj ON ti.todolist_id = pj.todo_list LEFT JOIN hlpkg_todolist_cstm hlc ON hlc.id_c = ti.todolist_id  WHERE kanban_ref='$kanbanid'  and ti.deleted='0'  ORDER By convert(ti.task_order,unsigned) ASC";
        $result = $db->query($Query);
         
        if($result) {
            return $result;
        } else {
                return null;
        }
    }
   
}

How to Create schema for custom modules

Hello,

Would you please provide details documentation on how to create custom module schema (queries and mutations ) I have try to explore code but its confusing and didn't get idea how to define schema for custom modules.

Thanks

How to handle custom error in rest.php file

Hello,

I passed auth token from react application to suite CRM and I have to check whether this token is expired or not in the rest.php file and on that basis I have to return custom message. So how can I return a custom error message and handle in my application.

Thanks.

How to check authentication?

Hello,

I have to check JWT authentication on each request. So how can I check JWT authentication and where to put my code for verification.

Thanks.

How to pass custom arguments in custom module queries?

Hello,

I have create custom module queries and and mutations and its working fine. now i need to filter query based on different arguments. As per your documentations LitsType file is used for query.

I have make custom TaskListType.php file for query list of tasks and its working fine.

// namespace SuiteCRM\Schema;

use Youshido\GraphQL\Type\NonNullType;
use Youshido\GraphQL\Type\ListType\AbstractListType;
use Youshido\GraphQL\Type\TypeMap ;
use Youshido\GraphQL\Execution\ResolveInfo;

require_once 'NoteType.php';

if (!defined('sugarEntry')) {
    define('sugarEntry', true);
}

class TasksListType extends AbstractListType
{
    public function getItemType()
    {
        return new TaskType();
    }

    public function build($config)
    {
        foreach (argsHelper::entityArgsHelper('Tasks', true) as $field => $type) {
            $config->addField($field, $type);
        
    }
    public function resolve($value = null, $args = [], $info = null)
    {
        require_once 'ListHelper.php';
        $list=ListHelper('Tasks',$value  , $args , $info );
        $resultArray = [];

        if (is_array($list['list']) && !empty($list['list'])) {
            if ($list['list'][0]->ACLAccess('list')) {
                foreach ($list['list'] as $item) {
                    $resultArray[] = TaskType::resolve(null, ['id' => $item->id], $info);
                }
            } else {
                //no access
                error_log('no access');
            }
            return empty($resultArray)? null :$resultArray;
        } else {
            return null;
        }
    }
}

Now I want to used same method for tasklist query but add different arguments like tasklist based on start date,end date, developer wise tasks etc,

Would you please provide proper documentations or example how to add custom arguments in query.

Thanks

Mutation not working

Hello,

I am trying to submit form to create records in suitecrm but mutations not working. Mutations working find with graphql tools but its not working with apollo-react.

Getting Below errors.

{"errors":[{"message":"Must provide an operation."}]}

Environment:
Suitecrm 7.11.2
PHP 7.0.22
NodeJs: 11.9.0
NextJs
React Apollo

Would you please suggest how to fix above issue.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.