0

So i am using SFs Rest API to fetch various data from SF, i am fetching all values for a picklist. Problem is that picklist has dependacies, so half of the values either belong in one category, or both. I'm gussing this is what the validFor attribute serves, but i can figure out how do I use this? Here's just one of the values. This is a PHP project btw (if this is relevant).

Array
(
    [active] => 1
    [defaultValue] => 
    [label] => Pro bono project
    [validFor] => AAAI
    [value] => Pro bono project
)
2

DescribeSObjectResult describes how validFor operates. It is decoded into a series of bits (base-64 encoded) where each bit is set to 0 if not valid, 1 if it is.

In your example, AAAI decodes to:

000000 000000 000000 001000 (base-64)
00000000 00000000 00001000 (binary bytes)

Which means that the 21st value in the controlling field is valid for "Pro bono project."

The documentation (above) provides a helpful snippet, but it's in Java:

public void dependentPicklistSample() {
  // inner class to decode a "validFor" bitset
  class Bitset {
    byte[] data;

    public Bitset(byte[] data) {
      this.data = data == null ? new byte[0] : data;
    }

    public boolean testBit(int n) {
      return (data[n >> 3] & (0x80 >> n % 8)) != 0;
    }

    public int size() {
      return data.length * 8;
    }
  }

  try {
    DescribeSObjectResult describeSObjectResult = connection.describeSObject("Case");
    Field[] fields = describeSObjectResult.getFields();
    // create a map of all fields for later lookup 
    Map fieldMap = new HashMap();
    for (int i = 0; i < fields.length; i++) {
      fieldMap.put(fields[i].getName(), fields[i]);
    }
    for (int i = 0; i < fields.length; i++) {
      // check whether this is a dependent picklist
      if (fields[i].getDependentPicklist()) {
        // get the controller by name
        Field controller = (Field)fieldMap.get(fields[i].getControllerName());
        System.out.println("Field '" + fields[i].getLabel() + "' depends on '" +
        controller.getLabel() + "'");
        PicklistEntry[] picklistValues = fields[i].getPicklistValues();
        for (int j = 0; j < picklistValues.length; j++) {
          // for each PicklistEntry: list all controlling values for which it is valid
          System.out.println("Item: '" + picklistValues[j].getLabel() +
          "' is valid for: ");
          Bitset validFor = new Bitset(picklistValues[j].getValidFor());
          if (FieldType.picklist == controller.getType()) {
            // if the controller is a picklist, list all
            // controlling values for which this entry is valid
            for (int k = 0; k < validFor.size(); k++) {
              if (validFor.testBit(k)) {
                // if bit k is set, this entry is valid for the
                // for the controlling entry at index k
                System.out.println(controller.getPicklistValues()[k].getLabel());
              }
            }
          } else if (FieldType._boolean == controller.getType()) {
            // the controller is a checkbox
            // if bit 1 is set this entry is valid if the controller is checked
            if (validFor.testBit(1)) {
              System.out.println(" checked");
            }
            // if bit 0 is set this entry is valid if the controller is not checked
            if (validFor.testBit(0)) {
              System.out.println(" unchecked");
            }
          }
        }
      }
    }
  } catch (ConnectionException ce) {
    ce.printStackTrace();
  }
}

You'll need to devise a way to convert this to binary data in your own code. It seems like you'll want to convert your base-64 data with base64_decode, convert the result to binary with unpack, and then you can render the appropriate values for a given index.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.