Apex Tip: Create a Knowledge Base Article from Apex

Backgound

If you worked with Salesforce Knowledge Base Articles in Apex, I would know that so many objects and restrictions that make that feature really difficult to rich a deep customization. 

As you can read in the official Doc you have to handle many tables related to Articles:
  • Article Type__DataCategorySelection Object A data category selection represents a data category that classifies an article.
  • Article Type__ka Object Gives access to an article from a specific article type independent of its version. This object is read–only and can’t be used in a SOQL clause or in a WITH DATA CATEGORY DataCategorySpec SOSL clause. For more information, see KnowledgeArticle.
  • Article Type__kav Object Gives access to all articles from a specific article type depending on their version. This object gives access to the fields available in KnowledgeArticleVersion. For more information, see KnowledgeArticleVersion.
  • Article Type__Feed Object Represents a single feed item in the feed displayed on the detail page for an article.
  • Article Type__ViewStat Object Provides statistics on the number of views for an article from a specific article type. For more information, see KnowledgeArticleViewStat.
  • Article Type__VoteStat Object Provides the weighted rating for an article from a specific article type on a scale of 1 to 5. For more information, see KnowledgeArticleVoteStat.
  • CaseArticle Object Represents the association between a Case and a KnowledgeArticle.
  • FeedComment Object Represents a comment added to a feed by a user.
  • FeedItem Object FeedItem represents an entry in the feed, such as changes in a record feed, including text posts, link posts, and content posts.
  • KnowledgeArticle Object Gives access to an article independent of its version. This object is read–only and can’t be used in a SOQL clause or in a WITH DATA CATEGORY DataCategorySpec SOSL clause.
  • KnowledgeArticleVersion Object Provides a global view of standard article fields across all article types depending on their version.
  • KnowledgeArticleViewStat Object Provides statistics on the number of views for the specified article across all article types.
  • KnowledgeArticleVoteStat Object Provides the weighted rating for the specified article on a scale of 1 to 5 across all article types.
  • NewsFeed Object Represents a single feed item on a user’s home tab. A Chatter feed shows recent changes to records that the user is following.
  • UserProfileFeed Object Represents a user profile feed, which tracks all actions by a user on records that can be tracked in a feed. This feed is displayed on the user profile page.
This week I had to create a REST web service to expose some FAQ articles to an external web site. That is not a big deal because you only have to query the ArticleType__kav object. The only tricky part there is to include the Language and PublishStatus in the Where clause.
Let me show you an example, if the ArticleType is FAQ, the query should be something like:

Create an Article from Apex.

After create the web service I had to create the Test Class (I really create it before ;)) I faced the problem to create the article from Apex.
After spend some time googling what table should I insert the article and what order I figured out that it is really easy. I only needed insert the article in FAQ__kav and SFDC trigger the insertion of the rest related records.
So, this is the TestHelper I made to create an Article:
More about the publishing service here.
Enjoy :)

Apex Tip: How to make a DML operation in a trigger After insert/update

Many times I’ve faced requirements to write a field in a trigger after the record is inserted or update. So, naturally I’ve tried something like this:

But there the record is read only and if you try to change a field value this exception will be fired:

execution of AfterInsert caused by: System.FinalException: Record is read-only

The workaround is quite simple. The object contained by the global trigger.new is read-only, but you can create a new object referring the same ID and change the value that you need.

In addition you have to avoid the recursion since you are changing the record the trigger will be fired again. To avoid that you have to use a static flag which says that the trigger has been already executed during the current executing context.

So, the final code should be like this:

Enjoy :)

Tip: the simplest way to list all objects

Since SFDC contains variable objects (custom and standard) we have many times to list them.

This is a simple snippet to do it.

Tip Apex: get SObject Type from Id

This is a really piece of cake apex snippet. Extremely useful when you are developing generic methods.

Tip Apex: Select * from X on apex (SOQL)

I’ve faced many times two problems on SOQL queries:

1. They have not * (star) operator and hence it is really tough to list all fields on large objects.
2. If you try to modify a field name or delete or update the type, salesforce won’t allow you if it is referenced on the code. It is really painful on deploys.

As a best practices when I have to retrieve all fields I use this simple function.

Apex Tip: check if field exists on SObject

This small function check if any SObject contains a field, really useful on many cases.

For instance if you want to know if country Picklist is active, you could check countryCode field active.

Other approach using JSON serializer

Sample use: