How to integrate web services with custom module in SugarCRM? - sugarcrm

I'm using SugarCRM to develop a software for customers management. I created a custom module from basic template with custom fields. Is it possible to get rid of SugarCRM db and perform CRUD operations through external web serivices? Actually I was able to show web services data in the datailview by setting the bean property of a custom controller.
class CustomerController extends SugarController{
public function action_detailview(){
$customer = new Customer();
$customer = getCustomerFromWebService();
$this->bean = $customer;
$this->view = "detail";
}
}
I would like to do the same thing with listview, but I don't know how set the records of the list (if it exists) used by the default listview.

You can change list view by customizing view.list.php in custom/modules/modulename/views/view.list.php using following code:
<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
require_once('include/MVC/View/views/view.list.php');
// name of class match module
class modulenameViewList extends ViewList{
// where clause that will be inserted in sql query
var $where = 'like 'htc'';
function modulenameViewList()
{
parent::ViewList();
}
/*
* Override listViewProcess with addition to where clause to exclude project templates
*/
function listViewProcess()
{
$this->lv->setup($this->seed, 'include/ListView/ListViewGeneric.tpl', $this->where, $this->params);
echo $this->lv->display();
}
}
?>

Related

EasyAdmin 3 create custom field

I'd like to create custom autocomplete field with externe api call.
I'm using doc Create custom fields
But my template is not used.
public static function new(string $propertyName, ?string $label = null): self
{
return (new self())
->setProperty($propertyName)
->setLabel($label)
// this template is used in 'index' and 'detail' pages
->setTemplatePath('admin/field/address.html.twig')
// this is used in 'edit' and 'new' pages to edit the field contents
// you can use your own form types too
->setFormType(TextType::class)
->addCssClass('field-address')
// these methods allow to define the web assets loaded when the
// field is displayed in any CRUD page (index/detail/edit/new)
->addCssFiles('js/admin/field-address.css')
->addJsFiles('js/admin/field-address.js')
;
}
I've no error.
I create template in : /templates/admin/field
Anyone has an idea ?

filter records in popup list view if assigned user is login SUITECRM

