├── Add a Mobile Card that Displays Content Based on Opportunity Stage
└── OpportunityStageTips.vfp
├── Add a Visualforce Page for a Contact Record Action
└── ShowAssistantInfo.vfp
├── Create a Form to Enter New Items
├── README.md
├── campingHeader.cmp
├── campingList.cmp
├── campingListController.js
└── campingListItem.cmp
├── Create a Global Action that Displays a User's Business Card Information
└── BusinessCard.vfp
├── Create a Selector class for the Account object
├── AccountsSelector.apxc
└── fflib_SObjectSelector.cls
├── Create a Visualforce Page
├── EmailMissionSpecialist.apxc
└── StationCheck.vfp
├── Create a Visualforce form which inserts a basic Contact record
└── CreateContact.vfp
├── Create a Visualforce page displaying new cases
├── NewCaseList.vfp
└── NewCaseListController.apxc
├── Create a Visualforce page that shows user information
└── DisplayUserInfo.vfp
├── Create a Visualforce page which displays a variety of output fields
└── OppView.vfp
├── Create a Visualforce page which shows a basic Contact record
└── ContactView.vpf
├── Create a Visualforce page which shows a list of Accounts linked to their record pages
└── AccountList.vfp
├── Create a mobile-friendly Visualforce page using SLDS
└── MobileContactList.vpf
├── Create a simple Visualforce page that displays an image
└── displayImage.vfp
├── Create an Apex class that returns Account objects
└── AccountUtils.apxc
├── Create an Apex class that returns both contacts and leads based on a parameter
├── ContactAndLeadSearch.apex
└── debug_console.apex
├── Create and deploy a custom big object
├── Rider_History__b.object
├── package.xml
└── rider_history.permissionset
├── Implement a basic Domain class and Apex trigger
├── Accounts.apxc
├── AccountsTrigger.apxt
└── fflib_SObjectDomain.cls
├── Refactor Components and Communicate with Events
├── README.md
├── addItemEvent.evt
├── campingList.cmp
├── campingListController.js
├── campingListForm.cpm
├── campingListFormController.js
├── campingListFormHelper.js
└── campingListHelper.js
├── Save and Load Records with a Server-Side Controller
├── CampingListController.cls
├── CampingListController.js
├── README.md
├── campingList.cmp
└── campingListHelper.js
├── Subscribe to a Platform Event in an Apex Trigger
└── OrderEventTrigger.apex
├── Use Apex Metadata API to add a custom field to a page layout
├── UpdateContactPageLayout.apxc
└── Use Apex Metadata API to add a custom metadata type to an org
│ └── MetadataExample.apxc
├── Use a static resource to display an image on a Visualforce Page
├── ShowImage.vfp
└── vfimagetest.zip
└── Write an Apex trigger that modifies Account fields before inserting records
├── AccountTrigger.apxt
├── AccountTriggerHandler.apxc
└── AccountTriggerTest.apxc
/Add a Mobile Card that Displays Content Based on Opportunity Stage/OpportunityStageTips.vfp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Prospecting
5 |
6 |
7 |
8 | Needs Analysis
9 |
10 |
11 |
12 | Proposal/Price Quite
13 |
14 |
15 |
16 | Negotiation/Review
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Add a Visualforce Page for a Contact Record Action/ShowAssistantInfo.vfp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
--------------------------------------------------------------------------------
/Create a Form to Enter New Items/README.md:
--------------------------------------------------------------------------------
1 | # Challenge Description
2 | **Create a Form to Enter New Items**
3 |
4 | In this challenge you'll create a form to enter new items, a list to display the items entered, and add SLDS styling. First, to make our camping list look more appealing, change the campingHeader component to use lightning:layout and SLDS. Similar to the unit, style the Camping List H1 inside the slds-page-header. Add the action:goal SLDS icon using lightning:icon.
5 |
6 | Next, modify the campingList component to contain a new item input form and an iteration of campingListItem components for displaying the items entered. Here are additional details for the modifications to the campingList component.
7 |
8 | In this challenge you'll create a form to enter new items, a list to display the items entered, and add SLDS styling. First, to make our camping list look more appealing, change the campingHeader component to use lightning:layout and SLDS. Similar to the unit, style the Camping List H1 inside the slds-page-header. Add the action:goal SLDS icon using lightning:icon.
9 |
10 | Next, modify the campingList component to contain a new item input form and an iteration of campingListItem components for displaying the items entered. Here are additional details for the modifications to the campingList component.
11 |
12 | * Add an attribute named items with the type of an array of camping item custom objects.
13 | * Add an attribute named newItem of type Camping_Item__c with default quantity and price values of 0.
14 | * The component displays the Name, Quantity, Price, and Packed form fields with the appropriate input component types and values from the newItem attribute. The Quantity field accepts a number that's at least 1.
15 | * Submitting the form executes the action clickCreateItem in the JavaScript controller.
16 | * If the form is valid, the JavaScript controller pushes the newItem onto the array of existing items, triggers the notification that the items value provider has changed, and resets the newItem value provider with a blank sObjectType of Camping_Item__c. For this challenge, place the code in your component's controller, not the helper.
17 |
18 |
--------------------------------------------------------------------------------
/Create a Form to Enter New Items/campingHeader.cmp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
Camping
9 |
My Camping
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Create a Form to Enter New Items/campingList.cmp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/Create a Form to Enter New Items/campingListController.js:
--------------------------------------------------------------------------------
1 | ({
2 | clickCreateItem : function(component, event, helper) {
3 | var validCamping = component.find('campingform').reduce(function (validSoFar, inputCmp) {
4 | // Displays error messages for invalid fields
5 | inputCmp.showHelpMessageIfInvalid();
6 | return validSoFar && inputCmp.get('v.validity').valid;
7 | }, true);
8 |
9 | if(validCamping){
10 | var newCampingItem = component.get("v.newItem");
11 | //helper.createCamping(component,newCampingItem);
12 | var campings = component.get("v.items");
13 | var item = JSON.parse(JSON.stringify(newCampingItem));
14 |
15 | campings.push(item);
16 |
17 | component.set("v.items",campings);
18 | component.set("v.newItem",{ 'sobjectType': 'Camping_Item__c','Name': '','Quantity__c': 0,
19 | 'Price__c': 0,'Packed__c': false });
20 | }
21 | }
22 | })
23 |
--------------------------------------------------------------------------------
/Create a Form to Enter New Items/campingListItem.cmp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Name:
5 |
6 |
7 |
Price:
8 |
9 |
10 |
Quantity:
11 |
12 |
13 |
Packed:
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Create a Global Action that Displays a User's Business Card Information/BusinessCard.vfp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Quick Share
5 |
{!$User.FirstName}
6 |
{!$User.LastName}
7 |
{!$User.Email}
8 |
{!$User.Phone}
9 |
{!$User.Title}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Create a Selector class for the Account object/AccountsSelector.apxc:
--------------------------------------------------------------------------------
1 | public class AccountsSelector extends fflib_SObjectSelector {
2 |
3 | public List getSObjectFieldList() {
4 | return new List {
5 | Account.ID, Account.Description, Account.Name, Account.AnnualRevenue
6 | };
7 | }
8 |
9 | public Schema.SObjectType getSObjectType() {
10 | return Account.SObjectType;
11 | }
12 |
13 | public List selectById(Set idSet) {
14 | List acctList = new List ();
15 | acctList = (List) selectSObjectsById(idSet);
16 | return acctList;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Create a Selector class for the Account object/fflib_SObjectSelector.cls:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c), FinancialForce.com, inc
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without modification,
6 | * are permitted provided that the following conditions are met:
7 | *
8 | * - Redistributions of source code must retain the above copyright notice,
9 | * this list of conditions and the following disclaimer.
10 | * - Redistributions in binary form must reproduce the above copyright notice,
11 | * this list of conditions and the following disclaimer in the documentation
12 | * and/or other materials provided with the distribution.
13 | * - Neither the name of the FinancialForce.com, inc nor the names of its contributors
14 | * may be used to endorse or promote products derived from this software without
15 | * specific prior written permission.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 | * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | **/
26 |
27 | /**
28 | * Class providing common database query support for abstracting and encapsulating query logic
29 | **/
30 | public abstract with sharing class fflib_SObjectSelector
31 | implements fflib_ISObjectSelector
32 | {
33 | /**
34 | * Indicates whether the sObject has the currency ISO code field for organisations which have multi-currency
35 | * enabled.
36 | **/
37 | private Boolean CURRENCY_ISO_CODE_ENABLED {
38 | get {
39 | if(CURRENCY_ISO_CODE_ENABLED == null){
40 | CURRENCY_ISO_CODE_ENABLED = describeWrapper.getFieldsMap().keySet().contains('currencyisocode');
41 | }
42 | return CURRENCY_ISO_CODE_ENABLED;
43 | }
44 | set;
45 | }
46 |
47 | /**
48 | * Should this selector automatically include the FieldSet fields when building queries?
49 | **/
50 | private Boolean m_includeFieldSetFields;
51 |
52 | /**
53 | * Enforce FLS Security
54 | **/
55 | private Boolean m_enforceFLS;
56 |
57 | /**
58 | * Enforce CRUD Security
59 | **/
60 | private Boolean m_enforceCRUD;
61 |
62 | /**
63 | * Order by field
64 | **/
65 | private String m_orderBy;
66 |
67 | /**
68 | * Sort the query fields in the select statement (defaults to true, at the expense of performance).
69 | * Switch this off if you need more performant queries.
70 | **/
71 | private Boolean m_sortSelectFields;
72 |
73 | /**
74 | * Describe helper
75 | **/
76 | private fflib_SObjectDescribe describeWrapper {
77 | get {
78 | if(describeWrapper == null)
79 | describeWrapper = fflib_SObjectDescribe.getDescribe(getSObjectType());
80 | return describeWrapper;
81 | }
82 | set;
83 | }
84 | /**
85 | * static variables
86 | **/
87 | private static String DEFAULT_SORT_FIELD = 'CreatedDate';
88 | private static String SF_ID_FIELD = 'Id';
89 |
90 | /**
91 | * Implement this method to inform the base class of the SObject (custom or standard) to be queried
92 | **/
93 | abstract Schema.SObjectType getSObjectType();
94 |
95 | /**
96 | * Implement this method to inform the base class of the common fields to be queried or listed by the base class methods
97 | **/
98 | abstract List getSObjectFieldList();
99 |
100 | /**
101 | * Constructs the Selector, defaults to not including any FieldSet fields automatically
102 | **/
103 | public fflib_SObjectSelector()
104 | {
105 | this(false);
106 | }
107 |
108 | /**
109 | * Constructs the Selector
110 | *
111 | * @param includeFieldSetFields Set to true if the Selector queries are to include Fieldset fields as well
112 | **/
113 | public fflib_SObjectSelector(Boolean includeFieldSetFields)
114 | {
115 | this(includeFieldSetFields, true, false);
116 | }
117 |
118 | /**
119 | * Constructs the Selector
120 | *
121 | * @param includeFieldSetFields Set to true if the Selector queries are to include Fieldset fields as well
122 | **/
123 | public fflib_SObjectSelector(Boolean includeFieldSetFields, Boolean enforceCRUD, Boolean enforceFLS)
124 | {
125 | this(includeFieldSetFields, enforceCRUD, enforceFLS, true);
126 | }
127 |
128 | /**
129 | * Constructs the Selector
130 | *
131 | * @param includeFieldSetFields Set to true if the Selector queries are to include Fieldset fields as well
132 | * @param enforceCRUD Enforce CRUD security
133 | * @param enforeFLS Enforce Field Level Security
134 | * @param sortSelectFields Set to false if selecting many columns to skip sorting select fields and improve performance
135 | **/
136 | public fflib_SObjectSelector(Boolean includeFieldSetFields, Boolean enforceCRUD, Boolean enforceFLS, Boolean sortSelectFields)
137 | {
138 | m_includeFieldSetFields = includeFieldSetFields;
139 | m_enforceCRUD = enforceCRUD;
140 | m_enforceFLS = enforceFLS;
141 | m_sortSelectFields = sortSelectFields;
142 | }
143 |
144 | /**
145 | * Override this method to provide a list of Fieldsets that can optionally drive inclusion of additional fields in the base queries
146 | **/
147 | public virtual List getSObjectFieldSetList()
148 | {
149 | return null;
150 | }
151 |
152 | /**
153 | * Override this method to control the default ordering of records returned by the base queries,
154 | * defaults to the name field of the object if it is not encrypted or CreatedDate if there the object has createdDated or Id
155 | **/
156 | public virtual String getOrderBy()
157 | {
158 | if (m_orderBy == null)
159 | {
160 | Schema.SObjectField nameField = describeWrapper.getNameField();
161 | if (nameField != null && !nameField.getDescribe().isEncrypted())
162 | {
163 | m_orderBy = nameField.getDescribe().getName();
164 | }
165 | else
166 | {
167 | m_orderBy = DEFAULT_SORT_FIELD;
168 | try {
169 | if (describeWrapper.getField(m_orderBy) == null)
170 | {
171 | m_orderBy = SF_ID_FIELD;
172 | }
173 | }
174 | catch(fflib_QueryFactory.InvalidFieldException ex) {
175 | m_orderBy = SF_ID_FIELD;
176 | }
177 | }
178 | }
179 | return m_orderBy;
180 | }
181 |
182 | /**
183 | * Returns True if this Selector instance has been instructed by the caller to include Field Set fields
184 | **/
185 | public Boolean isIncludeFieldSetFields()
186 | {
187 | return m_includeFieldSetFields;
188 | }
189 |
190 | /**
191 | * Returns True if this Selector is enforcing FLS
192 | **/
193 | public Boolean isEnforcingFLS()
194 | {
195 | return m_enforceFLS;
196 | }
197 |
198 | /**
199 | * Returns True if this Selector is enforcing CRUD Security
200 | **/
201 | public Boolean isEnforcingCRUD()
202 | {
203 | return m_enforceCRUD;
204 | }
205 |
206 | /**
207 | * Provides access to the builder containing the list of fields base queries are using, this is demand
208 | * created if one has not already been defined via setFieldListBuilder
209 | *
210 | * @depricated See newQueryFactory
211 | **/
212 | public fflib_StringBuilder.CommaDelimitedListBuilder getFieldListBuilder()
213 | {
214 | return
215 | new fflib_StringBuilder.CommaDelimitedListBuilder(
216 | new List(newQueryFactory().getSelectedFields()));
217 | }
218 |
219 | /**
220 | * Use this method to override the default FieldListBuilder (created on demand via getFieldListBuilder) with a custom one,
221 | * warning, this will bypass anything getSObjectFieldList or getSObjectFieldSetList returns
222 | *
223 | * @depricated See newQueryFactory
224 | **/
225 | public void setFieldListBuilder(fflib_StringBuilder.FieldListBuilder fieldListBuilder)
226 | {
227 | // TODO: Consider if given the known use cases for this (dynamic selector optomisation) if it's OK to leave this as a null operation
228 | }
229 |
230 | /**
231 | * Returns in string form a comma delimted list of fields as defined via getSObjectFieldList and optionally getSObjectFieldSetList
232 | *
233 | * @depricated See newQueryFactory
234 | **/
235 | public String getFieldListString()
236 | {
237 | return getFieldListBuilder().getStringValue();
238 | }
239 |
240 | /**
241 | * Returns in string form a comma delimted list of fields as defined via getSObjectFieldList and optionally getSObjectFieldSetList
242 | * @param relation Will prefix fields with the given relation, e.g. MyLookupField__r
243 | *
244 | * @depricated See newQueryFactory
245 | **/
246 | public String getRelatedFieldListString(String relation)
247 | {
248 | return getFieldListBuilder().getStringValue(relation + '.');
249 | }
250 |
251 | /**
252 | * Returns the string representaiton of the SObject this selector represents
253 | **/
254 | public String getSObjectName()
255 | {
256 | return describeWrapper.getDescribe().getName();
257 | }
258 |
259 | /**
260 | * Performs a SOQL query,
261 | * - Selecting the fields described via getSObjectFieldsList and getSObjectFieldSetList (if included)
262 | * - From the SObject described by getSObjectType
263 | * - Where the Id's match those provided in the set
264 | * - Ordered by the fields returned via getOrderBy
265 | * @returns A list of SObject's
266 | **/
267 | public List selectSObjectsById(Set idSet)
268 | {
269 | return Database.query(buildQuerySObjectById());
270 | }
271 |
272 | /**
273 | * Performs a SOQL query,
274 | * - Selecting the fields described via getSObjectFieldsList and getSObjectFieldSetList (if included)
275 | * - From the SObject described by getSObjectType
276 | * - Where the Id's match those provided in the set
277 | * - Ordered by the fields returned via getOrderBy
278 | * @returns A QueryLocator (typically for use in a Batch Apex job)
279 | **/
280 | public Database.QueryLocator queryLocatorById(Set idSet)
281 | {
282 | return Database.getQueryLocator(buildQuerySObjectById());
283 | }
284 |
285 | /**
286 | * Throws an exception if the SObject indicated by getSObjectType is not accessible to the current user (read access)
287 | *
288 | * @depricated If you utilise the newQueryFactory method this is automatically done for you (unless disabled by the selector)
289 | **/
290 | public void assertIsAccessible()
291 | {
292 | if(!getSObjectType().getDescribe().isAccessible())
293 | throw new fflib_SObjectDomain.DomainException(
294 | 'Permission to access an ' + getSObjectType().getDescribe().getName() + ' denied.');
295 | }
296 |
297 | /**
298 | * Public acccess for the getSObjectType during Mock registration
299 | * (adding public to the existing method broken base class API backwards compatability)
300 | **/
301 | public SObjectType getSObjectType2()
302 | {
303 | return getSObjectType();
304 | }
305 |
306 | /**
307 | * Public acccess for the getSObjectType during Mock registration
308 | * (adding public to the existing method broken base class API backwards compatability)
309 | **/
310 | public SObjectType sObjectType()
311 | {
312 | return getSObjectType();
313 | }
314 |
315 | /**
316 | * Returns a QueryFactory configured with the Selectors object, fields, fieldsets and default order by
317 | **/
318 | public fflib_QueryFactory newQueryFactory()
319 | {
320 | return newQueryFactory(m_enforceCRUD, m_enforceFLS, true);
321 | }
322 |
323 | /**
324 | * Returns a QueryFactory configured with the Selectors object, fields, fieldsets and default order by
325 | **/
326 | public fflib_QueryFactory newQueryFactory(Boolean includeSelectorFields)
327 | {
328 | return newQueryFactory(m_enforceCRUD, m_enforceFLS, includeSelectorFields);
329 | }
330 |
331 | /**
332 | * Returns a QueryFactory configured with the Selectors object, fields, fieldsets and default order by
333 | * CRUD and FLS read security will be checked if the corresponding inputs are true (overrides that defined in the selector).
334 | **/
335 | public fflib_QueryFactory newQueryFactory(Boolean assertCRUD, Boolean enforceFLS, Boolean includeSelectorFields)
336 | {
337 | // Construct QueryFactory around the given SObject
338 | return configureQueryFactory(
339 | new fflib_QueryFactory(getSObjectType2()),
340 | assertCRUD, enforceFLS, includeSelectorFields);
341 | }
342 |
343 | /**
344 | * Adds the selectors fields to the given QueryFactory using the given relationship path as a prefix
345 | *
346 | * // TODO: This should be consistant (ideally) with configureQueryFactory below
347 | **/
348 | public void configureQueryFactoryFields(fflib_QueryFactory queryFactory, String relationshipFieldPath)
349 | {
350 | // Add fields from selector prefixing the relationship path
351 | for(SObjectField field : getSObjectFieldList())
352 | queryFactory.selectField(relationshipFieldPath + '.' + field.getDescribe().getName());
353 | // Automatically select the CurrencyIsoCode for MC orgs (unless the object is a known exception to the rule)
354 | if(Userinfo.isMultiCurrencyOrganization() && CURRENCY_ISO_CODE_ENABLED)
355 | queryFactory.selectField(relationshipFieldPath+'.CurrencyIsoCode');
356 | }
357 |
358 | /**
359 | * Adds a subselect QueryFactory based on this selector to the given QueryFactor, returns the parentQueryFactory
360 | **/
361 | public fflib_QueryFactory addQueryFactorySubselect(fflib_QueryFactory parentQueryFactory)
362 | {
363 | return addQueryFactorySubselect(parentQueryFactory, true);
364 | }
365 |
366 | /**
367 | * Adds a subselect QueryFactory based on this selector to the given QueryFactor
368 | **/
369 | public fflib_QueryFactory addQueryFactorySubselect(fflib_QueryFactory parentQueryFactory, Boolean includeSelectorFields)
370 | {
371 | fflib_QueryFactory subSelectQueryFactory =
372 | parentQueryFactory.subselectQuery(getSObjectType2());
373 | return configureQueryFactory(
374 | subSelectQueryFactory,
375 | m_enforceCRUD,
376 | m_enforceFLS,
377 | includeSelectorFields);
378 | }
379 |
380 | /**
381 | * Adds a subselect QueryFactory based on this selector to the given QueryFactor, returns the parentQueryFactory
382 | **/
383 | public fflib_QueryFactory addQueryFactorySubselect(fflib_QueryFactory parentQueryFactory, String relationshipName)
384 | {
385 | return addQueryFactorySubselect(parentQueryFactory, relationshipName, TRUE);
386 | }
387 |
388 | /**
389 | * Adds a subselect QueryFactory based on this selector to the given QueryFactor
390 | **/
391 | public fflib_QueryFactory addQueryFactorySubselect(fflib_QueryFactory parentQueryFactory, String relationshipName, Boolean includeSelectorFields)
392 | {
393 | fflib_QueryFactory subSelectQueryFactory = parentQueryFactory.subselectQuery(relationshipName);
394 | return configureQueryFactory(subSelectQueryFactory, m_enforceCRUD, m_enforceFLS, includeSelectorFields);
395 | }
396 |
397 | /**
398 | * Constructs the default SOQL query for this selector, see selectSObjectsById and queryLocatorById
399 | **/
400 | private String buildQuerySObjectById()
401 | {
402 | return newQueryFactory().setCondition('id in :idSet').toSOQL();
403 | }
404 |
405 | /**
406 | * Configures a QueryFactory instance according to the configuration of this selector
407 | **/
408 | private fflib_QueryFactory configureQueryFactory(fflib_QueryFactory queryFactory, Boolean assertCRUD, Boolean enforceFLS, Boolean includeSelectorFields)
409 | {
410 | // CRUD and FLS security required?
411 | if (assertCRUD)
412 | {
413 | try {
414 | // Leverage QueryFactory for CRUD checking
415 | queryFactory.assertIsAccessible();
416 | } catch (fflib_SecurityUtils.CrudException e) {
417 | // Marshal exception into DomainException for backwards compatability
418 | throw new fflib_SObjectDomain.DomainException(
419 | 'Permission to access an ' + getSObjectType().getDescribe().getName() + ' denied.');
420 | }
421 | }
422 | queryFactory.setEnforceFLS(enforceFLS);
423 |
424 | // Configure the QueryFactory with the Selector fields?
425 | if(includeSelectorFields)
426 | {
427 | // select the Selector fields and Fieldsets and set order
428 | queryFactory.selectFields(getSObjectFieldList());
429 |
430 | List fieldSetList = getSObjectFieldSetList();
431 | if(m_includeFieldSetFields && fieldSetList != null)
432 | for(Schema.FieldSet fieldSet : fieldSetList)
433 | queryFactory.selectFieldSet(fieldSet);
434 |
435 | // Automatically select the CurrencyIsoCode for MC orgs (unless the object is a known exception to the rule)
436 | if(Userinfo.isMultiCurrencyOrganization() && CURRENCY_ISO_CODE_ENABLED)
437 | queryFactory.selectField('CurrencyIsoCode');
438 | }
439 |
440 | // Parse the getOrderBy()
441 | for(String orderBy : getOrderBy().split(','))
442 | {
443 | List orderByParts = orderBy.trim().split(' ');
444 | String fieldNamePart = orderByParts[0];
445 | String fieldSortOrderPart = orderByParts.size() > 1 ? orderByParts[1] : null;
446 | fflib_QueryFactory.SortOrder fieldSortOrder = fflib_QueryFactory.SortOrder.ASCENDING;
447 | if(fieldSortOrderPart==null)
448 | fieldSortOrder = fflib_QueryFactory.SortOrder.ASCENDING;
449 | else if(fieldSortOrderPart.equalsIgnoreCase('DESC'))
450 | fieldSortOrder = fflib_QueryFactory.SortOrder.DESCENDING;
451 | else if(fieldSortOrderPart.equalsIgnoreCase('ASC'))
452 | fieldSortOrder = fflib_QueryFactory.SortOrder.ASCENDING;
453 | queryFactory.addOrdering(fieldNamePart, fieldSortOrder, orderBy.containsIgnoreCase('NULLS LAST'));
454 | }
455 |
456 | queryFactory.setSortSelectFields(m_sortSelectFields);
457 |
458 | return queryFactory;
459 | }
460 | }
461 |
--------------------------------------------------------------------------------
/Create a Visualforce Page/EmailMissionSpecialist.apxc:
--------------------------------------------------------------------------------
1 | public class EmailMissionSpecialist {
2 | // Public method
3 | public void sendMail(String address, String subject, String body) {
4 | // Create an email message object
5 | Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
6 | String[] toAddresses = new String[] {address};
7 | mail.setToAddresses(toAddresses);
8 | mail.setSubject(subject);
9 | mail.setPlainTextBody(body);
10 | // Pass this email message to the built-in sendEmail method
11 | // of the Messaging class
12 | Messaging.SendEmailResult[] results = Messaging.sendEmail(
13 | new Messaging.SingleEmailMessage[] { mail });
14 | // Call a helper method to inspect the returned results
15 | inspectResults(results);
16 | }
17 | // Helper method
18 | private static Boolean inspectResults(Messaging.SendEmailResult[] results) {
19 | Boolean sendResult = true;
20 | // sendEmail returns an array of result objects.
21 | // Iterate through the list to inspect results.
22 | // In this class, the methods send only one email,
23 | // so we should have only one result.
24 | for (Messaging.SendEmailResult res : results) {
25 | if (res.isSuccess()) {
26 | System.debug('Email sent successfully');
27 | }
28 | else {
29 | sendResult = false;
30 | System.debug('The following errors occurred: ' + res.getErrors());
31 | }
32 | }
33 | return sendResult;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Create a Visualforce Page/StationCheck.vfp:
--------------------------------------------------------------------------------
1 |
2 |
3 |