Thursday, October 13, 2016

Salesforce: Obtaining Current User

Apex: 
Id userId = UserInfo.getUserId();
 
Visual Force Page:
{!$User.Id}
{!$User.FirstName}
etc. 

Tuesday, October 11, 2016

GIT: Creating Branches

git checkout -b branch_name

git push -u remote-name branch-name

git pull branch-name

Monday, September 26, 2016

SUGAR CRM: Retrieving Relationships Programatically in Logic Hooks

1. Create Logic Hook Trigger in your corresponding module (Assume this is a before_save trigger)
 
$hook_array['before_save'][] = 
 Array(     
       1,     
       'Some Description',     
       'custom/modules/<your_module>/<your_file_name>.php', 
       '<your_class_name>',     
       '<your_method_name>'
 );
   
2. Create class and logic

class <your_class_name>
{ 
   public function <your_method_name>($bean, $event, $args) 
   {         
      try         
      { 
         if (isset($bean->fetched_row['id'])) 
         {
             // Assume we're using documents
             $bean->load_relationship("documents");         
             foreach($bean->documents->getBeans() as $doc)
             {                     
                $GLOBALS['log']->fatal($doc->category_id);
             } 
         } 
      }              
      catch (Exception $ex) 
      {             
          $GLOBALS['log']->fatal($ex->getTraceAsString()); 
      } 
   } 
}
 
NOTE: Make sure you're retrieving the correct relationship name.
A common mistake is to grab the relationship name from Studio under
Admin. Try to obtain the relationship name from 
cache\modules\<your_module>\<your_module>vardefs.php

Finally, get the array name value not the relationship value:
'documents' => array  
(   
   'name' => 'documents', 
   'type' => 'link',   
   'relationship' => 'documents_opportunities', 
   'source' => 'non-db',   
   'vname' => 'LBL_DOCUMENTS_SUBPANEL_TITLE',
 ),
 
In this case we need "documents" and not "documents_opportunities"
for the relationship name. 

Wednesday, September 21, 2016

JavaScript: Replacing All Instances of a Character

Let's assume that we want to replace all hyphens with blank spaces.

We can either loop through the string character by character until we replace all hyphens,
or we can create a regular expression as follows:

var myStr = 'This-is-a-test';
var replacedString = myStr.replace(/-/g, ' ');
Where g represents a global match.

Friday, September 16, 2016

JavaScript: Creating Objects

function myObject()
{
    this.myField1= true;
    this.myField2= new Array();
}

var obj1= new myObject();
obj1.myField1 = false;
obj1.myField2.push('value');

JavaScript: Using a Map Data Structure

var myMap = {};

myMap['key1'] = 'value1';
myMap['key2'] = 'value2';

for (var key in myMap) 
{
   if(myMap[key] == 'value1'){...}
}

jQuery: Replacing All Blank Spaces in a String

var myVar= j$( "#myId option:selected" ).text().replace(/\s+/g, " ");

jQuery: Getting Selected Option

j$( "#myId option:selected" ).text();

jQuery: Traversing All Rows Except Table Headers

j$('#lineItemsTable > tbody > tr').not('thead tr').each(function()
{
     // logic here
});

Wednesday, August 17, 2016

MAGENTO: Updating Base URLs

update core_config_data set value = 'http://domainname/'
where path = 'web/unsecure/base_url';

update core_config_data set value = 'http://domainname/'
where path = 'web/secure/base_url';

Wednesday, August 10, 2016

MAGENTO: Disabling All Email Communications

  • Login to Magento backend
  • Go to the System->Configuration menu.
  • On the left hand menu under the Advanced tab (at the bottom) select the System menu item.
  • Select ‘Mail Sending Settings’ from the selection on the right hand side.
  • Set Disable email communications to ‘Yes’, then no email will send through Magento.

MAGENTO: Creating an Admin User


ADMIN USER:
insert into admin_user
select
(select max(user_id) + 1 from admin_user) user_id,
'FIRSTNAME' first_name,
'LASTNAME' last_name,
'TEST@EMAIL.COM' email,
'USERNAME' username,
MD5('PASSWORD') password,
now() created,
NULL modified,
NULL logdate,
0 lognum,
0 reload_acl_flag,
1 is_active,
(select max(extra) from admin_user where extra is not null) extra,
NULL,
NULL;