I want to filter records so that the assigned user can only see the records that are assigned to him from the popup list view.
The reason why I'm not doing this in the roles management is because if I assigned a user to a client record then other users that have the same role wouldn't able to see it so I've set the role->list tab to "all" and added custom code in list view that only the login user can see their own records.
Here's what I've done.
<?php
require_once('include/MVC/View/views/view.popup.php');
class AccountsViewPopup extends ViewPopup
{
public function display()
{
parent::display(); // TODO: Change the autogenerated stub
require_once 'modules/ACLRoles/ACLRole.php';
$ACLRole = new ACLRole();
$roles = $ACLRole->getUserRoles($GLOBALS['current_user']->id);
if (in_array('User1', $roles)) {
global $db, $current_user;
$this->where .= " AND accounts.assigned_user_id = '$current_user->id' AND deleted=0 ";
}
}
}
But i get this error:
Undefined property: AccountsViewPopup::$where
For list view only: custom/modules/MODULE_NAME/views/view.list.php
and following is the helping code:
require_once('include/MVC/View/views/view.list.php');
class MODULE_NAMEViewList extends ViewList {
function listViewProcess() {
global $current_user;
$this->params['custom_where'] = ' AND module_name.name = "test" ';
parent::listViewProcess();
}
}
For list and popup view(both):
You need to change the logic inside create_new_list_query function which actually prepares a query. Some modules have override it a bean level(e.g. see modules/Leads/Lead.php).
If you want to override it in upgrade safe manner then create a file in custom directory e.g: custom/modules/Leads/Lead.php, then extend it from the core bean class like following:
<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
require_once('modules/Leads/Lead.php');
class CustomLead extends Lead {
function create_new_list_query($order_by, $where,$filter=array(),$params=array(), $show_deleted = 0,$join_type='', $return_array = false,$parentbean=null, $singleSelect = false, $ifListForExport = false)
{
// Code from create_new_list_query in and then modify it accordingly.
}
}
Register new bean class in this location: custom/Extension/application/Ext/Include/custom_leads_class.php and registration code will look like following:
<?php
$objectList['Leads'] = 'Lead';
$beanList['Leads'] = 'CustomLead';
$beanFiles['CustomLead'] = 'custom/modules/Leads/Lead.php';
?>
I know this has been answered, but decided to post my solution anyway. I had almost the same problem some time ago (7.10.7).
PopupView has method getCustomWhereClause() which you can implement in your custom view.
It has to return containing string with the conditions.
Example:
custom/modules/Meetings/views/view.popup.php
/*class declaration and other stuff*/
protected function getCustomWhereClause()
{
global $current_user;
return " ( {$this->bean->table_name}.assigned_user_id='{$current_user->id}') ";
}
Remember to leave at least one space at the start and the end because SuiteCRM actually forgets to add it and it may result in broken query (but it's fairly easy to find in logs).

REST Api with QueryParamAuth authenticator - Yii2

I'm trying to create rest api for my application to get the data in my android app. This is my controller
<?php
namespace api\modules\v1\controllers;
use yii\rest\ActiveController;
use yii\filters\auth\QueryParamAuth;
/**
* Tk103 Controller API
*/
class Tk103Controller extends ActiveController
{
public $modelClass = 'api\modules\v1\models\Tk103CurrentLocation';
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => QueryParamAuth::className(),
];
return $behaviors;
}
}
I added access_token column in my user table, implemented findIdentityByAccessToken() in User Model and calling this URL
http://localhost:7872/api/v1/tk103s?access-token=abcd
This is working great and returning data if and only if access_token matches with any single user in the table.
I checked QueryParamAuth class and found that QueryParamAuth::authenticate() returns $identity after successful authentication.
Currently this url is returning whole data of my table.
What I want is(after authentication):
Get user id/username of the requester.
Based on that id/username, the data related to him as per relations of tables in db. (currently whole rows are being returned but I want only few that are matching with the current requester/user)
I tried but didn't getting any clue to catch returned $identity of user after authentication.
And I know it is possible too to make this work. Help me out folks to create magic.
Get user id/username of the requester.
That user instance you did return within the findIdentityByAccessToken method should be accessible any where inside your app within Yii::$app->user->identity. And should hold all the attributes retreived from DB. here is a quick example of using it to check access within the checkAccess method of the ActiveController class:
public function checkAccess($action, $model = null, $params = [])
{
// only an image owner can request the related 'delete' or 'update' actions
if ($action === 'update' or $action === 'delete') {
if ($model->user_id !== \Yii::$app->user->identity->id)
throw new \yii\web\ForbiddenHttpException('You can only '.$action.' images that you\'ve added.');
}
}
Note that the checkAccess is by default an empty method that is manually called inside all the built-in actions in ActiveController. the Idea is to pass the action ID and the model instance to it just after retrieving it from DB and before modifying it so we can do extra checks. If you just need to perform checks by actions ID then yii\filters\AccessControl may be enough but inside checkAccess you are expecting to also get the model instance itself so it is important to note that when building your own actions or overriding existing onces. be sure to manually invoke it the same way it is done in UpdateAction.php or DeleteAction.php.
whole rows are being returned but I want only few .. matching with .. current requester/user
It depends on how your data is structured. You can override ActiveController's actions to filter results before outputting them, it can be handled in the related SearchModel class if you are using one or it can be handled in model. A quick tip may be by simply overriding the find method inside your model:
public static function find()
{
return parent::find()->where(['user_id' => Yii::$app->user->getId()]); // or Yii::$app->user->identity->id
}
Note that this works only when using ActiveRecord. Which means when using this:
$images = Image::find()->all();
The find method we just overriden will be filtered by default by always including that where condition before generating the DB query. Also note the default built-in actions in ActiveController are using ActiveRecords but if you are using actions where you are constructing the SQL queries using the Query Builder then you should manually do the filtering.
The same can be done if using ActiveQuery (maybe better explained here) by doing this:
public static function find()
{
$query = new \app\models\Image(get_called_class());
return $query->andWhere(['user_id' => Yii::$app->user->getId()]);
}

TYPO3 4.5: How to read constraint(s) in query

