├── README.md ├── build.properties ├── build_template.xml ├── getOrgData.php ├── getOrgData.sh ├── git └── .gitignore ├── lists └── .gitignore ├── logs └── .gitignore ├── metadata └── .gitignore └── settings.php /README.md: -------------------------------------------------------------------------------- 1 | salesforceMetadataBackup 2 | ======================== 3 | 4 | Get all salesforce metadata via rest api and apache ant and push to github 5 | 6 | 7 | 8 | getOrgData.php relies on the salesforce php toolkit to be installed 9 | 10 | salesforce php toolkit is available here: 11 | http://wiki.developerforce.com/page/Force.com_Toolkit_for_PHP 12 | save it to ./phpToolKit 13 | -------------------------------------------------------------------------------- /build.properties: -------------------------------------------------------------------------------- 1 | # build.properties 2 | # 3 | 4 | # Specify the login credentials for the desired Salesforce organization 5 | sf.username = 6 | sf.password = 7 | sf.dir = /home/dreamforce/sfMetadata 8 | #sf.pkgName = 9 | #sf.zipFile = 10 | #sf.metadataType = ApexClass 11 | 12 | # Use 'https://login.salesforce.com' for production or developer edition (the default if not specified). 13 | # Use 'https://test.salesforce.com for sandbox. 14 | #sf.serverurl = https://login.salesforce.com 15 | sf.serverurl = https://na9.salesforce.com 16 | 17 | # If your network requires an HTTP proxy, see http://ant.apache.org/manual/proxy.html for configuration. 18 | # 19 | -------------------------------------------------------------------------------- /build_template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | -------------------------------------------------------------------------------- /getOrgData.php: -------------------------------------------------------------------------------- 1 | ', $bulkRetrieve); 69 | //========================================= END OPERATION 3 70 | 71 | 72 | //========================================= OPERATION 4. get the standard and custom object names via the rest API, and there subcomponents via ant list 73 | //get a list of standard and custom objects 74 | $arrObjectList = getObjectLists($sessionId); 75 | $arrStdObjects = $arrObjectList['standard']; 76 | $arrCustomObjects = $arrObjectList['custom']; 77 | 78 | //loop through the std and custom objects, building this kind of XML: 79 | /* 80 | 81 | Account 82 | CustomObject 83 | 84 | */ 85 | 86 | 87 | $objectXML = ""; 88 | $objectXML .= "\t\r\n"; 89 | $objectXML .= "\t\t*\r\n"; 90 | 91 | 92 | foreach($arrStdObjects as $stdObj) { 93 | $objectXML .= "\t\t".$stdObj."\r\n"; 94 | } 95 | 96 | 97 | foreach($arrCustomObjects as $custObj) { 98 | $objectXML .= "\t\t".$custObj."\r\n"; 99 | } 100 | 101 | $objectXML .= "\t\tCustomObject\r\n"; 102 | $objectXML .= "\t\r\n"; 103 | 104 | 105 | 106 | // we need to get these subcomponents of our objects: 107 | //CustomField,BusinessProcess,RecordType,WebLink,ValidationRule,NamedFilter,SharingReason,ListView,FieldSet 108 | $arrCustomField = filerToStandardObjects(parseLog("/home/dreamforce/sfMetadata/lists/CustomField.log")); 109 | $arrBusinessProcess = parseLog("/home/dreamforce/sfMetadata/lists/BusinessProcess.log"); 110 | $arrRecordType = parseLog("/home/dreamforce/sfMetadata/lists/RecordType.log"); 111 | $arrWebLink = parseLog("/home/dreamforce/sfMetadata/lists/WebLink.log"); 112 | $arrValidationRule = parseLog("/home/dreamforce/sfMetadata/lists/ValidationRule.log"); 113 | $arrNamedFilter = parseLog("/home/dreamforce/sfMetadata/lists/NamedFilter.log"); 114 | $arrSharingReason = parseLog("/home/dreamforce/sfMetadata/lists/SharingReason.log"); 115 | $arrListView = parseLog("/home/dreamforce/sfMetadata/lists/ListView.log"); 116 | $arrFieldSet = parseLog("/home/dreamforce/sfMetadata/lists/FieldSet.log"); 117 | 118 | $objectSubXML = ""; 119 | 120 | $objectSubXML .= generateXMLTypeBlock($arrCustomField, "CustomField"); 121 | $objectSubXML .= generateXMLTypeBlock($arrBusinessProcess, "BusinessProcess"); 122 | $objectSubXML .= generateXMLTypeBlock($arrRecordType, "RecordType"); 123 | $objectSubXML .= generateXMLTypeBlock($arrWebLink, "WebLink"); 124 | $objectSubXML .= generateXMLTypeBlock($arrValidationRule, "ValidationRule"); 125 | $objectSubXML .= generateXMLTypeBlock($arrNamedFilter, "NamedFilter"); 126 | $objectSubXML .= generateXMLTypeBlock($arrSharingReason, "SharingReason"); 127 | $objectSubXML .= generateXMLTypeBlock($arrListView, "ListView"); 128 | $objectSubXML .= generateXMLTypeBlock($arrFieldSet, "FieldSet"); 129 | 130 | $completeObjectXML = $objectXML.$objectSubXML; //join the object, and subcomponent together 131 | 132 | createPackageXMLfile($completeObjectXML, "objects.xml"); //write them to the package.xml file 133 | 134 | //========================================= END OPERATION 4 135 | 136 | 137 | //========================================= OPERATION 5. get any remaining components which need to be dot qualified with info we get from ant 138 | $arrLetterhead = parseLog("/home/dreamforce/sfMetadata/lists/Letterhead.log"); 139 | $arrAccountCriteriaBasedSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/AccountCriteriaBasedSharingRule.log"); 140 | $arrAccountOwnerSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/AccountOwnerSharingRule.log"); 141 | $arrAccountSharingRules = parseLog("/home/dreamforce/sfMetadata/lists/AccountSharingRules.log"); 142 | $arrCampaignCriteriaBasedSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/CampaignCriteriaBasedSharingRule.log"); 143 | $arrCampaignOwnerSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/CampaignOwnerSharingRule.log"); 144 | $arrCampaignSharingRules = parseLog("/home/dreamforce/sfMetadata/lists/CampaignSharingRules.log"); 145 | $arrCaseCriteriaBasedSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/CaseCriteriaBasedSharingRule.log"); 146 | $arrCaseOwnerSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/CaseOwnerSharingRule.log"); 147 | $arrCaseSharingRules = parseLog("/home/dreamforce/sfMetadata/lists/CaseSharingRules.log"); 148 | $arrContactCriteriaBasedSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/ContactCriteriaBasedSharingRule.log"); 149 | $arrContactOwnerSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/ContactOwnerSharingRule.log"); 150 | $arrContactSharingRules = parseLog("/home/dreamforce/sfMetadata/lists/ContactSharingRules.log"); 151 | $arrCustomObjectCriteriaBasedSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/CustomObjectCriteriaBasedSharingRule.log"); 152 | $arrCustomObjectSharingRules = parseLog("/home/dreamforce/sfMetadata/lists/CustomObjectSharingRules.log"); 153 | $arrLeadCriteriaBasedSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/LeadCriteriaBasedSharingRule.log"); 154 | $arrLeadOwnerSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/LeadOwnerSharingRule.log"); 155 | $arrLeadSharingRules = parseLog("/home/dreamforce/sfMetadata/lists/LeadSharingRules.log"); 156 | $arrOpportunityCriteriaBasedSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/OpportunityCriteriaBasedSharingRule.log"); 157 | $arrOpportunityOwnerSharingRule = parseLog("/home/dreamforce/sfMetadata/lists/OpportunityOwnerSharingRule.log"); 158 | $arrOpportunitySharingRules = parseLog("/home/dreamforce/sfMetadata/lists/OpportunitySharingRules.log"); 159 | 160 | $remainingXML = ""; 161 | 162 | $remainingXML .= generateXMLTypeBlock($arrLetterhead,"Letterhead"); 163 | $remainingXML .= generateXMLTypeBlock($arrAccountCriteriaBasedSharingRule,"AccountCriteriaBasedSharingRule"); 164 | $remainingXML .= generateXMLTypeBlock($arrAccountOwnerSharingRule,"AccountOwnerSharingRule"); 165 | $remainingXML .= generateXMLTypeBlock($arrAccountSharingRules,"AccountSharingRules"); 166 | $remainingXML .= generateXMLTypeBlock($arrCampaignCriteriaBasedSharingRule,"CampaignCriteriaBasedSharingRule"); 167 | $remainingXML .= generateXMLTypeBlock($arrCampaignOwnerSharingRule,"CampaignOwnerSharingRule"); 168 | $remainingXML .= generateXMLTypeBlock($arrCampaignSharingRules,"CampaignSharingRules"); 169 | $remainingXML .= generateXMLTypeBlock($arrCaseCriteriaBasedSharingRule,"CaseCriteriaBasedSharingRule"); 170 | $remainingXML .= generateXMLTypeBlock($arrCaseOwnerSharingRule,"CaseOwnerSharingRule"); 171 | $remainingXML .= generateXMLTypeBlock($arrCaseSharingRules,"CaseSharingRules"); 172 | $remainingXML .= generateXMLTypeBlock($arrContactCriteriaBasedSharingRule,"ContactCriteriaBasedSharingRule"); 173 | $remainingXML .= generateXMLTypeBlock($arrContactOwnerSharingRule,"ContactOwnerSharingRule"); 174 | $remainingXML .= generateXMLTypeBlock($arrContactSharingRules,"ContactSharingRules"); 175 | $remainingXML .= generateXMLTypeBlock($arrCustomObjectCriteriaBasedSharingRule,"CustomObjectCriteriaBasedSharingRule"); 176 | $remainingXML .= generateXMLTypeBlock($arrCustomObjectSharingRules,"CustomObjectSharingRules"); 177 | $remainingXML .= generateXMLTypeBlock($arrLeadCriteriaBasedSharingRule,"CriteriaBasedSharingRule"); 178 | $remainingXML .= generateXMLTypeBlock($arrLeadOwnerSharingRule,"LeadOwnerSharingRule"); 179 | $remainingXML .= generateXMLTypeBlock($arrLeadSharingRules,"LeadSharingRules"); 180 | $remainingXML .= generateXMLTypeBlock($arrOpportunityCriteriaBasedSharingRule,"OpportunityCriteriaBasedSharingRule"); 181 | $remainingXML .= generateXMLTypeBlock($arrOpportunityOwnerSharingRule,"OpportunityOwnerSharingRule"); 182 | $remainingXML .= generateXMLTypeBlock($arrOpportunitySharingRules,"OpportunitySharingRules"); 183 | 184 | createPackageXMLfile($remainingXML, "remaining.xml"); //write them to the package.xml file 185 | 186 | //========================================= END OPERATION 5 187 | 188 | 189 | //========================================= OPERATION 6, run the ant jobs to retrieve the metadata we have defined 190 | echo shell_exec('ant -buildfile /home/dreamforce/sfMetadata/build.xml bulkRetrieve'); 191 | echo shell_exec('ant -buildfile /home/dreamforce/sfMetadata/build.xml bulkRetrieveFolders'); 192 | //========================================= END OPERATION 6 193 | 194 | 195 | 196 | //========================================= OPERATION 7, remove any files from local git repo which were removed in salesforce, copy all the files to the git repo, add, commit, push to github 197 | 198 | /* 199 | we have a local git repo in: 200 | /home/dpeter/git/salesforce-metadata 201 | we want to copy the metadata we downloaded here: 202 | /home/dpeter/metadata 203 | which we want to push up to github: 204 | git@github.com:safarijv/salesforce-metadata.git 205 | */ 206 | 207 | 208 | 209 | //============================================================= 210 | //remove all the files from the local github repo which aren't in the metadata repo (in case these were objects which were deleted in salesforce) 211 | //get the an array of each file listings, recursively. Strip off the beginning path from each entry in the array so we can do text comparison 212 | $arrMetadata = stripBlanks(str_replace('/home/dreamforce/sfMetadata/metadata', '', @getFilesFromDir('/home/dreamforce/sfMetadata/metadata'))); 213 | $arrGit = stripBlanks(str_replace('/home/dreamforce/sfMetadata/git/salesforce-metadata', '', @getFilesFromDir('/home/dreamforce/sfMetadata/git/salesforce-metadata'))); 214 | 215 | //remove array entries in the /.git directory 216 | $arrGit = stripGit($arrGit); 217 | 218 | $arrDeleteFromGit = array(); 219 | 220 | $fileInGitAndMetadata = false; 221 | foreach ($arrGit as $gitFile) { 222 | $fileInGitAndMetadata = false; 223 | foreach ($arrMetadata as $metadataFile) { 224 | if ($gitFile == $metadataFile) { 225 | $fileInGitAndMetadata = true; 226 | } 227 | } 228 | if (!$fileInGitAndMetadata) { 229 | array_push($arrDeleteFromGit, $gitFile); 230 | } 231 | } 232 | 233 | //print_r($arrDeleteFromGit); 234 | 235 | foreach ($arrDeleteFromGit as $gitFile) { 236 | echo shell_exec('git --git-dir=/home/dreamforce/sfMetadata/git/salesforce-metadata/.git --work-tree=/home/dreamforce/sfMetadata/git/salesforce-metadata/ rm -r -f /home/dreamforce/sfMetadata/git/salesforce-metadata'.$gitFile); 237 | } 238 | 239 | //============================================================= 240 | 241 | 242 | //copy all the files from the metadata downloads back into the local github repo 243 | echo shell_exec('cp -R -f metadata/* git/salesforce-metadata'); 244 | 245 | //add the files to the local git repo 246 | echo shell_exec('git --git-dir=/home/dreamforce/sfMetadata/git/salesforce-metadata/.git --work-tree=/home/dreamforce/sfMetadata/git/salesforce-metadata/ add /home/dreamforce/sfMetadata/git/salesforce-metadata/*'); 247 | 248 | //commit the files 249 | echo shell_exec('git --git-dir=/home/dreamforce/sfMetadata/git/salesforce-metadata/.git --work-tree=/home/dreamforce/sfMetadata/git/salesforce-metadata/ commit -m "Automated Daily Commit from SFSYNC"'); 250 | 251 | //push the files 252 | echo shell_exec('git --git-dir=/home/dreamforce/sfMetadata/git/salesforce-metadata/.git --work-tree=/home/dreamforce/sfMetadata/git/salesforce-metadata/ push origin master'); 253 | 254 | //========================================= END OPERATION 7 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | function generateXMLTypeBlock($arrMembers, $sName) { 265 | //Build an XML block like below, iterating over $arrMembers 266 | 267 | /* 268 | 269 | Account 270 | CustomObject 271 | 272 | */ 273 | 274 | $sXML = ""; 275 | 276 | if (count($arrMembers) > 0) { 277 | $sXML .= "\t\r\n"; 278 | foreach ($arrMembers as $arrField) { 279 | $sXML .= "\t\t".$arrField."\r\n"; 280 | } 281 | $sXML .= "\t\t".$sName."\r\n"; 282 | $sXML .= "\t\r\n"; 283 | } 284 | 285 | return $sXML; 286 | } 287 | 288 | 289 | function parseLog($fileName) { 290 | $arrFields = array(); 291 | $myFile = $fileName; 292 | if (file_exists($myFile)) { 293 | $fh = fopen($myFile, 'r'); 294 | $theData = fread($fh, filesize($myFile)); 295 | fclose($fh); 296 | 297 | 298 | //read the file into an array of lines 299 | $arrLines = explode("\n", $theData); 300 | 301 | //loop through the lines and get the ones that start with "FullName/Id:" 302 | //lines look like this: FullName/Id: Case.Queue_Feedback/00B000000095c8IEAQ 303 | foreach ($arrLines as $arrLine) { 304 | if (strpos($arrLine, "FullName/Id:") !== false) { 305 | //parse out just the objectName.ListView, FieldName, etc from the string 306 | $arrTemp = explode("FullName/Id:", $arrLine, 2); 307 | if (count($arrTemp) == 2) { 308 | $arrTemp = explode("/", $arrTemp[1], 2); 309 | if (count($arrTemp) == 2) { 310 | array_push($arrFields, trim($arrTemp[0])); 311 | } 312 | } 313 | } 314 | } 315 | } 316 | 317 | sort($arrFields); 318 | return $arrFields; 319 | } 320 | 321 | function filerToStandardObjects($arrInput) { 322 | //now we want to filter this list down to just the custom fields on the standard object. we don't want the custom fields on the custom objects, because they 323 | //will already get included with the custom objects. 324 | $arrStandard = array(); 325 | foreach ($arrInput as $arrField) { 326 | //Account.Auto_renewing__c //standard looks like this 327 | //Alert__c.Send_Support_Page__c //custom looks like this 328 | //Support_Alert__kav.Details__c //custom also looks like this 329 | $isCustom = false; 330 | $arrTemp = explode(".", $arrField, 2); 331 | if (count($arrTemp) == 2) { 332 | if (strtolower(substr($arrTemp[0], -3)) == "__c") { 333 | $isCustom = true; 334 | } 335 | if (strtolower(substr($arrTemp[0], -5)) == "__kav") { 336 | $isCustom = true; 337 | } 338 | if (!$isCustom) { 339 | array_push($arrStandard, $arrField); 340 | } 341 | } 342 | } 343 | return $arrStandard; 344 | } 345 | 346 | 347 | function parseCustomFieldLog() { 348 | 349 | $myFile = "lists/CustomField.log"; 350 | $fh = fopen($myFile, 'r'); 351 | $theData = fread($fh, filesize($myFile)); 352 | fclose($fh); 353 | 354 | 355 | //read the file into an array of lines 356 | $arrLines = explode("\n", $theData); 357 | 358 | //loop through the lines and get the ones that start with "FullName/Id:" 359 | //lines look like this: FullName/Id: Opportunity.Qualified_Pre_Trial_Checklist__c/00N000000072Qe0EAE 360 | $arrFields = array(); 361 | foreach ($arrLines as $arrLine) { 362 | if (strpos($arrLine, "FullName/Id:") !== false) { 363 | //parse out just the objectName.FieldName from the string 364 | $arrTemp = explode("FullName/Id:", $arrLine, 2); 365 | if (count($arrTemp) == 2) { 366 | $arrTemp = explode("/", $arrTemp[1], 2); 367 | if (count($arrTemp) == 2) { 368 | array_push($arrFields, trim($arrTemp[0])); 369 | } 370 | } 371 | } 372 | } 373 | 374 | //now we want to filter this list down to just the custom fields on the standard object. we don't want the custom fields on the custom objects, because they 375 | //will already get included with the custom objects. 376 | $arrStandard = array(); 377 | foreach ($arrFields as $arrField) { 378 | //Account.Auto_renewing__c //standard looks like this 379 | //Alert__c.Send_Support_Page__c //custom looks like this 380 | //Support_Alert__kav.Details__c //custom also looks like this 381 | $isCustom = false; 382 | $arrTemp = explode(".", $arrField, 2); 383 | if (count($arrTemp) == 2) { 384 | if (strtolower(substr($arrTemp[0], -3)) == "__c") { 385 | $isCustom = true; 386 | } 387 | if (strtolower(substr($arrTemp[0], -5)) == "__kav") { 388 | $isCustom = true; 389 | } 390 | if (!$isCustom) { 391 | array_push($arrStandard, $arrField); 392 | } 393 | } 394 | } 395 | $arrFields = $arrStandard; 396 | 397 | sort($arrFields); 398 | return $arrFields; 399 | } 400 | 401 | 402 | 403 | 404 | 405 | 406 | function createPackageXMLfile($sXML, $sFilename) { 407 | $myFile = $sFilename; 408 | $fh = fopen($myFile, 'w') or die("can't open file"); 409 | fwrite($fh, getPackageXMLheader().$sXML.getPackageXMLfooter()); 410 | fclose($fh); 411 | } 412 | 413 | function getPackageXMLheader() { 414 | $sReturn = ''."\r\n"; 415 | $sReturn .= ''."\r\n"; 416 | return $sReturn; 417 | } 418 | 419 | function getPackageXMLfooter() { 420 | $sReturn = ''."\r\n"; 421 | return $sReturn; 422 | } 423 | 424 | function getCustomFieldsFromObjectRaw($arrObject) { 425 | $arrReturn = array(); 426 | foreach ((array) $arrObject['fields'] as $field) { 427 | if ($field['custom'] == true) { 428 | array_push($arrReturn, $field['name']); 429 | } 430 | } 431 | return $arrReturn; 432 | } 433 | 434 | function getObjectInfoRaw($objectName, $access_token) { 435 | $url = "https://".SFURL."/services/data/v24.0/sobjects/".$objectName."/describe/"; 436 | $curl = curl_init($url); 437 | curl_setopt($curl, CURLOPT_HEADER, false); 438 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 439 | curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: OAuth $access_token")); 440 | $json_response = curl_exec($curl); 441 | curl_close($curl); 442 | $response = json_decode($json_response, true); 443 | return $response; 444 | } 445 | 446 | function getObjectLists($access_token) { 447 | //this function returns an assoc array. The value "standard" is an array of the std objects, "custom" is an array of the custom objects 448 | $arrReturn = array(); 449 | $arrReturn['standard'] = array(); 450 | $arrReturn['custom'] = array(); 451 | 452 | $url = "https://".SFURL."/services/data/v24.0/sobjects/"; 453 | 454 | $curl = curl_init($url); 455 | curl_setopt($curl, CURLOPT_HEADER, false); 456 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 457 | curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: OAuth $access_token")); 458 | 459 | $json_response = curl_exec($curl); 460 | curl_close($curl); 461 | 462 | $response = json_decode($json_response, true); 463 | 464 | foreach ((array) $response['sobjects'] as $record) { 465 | if ($record['custom'] == true) { 466 | array_push($arrReturn['custom'], $record['name']); 467 | } else { 468 | array_push($arrReturn['standard'], $record['name']); 469 | } 470 | } 471 | 472 | return $arrReturn; 473 | 474 | } 475 | 476 | 477 | 478 | 479 | 480 | 481 | function searchReplaceBuildXmlFile($search, $replace) { 482 | // Open file for read and string modification 483 | $file = "/home/dreamforce/sfMetadata/build.xml"; 484 | $fh = fopen($file, 'r'); 485 | $contents = fread($fh, filesize($file)); 486 | $new_contents = str_replace($search, $replace, $contents); 487 | fclose($fh); 488 | 489 | // Open file to write 490 | $fh = fopen($file, 'w'); 491 | fwrite($fh, $new_contents); 492 | fclose($fh); 493 | 494 | } 495 | 496 | 497 | function buildBulkRetrieve($metadataType, $arrFolders) { 498 | $sReturn = ''; 499 | 500 | foreach ($arrFolders as $value) { 501 | $sReturn .= "\t\t".''."\r\n"; 502 | } 503 | 504 | return rtrim($sReturn); 505 | } 506 | 507 | function getSession() { 508 | $sessionId = ''; 509 | try { 510 | $mySforceConnection = new SforcePartnerClient(); 511 | $mySoapClient = $mySforceConnection->createConnection('phpToolkit/partner.wsdl.xml'); 512 | $mylogin = $mySforceConnection->login(USERNAME, PASSWORD); 513 | $sessionId = $mylogin->sessionId; 514 | } catch (Exception $e) { 515 | print_r($mySforceConnection->getLastRequest()); 516 | echo $e->faultstring; 517 | } 518 | return $sessionId; 519 | } 520 | 521 | 522 | function getReportFolders($access_token) { 523 | $arrReturn = array(); 524 | 525 | $query = "SELECT Id, DeveloperName FROM Folder WHERE Type='Report' AND DeveloperName != ''"; 526 | $url = "https://".SFURL."/services/data/v20.0/query?q=" . urlencode($query); 527 | 528 | $curl = curl_init($url); 529 | curl_setopt($curl, CURLOPT_HEADER, false); 530 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 531 | curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: OAuth $access_token")); 532 | 533 | $json_response = curl_exec($curl); 534 | curl_close($curl); 535 | 536 | $response = json_decode($json_response, true); 537 | 538 | foreach ((array) $response['records'] as $record) { 539 | array_push($arrReturn, $record['DeveloperName']); 540 | } 541 | 542 | return $arrReturn; 543 | 544 | } 545 | 546 | function getDashboardFolders($access_token) { 547 | $arrReturn = array(); 548 | 549 | $query = "SELECT Id, DeveloperName FROM Folder WHERE Type='Dashboard' AND DeveloperName != ''"; 550 | $url = "https://".SFURL."/services/data/v20.0/query?q=" . urlencode($query); 551 | 552 | $curl = curl_init($url); 553 | curl_setopt($curl, CURLOPT_HEADER, false); 554 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 555 | curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: OAuth $access_token")); 556 | 557 | $json_response = curl_exec($curl); 558 | curl_close($curl); 559 | 560 | $response = json_decode($json_response, true); 561 | 562 | foreach ((array) $response['records'] as $record) { 563 | array_push($arrReturn, $record['DeveloperName']); 564 | } 565 | 566 | return $arrReturn; 567 | 568 | } 569 | 570 | 571 | function getDocumentFolders($access_token) { 572 | $arrReturn = array(); 573 | 574 | $query = "SELECT Id, DeveloperName FROM Folder WHERE Type='Document' AND DeveloperName != ''"; 575 | $url = "https://".SFURL."/services/data/v20.0/query?q=" . urlencode($query); 576 | 577 | $curl = curl_init($url); 578 | curl_setopt($curl, CURLOPT_HEADER, false); 579 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 580 | curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: OAuth $access_token")); 581 | 582 | $json_response = curl_exec($curl); 583 | curl_close($curl); 584 | 585 | $response = json_decode($json_response, true); 586 | 587 | foreach ((array) $response['records'] as $record) { 588 | array_push($arrReturn, $record['DeveloperName']); 589 | } 590 | 591 | return $arrReturn; 592 | 593 | } 594 | 595 | 596 | function getEmailTemplateFolders($access_token) { 597 | $arrReturn = array(); 598 | 599 | $query = "SELECT Id, DeveloperName FROM Folder WHERE Type='Email' AND DeveloperName != ''"; 600 | $url = "https://".SFURL."/services/data/v20.0/query?q=" . urlencode($query); 601 | 602 | $curl = curl_init($url); 603 | curl_setopt($curl, CURLOPT_HEADER, false); 604 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 605 | curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: OAuth $access_token")); 606 | 607 | $json_response = curl_exec($curl); 608 | curl_close($curl); 609 | 610 | $response = json_decode($json_response, true); 611 | 612 | foreach ((array) $response['records'] as $record) { 613 | array_push($arrReturn, $record['DeveloperName']); 614 | } 615 | 616 | return $arrReturn; 617 | 618 | } 619 | 620 | 621 | 622 | function getFilesFromDir($dir) { 623 | $files = array(); 624 | if ($handle = opendir($dir)) { 625 | while (false !== ($file = readdir($handle))) { 626 | if ($file != "." && $file != "..") { 627 | if(is_dir($dir.'/'.$file)) { 628 | $dir2 = $dir.'/'.$file; 629 | $files[] = @getFilesFromDir($dir2); 630 | } 631 | else { 632 | $files[] = $dir.'/'.$file; 633 | } 634 | } 635 | } 636 | closedir($handle); 637 | } 638 | return @array_flat($files); 639 | } 640 | 641 | function array_flat($array) { 642 | foreach($array as $a) { 643 | if(is_array($a)) { 644 | $tmp = array_merge($tmp, array_flat($a)); 645 | } 646 | else { 647 | $tmp[] = $a; 648 | } 649 | } 650 | return $tmp; 651 | } 652 | 653 | function stripGit($arrInput) { 654 | $arrStripped = array(); 655 | foreach ($arrInput as $stripFile) { 656 | if (substr($stripFile, 0, 5) == "/.git") { 657 | //don't add it 658 | } else { 659 | array_push($arrStripped, $stripFile); 660 | } 661 | } 662 | return $arrStripped; 663 | } 664 | 665 | function stripBlanks($arrInput) { 666 | $arrStripped = array(); 667 | foreach ($arrInput as $stripFile) { 668 | if (trim($stripFile) == "") { 669 | //don't add it 670 | } else { 671 | array_push($arrStripped, trim($stripFile)); 672 | } 673 | } 674 | return $arrStripped; 675 | } 676 | ?> 677 | 678 | 679 | 680 | 681 | 682 | 683 | -------------------------------------------------------------------------------- /getOrgData.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd /home/dreamforce/sf 3 | php getOrgData.php > logs/log.txt -------------------------------------------------------------------------------- /git/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /lists/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /logs/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /metadata/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /settings.php: -------------------------------------------------------------------------------- 1 | "); 4 | define("PASSWORD", ""); 5 | define("SFURL", "na9.salesforce.com"); 6 | //define("SFURL", "ssl.salesforce.com"); 7 | 8 | 9 | 10 | ?> --------------------------------------------------------------------------------