ADMIN ROLE:
insert into admin_role
select
(select max(role_id) + 1 from admin_role) role_id,
(select role_id from admin_role where role_name = 'Administrators') 
parent_id, 2 tree_level, 0 sort_order, 'U' role_type,
(select user_id from admin_user where username = 'USERNAME') user_id,
'USERNAME' role_name;

Tuesday, July 12, 2016

JSON: Invalid UTF-8 middle byte

Assume you have the following JSON:
 
{
     "myObject" :
{
"name" : "resumé"
}
}
 
If you run this with your favorite JSON parser, you may get the following error:

[{"message":"Invalid UTF-8 middle byte 0x65 at [line:.., column:..]","errorCode":"JSON_PARSER_ERROR"}]

To solve this, you will either need to update your parser to only accept UTF (8, 16, or 32), or escape the especial characters (i.e. \u00E9 for é)

As a test, you can try this:

{
     "myObject" :
{
"name" : "resum\u00E9"
}
}

Thursday, June 30, 2016

APEX: Compare Old and New Values in a Trigger

// Inside your trigger handler
public static void onBeforeUpdate()
{
    try
    {
       for(Account acct : Trigger.new)
       {
           Account oldAccount = Trigger.oldMap.get(acct.Id);
    
          if(oldAccount.FirstName != acct.FirstName)
          {
               // Value Changed 
          }
       }
    }
   catch(Exception ex)
   {
       system.debug(ex.getMessage() + '  ' + ex.getStackTraceString()); 
   }
}

Monday, June 27, 2016

SUGAR CRM 7: Bulkified POST Service using a custom API

1. Please take a look at the previous Post: http://programmersrealm.blogspot.com/2016/06/sugar-crm-7-creating-custom-api.html

2. Change reqType to 'POST'

3. Change path to array("Accounts", "PostExample")

4. Change method to 'MyPost'

5. Create mehtod MyPost()
public function MyPost($api, $args) 
{
    if (empty($args)) 
    {        
      return false; 
    } 
    $results = array(); 
    foreach ($args as $module => $records) 
    {        
      if (is_array($records)) 
      { 
        foreach ($records as $fieldsArray) 
        {                
          $sugarBean = 
           $this->create($module, $fieldsArray);                
          $results[$module][] = $sugarBean->id; 
        } 
      } 
    } 
    return $results; 
}

private function create($module, $fieldsArray) 
{    
    $sugarBean = BeanFactory::newBean($module);
    if (is_null($sugarBean)) 
    {        
      return null; 
    }    
    foreach ($fieldsArray as $field => $data) 
    {        
      $sugarBean->$field = $data; 
    }    
    $sugarBean->save(); 
    return $sugarBean; 
}

