/** * Save object and unsaved children within. * * @param ParseObject|array $target * @param bool $useMasterKey Whether to use the Master Key. * * @throws Exception * @throws ParseAggregateException * @throws ParseException */ private static function deepSave($target, $useMasterKey = false) { $unsavedChildren = []; $unsavedFiles = []; static::findUnsavedChildren($target, $unsavedChildren, $unsavedFiles); $sessionToken = null; if (ParseUser::getCurrentUser()) { $sessionToken = ParseUser::getCurrentUser()->getSessionToken(); } foreach ($unsavedFiles as &$file) { $file->save(); } $objects = []; // Get the set of unique objects among the children. foreach ($unsavedChildren as &$obj) { if (!in_array($obj, $objects, true)) { $objects[] = $obj; } } $remaining = $objects; while (count($remaining) > 0) { $batch = []; $newRemaining = []; foreach ($remaining as $key => &$object) { if (count($batch) > 40) { $newRemaining[] = $object; continue; } if ($object->canBeSerialized()) { $batch[] = $object; } else { $newRemaining[] = $object; } } $remaining = $newRemaining; if (count($batch) === 0) { throw new Exception('Tried to save a batch with a cycle.'); } $requests = []; foreach ($batch as $obj) { $json = $obj->getSaveJSON(); $method = 'POST'; $path = 'classes/' . $obj->getClassName(); if ($obj->getObjectId()) { $path .= '/' . $obj->getObjectId(); $method = 'PUT'; } $requests[] = ['method' => $method, 'path' => $path, 'body' => $json]; } if (count($requests) === 1) { $req = $requests[0]; $result = ParseClient::_request($req['method'], $req['path'], $sessionToken, json_encode($req['body']), $useMasterKey); $batch[0]->mergeAfterSave($result); } else { foreach ($requests as &$r) { $r['path'] = '/' . ParseClient::getMountPath() . $r['path']; } $result = ParseClient::_request('POST', 'batch', $sessionToken, json_encode(['requests' => $requests]), $useMasterKey); $errorCollection = []; foreach ($batch as $key => &$obj) { if (isset($result[$key]['success'])) { $obj->mergeAfterSave($result[$key]['success']); } elseif (isset($result[$key]['error'])) { $response = $result[$key]; $error = $response['error']['error']; $code = isset($response['error']['code']) ? $response['error']['code'] : -1; $errorCollection[] = ['error' => $error, 'code' => $code, 'object' => $obj]; } else { $errorCollection[] = ['error' => 'Unknown error in batch save.', 'code' => -1, 'object' => $obj]; } } if (count($errorCollection)) { throw new ParseAggregateException('Errors during batch save.', $errorCollection); } } } }