I need to use a REST service in order to get some data to a plugin. In order to do so, I have overriden the normal backend interface in typoscript with the following command :
objects.Tx_Extbase_Persistence_Storage_BackendInterface.className = Tx_extensionname_Persistence_Storage_RestBackend
This BackendInterface then returns Query Objects in my repository when I use to following:
Ex:
$query = $this->createQuery();
$query = $query->execute()->toArray();
Here, $query holds the response from the service as a TYPO3 Tx_Extbase_Persistence_QueryInterface object.
The problem is that I need to be able to do a call to the service while passing an ID parameter (appending to the endpoint with /ID). Ideally, I would do it in such a way that this repo function (called in the controller) would return what I want :
public function findById( $id ) {
$query = $this->createQuery();
$query->matching($query->equals('id', $id));
return $query->execute()->toArray();
}
The problem is that I need to be able to access the query constraint within my Tx_extensionname_Persistence_Storage_RestBackend. Normally, I would use the '$query->getConstraint()' method. However, we are using typo3 4.5 and this function is not yet defined for Tx_Extbase_Persistence_QueryInterface.
Modifying the typo3 core to add this function is not an option.
I tried to extend the Query Interface to add this functionnality in a subclass in order to then override the class in typoscript but then realized this wouldn't be portable enough. I need to be able to access the query constraint only using typo3 4.5 native functionnalities.
Well I fixed it. The only thing needed to do was :
Tx_Extbase_Persistence_QueryInterface.className = Tx_MyExtension_Persistence_RestQuery
class Tx_MyExtension_Persistence_RestQuery extends Tx_Extbase_Persistence_Query implements Tx_MyExtension_Persistence_RestQueryInterface
{
}
interface Tx_MyExtension_Persistence_RestQueryInterface extends Tx_Extbase_Persistence_QueryInterface {
public function getConstraint();
}

Symfony: How to hide form fields from display and then set values for them in the action class

I am fairly new to symfony and I have 2 fields relating to my table "Pages"; created_by and updated_by. These are related to the users table (sfGuardUser) as foreign keys. I want these to be hidden from the edit/new forms so I have set up the generator.yml file to not display these fields:
form:
display:
General: [name, template_id]
Meta: [meta_title, meta_description, meta_keywords]
Now I need to set the fields on the save. I have been searching for how to do this all day and tried a hundred methods. The method I have got working is this, in the actions class:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form_params = $request->getParameter($form->getName());
$form_params['updated_by'] = $this->getUser()->getGuardUser()->getId();
if ($form->getObject()->isNew()) $form_params['created_by'] = $this->getUser()->getGuardUser()->getId();
$form->bind($form_params, $request->getFiles($form->getName()));
So this works. But I get the feeling that ideally I shouldnt be modifying the web request, but instead modifying the form/object directly. However I havent had any success with things like:
$form->getObject()->setUpdatedBy($this->getUser()->getGuardUser());
If anyone could offer any advice on the best ways about solving this type of problem I would be very grateful.
Thanks,
Tom
After processing and saving the form you could set those fields on the object and re-save:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form->bind($request->getParameter($form->getName()));
if ($form->isValid())
{
$page = $form->save();
$user = $this->getUser()->getGuardUser();
$page->setUpdatedBy($user);
if (empty($page->created_by))
{
$page->setCreatedBy($user);
}
$page->save();
$this->getUser()->setFlash('notice', 'Successfully saved page.');
$this->redirect('#homepage');
}
}
There's also a Doctrine extension called Blameable that automatically sets edited_by and created_by fields on specified models. The Doctrine website is undergoing some reorganization but here is the cached page for the extension.
To process your form create a new object, set the fields then save.
$article = new Article();
$article->setName($request->getParameter($form->getName());
$article->setDescription($request->getParameter($form->getDescription());
$article->setMetaKeywords($request->getParameter($form->getMetaKeywords());
$article->save();
What you want to do is customize your form and unset the 'created_at' and 'updated_at' pieces of the form in configure
class SampleForm extends BaseSampleForm
{
public function configure()
{
unset(
$this['created_at'],
$this['updated_at']
);
}
}
Then they won't show up in the form and will get the values setup by the "Timestampable" behavior before being saved
http://stereointeractive.com/blog/2010/04/07/symfony-forms-hide-created_at-updated_at-columns/