6. Add your url to Postman with the new endpoint (i.e. http://<my path>/rest/v10/Accounts/PostExample) with POST as the service

7. Add Authorization Token to Postman (if noauthorizationrequired is set to true, there's no need to add a token)

8. Create JSON data and put it under Body in Postman
{
"Accounts":
    [
        {
            "id" : "edf5e66e-6a2a-ccb3-d0bc-577142ee65ca",
            "name":"Testing10",
            "billing_address_city" : "ELP"
        },
        {
            "id" : "682d8dce-d397-85ce-7cc3-57714287c485",
            "name":"Testing3",
            "billing_address_city" : "PHX"
            
        },
        {
            "id" : "7de85759-0203-7a1c-240e-57714241b289",
            "name":"Testing2",
            "billing_address_city" : "LA"
            
        }
    ]
}

SUGAR CRM 7: Creating a Custom API

1. Add your php class under custom/modules/<module>/clients/base/api for specific module extensions or clients/base/api for custom api calls

2. Override registerApiRest() and add your API customization.
public function registerApiRest() 
{   
    return array(       
           'MyGet' => array(           
              'reqType' => 'GET',
              'path' => array('Accounts', 'GetExample'),
              'pathVars' => array('', ''),           
              'method' => 'MyGet',           
              'shortHelp' => 'An Example of a GET endpoint',
              'longHelp' => '',        )
    );
}
 
3. Add your MyGet method
public function MyGet($api, $args){
    return "Hello World!";}
 
4. Final Code
<?php
if(!defined('sugarEntry') ||
!sugarEntry) die('Not A Valid Entry Point');

class MyEndpointsApi extends SugarApi
{
   public function registerApiRest()
   {
     return array(            
       'MyGet' => array(                
         'reqType' => 'GET',                
         'path' => array('Accounts', 'GetExample'),                
         'pathVars' => array('', ''),                
         'method' => 'MyGet',                
         'shortHelp' => 'An Example of a GET endpoint',                
         'longHelp' => '',
       )
     );
   }
 
   public function MyGet($api, $args)
   {return "Hello World!";}

5. Test your API call (I suggest POSTMAN for Chrome)
    

Friday, June 24, 2016

SUGAR CRM 7: Updating Model inside Ajax

var self = this;
// more logic here
$.ajax({
    beforeSend: function (request) {
        request.setRequestHeader("OAuth-Token", your token);
    },
    type: "PUT",
    data: JSON.stringify({"status": "Closed"}),
    dataType: "json",
    url: 'your url',
    success: function (data)
    {
        // more logic here
        self.model.set('status', 'Closed');
    }
}); 

jQuery AJAX: HTTP API Requests requiring OAuth Token

$.ajax({
    beforeSend: function(request) {
        request.setRequestHeader("OAuth-Token", your token);
    },
    type: "PUT",
    data: JSON.stringify({
        "status": "Closed"
    }),
    dataType: "json",
    url: 'your url',
    success: function(data) {
     // your logic here
    }
});

Friday, June 3, 2016

PHP: External Service Sends JSON Format to your API Method

If you have an external service sending information over to your PHP server as JSON or XML, you can capture the response as follows:

$postResult = file_get_contents('php://input');
$payload = json_decode($postResult, true);

PHP: XML File Reading using Simple XML

The simplest solution is to load the file and process the xml nodes as follows:

$xml = simplexml_load_file('myfile.xml');

$node1 = $xml->child1;

$node2 = $xml->child2;


However, in some instances the resulting xml is either blank or empty. In this case, we need to call the following method:

$xml = simplexml_load_file('myfile.xml');

echo $xml->asXML();


If none of the above steps work, we need to create a Simple XML Element as follows:


$content = file_get_contents($fileName);

$xml = new SimpleXMLElement($content);
$node1 = $xml->child1;

If you still have issues after all this, typecast the node values:

$node1 = (string)$xml->child1;


Sample XML: myfile.xml
<root>

   <child1>Child 1</child1>

   <child2>Child 2</child2>

</root>

Wednesday, June 1, 2016

GIT: HTTPS Repository Error

If you get the following error while pushing to a specific remote repository: The requests URL returned error: 401 Unauthorized while accessing https:...

Try adding the repository as follows first then push:

git remote add origin https://yourname@bitbucket.org/yourorg/yourrepository
......
git push -u origin

GIT: Remove Origin from Git Repository

In case you accidentally added an incorrect remote or you want to switch from ssh to https or vice versa, you can try the following command:

git remote rm origin

GIT: Configure Global User

In case you need to set up both the global user name and email in git, you need to provide the following commands:

git config --global user.name "Your Name"

git config --global user.email you@example.com

Please be careful when executing the above commands as these will override the current settings.

In case you want to commit/push as a different user without affecting the global settings, you can try:

git commit --amend --author='Your Name <you@example.com>'

For more information on git Commands: https://git-scm.com/docs

GIT: From an Existing Project

cd /path/to/my/repogit remote add origin git@bitbucket.org:myorg/myrepository.git(or git remote add origin https://bitbucket.org/myorg/myrepository) in case you use httpsgit push -u origin --all # pushes up the repo and its refs for the first timegit push origin --tags # pushes up any tags
More info from BitBucket

GIT: Creating a GIT Repository From Scratch

Set up your local directory

mkdir /path/to/your/projectcd /path/to/your/projectgit initgit remote add origin git@bitbucket.org:myorg/myrepository.git (or git remote add origin https://bitbucket.org/myorg/myrepository) in case you use https

Create your first file, commit, and push

echo "My Text" >> contributors.txtgit add contributors.txtgit commit -m 'Initial commit with contributors'git push -u origin master

You can also find this information when creating a new repository from BitBucket [1].[1] https://bitbucket.org

Tuesday, May 31, 2016

APEX: Access History Programatically

For Standard Objects:
AccountHistory
ContactHistory
OpportunityHistory

For Custom Objects:
MyCustomObject__History

Example:
1. Select Id, Name, (Select OldValue, NewValue From Histories) From MyObject__c [1]

2. Select ParentId, OldValue, NewValue, Field, CreatedById, CreatedDate From MyObject__History [2]

[1] http://salesforce.stackexchange.com/questions/17057/how-to-track-history-of-a-record-of-a-custom-object-in-apex-classhttp://salesforce.stackexchange.com/questions/17057/how-to-track-history-of-a-record-of-a-custom-object-in-apex-class

[2] https://developer.salesforce.com/forums/?id=906F0000000937RIAQ

APEX: Access Sharing Programatically

For Standard Objects:
AcountShare
ContactShare
OpportunityShare
.......

For Custom Objects:
MyCustomObject__Share

Properties:
AccessLevel
ParentID
RowCause
UserOrGroupdId

Examples:
MyCustomObject__Share myObj = new MyCustomObject__Share();

myObj.AccessLevel = 'Read';

myObj.ParentID = someId;

myObj.RowCause = Schema.MyCustomObject__Share.Manual;

myObj.UserOrGroupId = someUserOrGroupId;

For more information: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_bulk_sharing_creating_with_apex.htm

Friday, May 27, 2016

APEX: Web Service Callouts using WebServiceMock

1. Implement the WebServiceMock 

@isTest
global class MyWebServiceCalloutMock implements WebServiceMock
{
    // Need to override this method
    global void doInvoke(
                   Object stub,
           Object request,
           Map<String, Object> response,
           String endpoint,
           String soapAction,
           String requestName,
           String responseNS,
           String responseName,
           String responseType)
    {
        try
        {
             MyService.myElement test = MyService.MyElement();
             MyElement.Result = 'Test';
       response.put('response_x', test); 
        }
        catch(Exception ex)
        {
           system.debug(ex.getMessage() + ' ' + ex.getStackTraceString());
        }
        return res;
     }
}


2. Create the test class
@isTest
public class WebServiceTest 
{
     public static testMethod void testRestGetService() 
     {
        try
        {
           Test.startTest();
             Test.setMock(WebServiceMock.class, new MyWebserviceCalloutMock());
        
             String response = MyCalloutClass.processService('Test');
        
             // provide your assertions here

           Test.stopTest();
        }
        catch(Exception ex)
        {
           system.debug(ex.getMessage() + ' ' + ex.getStackTraceString());
        }
    }
}
This is the sample Callout Class public class MyCalloutClass { public static String processService(String input) {
        try
        {
          MyService.MyElement elm = new MyService.MyElement();
          elm.endpoint_c = 'your endpoint url';
          return elm.myServiceMethod(input);
        }
        catch(Exception ex)
        {
           system.debug(ex.getMessage() + ' ' + ex.getStackTraceString()); 
        }
        return '';
    }
}

This is a sample generated class
public class MyService
{
    public class MyElement
    {
       public static String Result;
       public String myServiceMethod(String input)
       {
           // Autogenerated code here
       }
    }
}

You can find more information to the original article here: 
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_wsdl2apex_testing.htm

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts_wsdl2apex_gen_code.htm

APEX: HTTP Callouts Testing using HttpCalloutMock

So far, we have seen a simple way for testing REST services in a single test method http://programmersrealm.blogspot.com/2016/05/creating-tests-for-rest-services-in.html

However, there may be times when we don't want to hit the actual server. Isolating our testing in our environment is ideal and crucial to catch any errors before testing in the real environment.

As a best practice, we can use the HttpCalloutMock Interface that Salesforce provides out of the box.
This will help us provide fake responses in our test class.

1. Implement the HttpCalloutMock

@isTest
global class MyHttpCalloutMock implements HttpCalloutMock
{
    // Need to override this method
    global HTTPResponse respond(HTTPRequest req)
    {
        try
        {
           HttpResponse res = new HttpResponse();
           res.setHeader('Content-Type', 'application/json');
           res.setBody('{"myvar":"myvalue"}');
           res.setStatusCode(200);
        }
        catch(Exception ex)
        {
           system.debug(ex.getMessage() + ' ' + ex.getStackTraceString());
        }
        return res;
     }
}


2. Create the test class
@isTest
public class RestServiceTest 
{
     public static testMethod void testRestGetService() 
     {
        try
        {
           Test.startTest();
             Test.setMock(HttpCalloutMock.class, new MyHttpCalloutMock());
        
             HttpResponse res = MyCalloutClass.processGetService();
        
             // provide your assertions here

           Test.stopTest();
        }
        catch(Exception ex)
        {
           system.debug(ex.getMessage() + ' ' + ex.getStackTraceString());
        }
    }
}
This is the sample Callout Class public class MyCalloutClass { public static HttpResponse processGetService() { try { HttpRequest req = new HttpRequest(); req.setEndpoint('http://yourendpoint/myvar/myvalue'); req.setMethod('GET'); Http h = new Http(); HttpResponse res = h.send(req); } catch(Exception ex) { system.debug(ex.getMessage() + ' ' + ex.getStackTraceString()); } return res; } }

You can find more information to the original article here: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restful_http_testing_httpcalloutmock.htm

Friday, May 20, 2016

APEX: Mixed DML Operations Error

You get the following exception or similar: "Insert failed. First exception on row 0; first error: MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa): User, original object:  Product2"

In this case, you need to enclose your setup object in a system.runAs() operation as follows:

system.runAs(new User(Id = UserInfo.getUserId())) 
{
    ...your setup-object DML...
    User usr = new User();
    usr.UserName = 'Test';
    .....
    insert usr;
}

Thursday, May 19, 2016

APEX: Instantiating a Constructor with a StandardController Parameter in a Test Class

Suppose you have the following class:

public with sharing class MyClass {
public MyClass(ApexPages.StandardController con) { try { if(con != null) { // your sObject and any other logic here Account acct = (Account)con.getRecord(); } } catch(Exception ex) { system.debug(ex.getMessage() + ' ' + ex.getStackTraceString()); } } public void myMethod(){} }

Then in your test class:
public static testMethod void testMyClass() { try { Test.startTest(); // Create sObject in your own factory class List<Account> accts = TestFactory.createSObject('Account', 1, true); system.assertEquals(accts.size(), 1); PageReference pr = Page.MyPage; Test.setCurrentPageReference(pr);
        ApexPages.currentPage().getParameters().put('qp', 'yyyy');
MyClass mc = new MyClass(new ApexPages.StandardController(accts.get(0))); Test.stopTest(); } catch(Exception ex) { system.debug(ex.getMessage() + ' ' + ex.getStackTraceString()); } }

Tuesday, May 17, 2016

jQuery: DOM Element not loaded even when using $(document).ready()

DOM Element may not be loaded yet due to an external library being used, or the page loading time is taking too long. 

I'm not a big fan of timeouts, but if you have a better solution, please let me know.


Solution:
Check if the element is loaded, if not, set a timeout to load the element.


<script> jQuery(document).ready(getUsers); function getUsers() { var elm = jQuery(".leftPanel").find("#rowheader0"); if (elm[0]) { alert(jQuery(".leftPanel").find("#rowheader0").text()); } else { // Wait a bit longer setTimeout(getUsers, 50); } } </script>

APEX: Creating Tests for Rest Services in Apex using GET

Suppose you have the following rest service in your org:

@HttpGet global static Object getObject() { Map<String, String> paramMap = RestContext.request.params; String param1Value = paramMap.get('param1'); }

How do you test the above code snippet?
In your test class, you need to provide the parameters as follows:

// Initialize both response and request from the service to be called
RestRequest rReq = new RestRequest(); RestResponse rRes = new RestResponse(); // The Service we want to access rReq.requestURI = url.getSalesforceBaseUrl().toExternalForm() + '/MyRestServiceURL/'; // The parameter(s) we want to pass to the service rReq.addParameter('param1', 'some value'); // Service method rReq.httpMethod = 'GET'; // Service Context objects ready RestContext.request = rReq; RestContext.response = rRes; // Call Service Object myObj = MyRestService.getObject();