Google TeamDrive getChildren of a teamDriveID PHP - php

I'm using PHP and the following call to retrieve the top-level TeamDrive folders.
$service->teamdrives->listTeamdrives()->getTeamDrives();
Results
TeamDrive1 --- let's say the ID is XXXXXX
TeamDrive2 --- let's say the ID is YYYYYY
TeamDrive1 has a sub-folder called TeamDrive1Sub1 (ID is SSSSS)
then TeamDrive1Sub1 (ID PPPPP) also has a sub-folder etc
I've tried to use the Drive REST API files:List - but this does not seem to work...
I need to find the children "x" levels deep, how do I do that? Maybe some other interface call such as the one I'm using above $service->teamdrives->listTeamdrives()->getTeamDrives(); which allows me to start at the ID XXXXXX and retrieve it's children

Found my own answer, but there's probably a better way... if you have the ID of a teamdrive folder and want to get the sub-folders - here's what I have for the PHP code
//- first we need to get the $teamDriveId - using the /files/get & the $folderId we passed in
$folderId = "XXXXXX" // from above
$optParams = array(
'supportsTeamDrives' => true,
);
$results = $service->files->get($folderId, $optParams);
$teamDriveId = $results["teamDriveId"];
// now we can get the sub-folders (if there are any)
$params = [
'q' => "'{$folderId}' in parents and trashed = false and mimeType = 'application/vnd.google-apps.folder'",
'pageSize' => $pageSize,
'corpora' => 'teamDrive',
'includeTeamDriveItems' => true,
'supportsTeamDrives' => true,
'teamDriveId' => $teamDriveId, // this must be the parent Id
'orderBy' => 'name',
];
$results = $service->files->listFiles($params);
Hope this helps someone

Related

List all folders that are direct children Google drive API

I'm trying to list all folders that are at the root of a teamdrive using the google api php client. The perans i'm using look like this:
$optParams = array(
'driveId' => "<ID OF TEAM DRIVE>",
'pageSize' => 100,
'includeItemsFromAllDrives' => true,
'supportsAllDrives' => true,
'corpora' => "drive",
'fields'=>'nextPageToken, files(id, name)',
'q' => ["mimeType = 'application/vnd.google-apps.folder'", "'<ID OF TEAM DRIVE>' in parents"]
);
The problem is that this lists all the sub-folders as well and not just the folders in the root of that team drive.
This feels like it should be easy but i'm probably missing something obvious.
I did solve this by removing DriveId, copora and the mimeType.
My guess is that this statement (which I did not find a documentation on) means one thing OR another thing and not one thing AND another thing.
["mimeType = 'application/vnd.google-apps.folder'", "'<ID OF TEAM DRIVE>' in parents"]
So what worked for me was:
$optParams = array(
'pageSize' => 100,
'includeItemsFromAllDrives' => true,
'supportsAllDrives' => true,
'fields'=>'nextPageToken, files(id, name)',
'q' => "'<DRIVE ID>' in parents"
);
user3477740, you were very close.
Place your entire query inside a single string like below, and (I strongly suggest) separate your logic inside parenthesis:
'q' => "(trashed = false) and (mimeType = 'application/vnd.google-apps.folder') and ('<DRIVE ID>' in parents)"
And thanks to you for showing me the easy way to reference google drive children within a google drive folder - it's not well documented in Google Drive V3

Upload a File to a Task on Cerb API

At the moment I am adding a task to Cerb using the API (Docs: https://cerb.ai/docs/api/). I can add and edit comments on the task.
An extension is to add file uploads. The API documentation seems to be extremely limited in terms of file uploads and isn't helping much. I have based my current code on https://cerb.ai/docs/api/endpoints/records/#update, using a custom field linked to the task and posting directly to the API.
The process is as follows:
1 - User inserts information on a Laravel form
2 - Form is submitted, task is created
3 - If the user entered a comment or description, the controller then uses the ID from the newly created task toa dd the comment
4 - If the user adds a file, the controller should then use the same ID from the task to attach the file
Task and comment adding has been done through models, which were previously done directly through the API and reformatted once they worked.
Add Task:
$params = [
'title' => $request->input('title'),
'links' => ['project:'.$request->input('project')],
'priority' => $request->input('priority'),
'status_id' => 2
];
$due_date = $request->input('due');
if(!empty($due_date)){
$params['due'] = strtotime($due_date);
}
$success_task = $task->addUpdateRecord('tasks.add', $params);
Add Comment:
$params = [
'author__context' => 'bot',
'author_id' => 3,
'comment' => empty($comment_input) ? request()->comment : $comment_input,
'target__context' => 'task',
'target_id' => $task_id,
'author' => Auth::user()->name // custom field
];
$success = $comment->addUpdateRecord('comments.add', $params);
The addUpdateRecord() essentially does the same thing as the file upload as below:
$cerb = new CerbApi();
$out = $cerb->put($root.'records/file_bundle/1054.json?expand=custom_', $putfields);
$putfields contains a normal file upload object.
I'm getting the following error on request:
array:2 [▼
"__status" => "error"
"message" => "Unknown command (root/records/task/1054.json)"
]
(root removed for confidentiality)
Has anyone worked with this? Anyone able to assist?
Ended up getting it right by using the attachments record type https://cerb.ai/docs/records/types/attachment/ and creating a model for it with its own addUpdateRecord() method.
I then used the records API to do the post for the file as the first step instead of the last one:
$file_upload = new File;
// Get file contents
$data = file_get_contents($file);
// Base64 encode contents
$data = base64_encode($data);
$file_params = [
'name' => $file->getClientOriginalName(),
'content' => $data
];
// Do upload
$file_success = $file_upload->addUpdateRecord('files.add', $file_params);
// Only need to return the file ID to link it to the task
return $file_success["data"]["id"];
And then using the ID that was being returned to link it to the task:
$task = new Task();
$params = [
'title' => $request->input('title'),
'links' => [
'project:'.$request->input('project'),
'file:'.$file_id
],
'priority' => $request->input('priority'),
'status_id' => 2
];
I hope this helps someone in the future.
Note: Cerb API Version 9.2.0

How do I download an image from an Alfresco repository using CMIS?

I'm working with a system that uploads and downloads images on an Alfresco repository following the structure: "root/folder1/folder2/image.jpg"
I managed to fix the uploading part but I'm struggling trying to download the images, I have the following code:
if(!empty($path)) {
$path = $this->_clientCMIS->getObjectByPath('/'.$path);
$path = ' AND IN_FOLDER(\''.$path->id.'\')';
}
$query = 'SELECT * FROM cmis:document WHERE cmis:name = \''.$file.'\''.$path;
$documents = $this->_clientCMIS->query($query);
foreach ($documents->objectList as $document) {
$data = explode(':', $document->uuid);
array_push($response['data'], array(
'id' => $document->properties['cmis:objectId']
, 'path' => (isset($document->properties['cmis:path']))?$document->properties['cmis:path']:''
, 'name' => $document->properties['cmis:name']
, 'url' => 'http://'.$this->_ip.$this->_port.'/share/proxy/alfresco/api/node/content/workspace/SpacesStore/'.$data[2].'/'.$document->properties['cmis:name']
, 'type' => 'file'
, 'size' => $document->properties['cmis:contentStreamLength']
, 'createdBy' => $document->properties['cmis:createdBy']
, 'creationDate' => $document->properties['cmis:creationDate']
, 'lastModifiedBy' => $document->properties['cmis:lastModifiedBy']
, 'lastModificationDate' => $document->properties['cmis:lastModificationDate']
, 'parentId' => (isset($document->properties['cmis:parentId']))?$document->properties['cmis:parentId']:''
));
}
$response['total'] = sizeof($response['data']);
$response['error'] = '';
I checked the $path and $file variables and their values are correct (the folder where the image is stored and the image's name) but the query returns an empty object list (therefore, the code never enters the foreach loop).
The value of the $query variable is something like this:
SELECT * FROM cmis:document WHERE cmis:name = 'my_image.jpg' AND IN_FOLDER('workspace://SpacesStore/5acb1737-b30a-2ff8-d47a-7f360c235bd0')
That query should work. I suggest you use something like the Apache Chemistry OpenCMIS Workbench to test your query (or the node browser in Alfresco).
It could be that the user you are authenticated as does not have access to the folder you are querying against.
Also, a minor nit, but be careful about confusing an Alfresco node reference for a CMIS object ID. Those are not the same thing.

Cannot update reference app field

I have an item with a referenced field to another app. A call has an assigned client.
I use this library: http://podio.github.io/podio-php/
I followed this article: http://podio.github.io/podio-php/fields/
I want to update an existing item by changing the item_id of its field that's referencing another app. The item_id already exists in the other app.
Here's what I tried (this happens when a Webhook is triggered):
$item = PodioItem::get($_POST['item_id']);
$item->fields['client']->values = array(
array('item_id' => $id_client)
);
$item->save(array(
'hook' => false,
'silent' => true
));
AND
$item = PodioItem::get($_POST['item_id']);
$item->fields['client']->values = array('item_id' => $id_client);
$item->save(array(
'hook' => false,
'silent' => true
));
Where 'client' is the external id of the field and $id_client is an integer number.
Here's the error I get:
[18-Aug-2014 17:33:30 UTC] PHP Notice: Indirect modification of overloaded property PodioItem::$field has no effect in /home1/magikweb/public_html/dev/magik-net/helpdesk/webhook/call.php on line 66
[18-Aug-2014 17:33:30 UTC] PHP Warning: Creating default object from empty value in /home1/magikweb/public_html/dev/magik-net/helpdesk/webhook/call.php on line 66
If anyone could explain to me why this isn't working I'd be really grateful. The provided documentation is not clear on that subject.
Thank you!
SOLUTION
I got it to work this way, credits to Andreas:
if(!isset($item->fields['client']->values[0]->item_id)){
$item->fields['client'] = new PodioAppItemField();
$item->fields['client']->values = array(
array('item_id' => $id_client)
);
$item->save(array(
'hook' => false,
'silent' => true
));
}
You're getting this error because the client field doesn't exist on your item yet. So you're trying to set values for something that doesn't exist.
You need to do something like (untested, but should work):
$item = PodioItem::get($_POST['item_id']);
if (!isset($item->fields['client'])) {
$item->fields['client'] = new PodioAppItemField();
}
$item->fields['client']->values = array(
array('item_id' => $id_client)
);
$item->save(array(
'hook' => false,
'silent' => true
));
When you get an item from Podio you won't get all fields in the app, only that ones that have values for that particular item. So you have to check if your particular field is present before trying to set values on it.

In Amazon API use ItemSearch with respect to category only

I am using Amazon Product Advertising API, I want to retrieve all products of a category. What I want to know is can I only provide a category without passing any Keyword into the ItemSearch operation and retrieve the complete set of product records including their sub-category products.
I tried passing this parameter in an array without supplying a 'Keyword' item:
$category = 'Software';
$single = array(
"Operation" => "ItemSearch",
"SearchIndex" => $category,
"Condition" => "All",
"ResponseGroup" => "Medium,Reviews"
);
But it does not work. Please help me.
Let me explain again in short that all I want is to get the complete list of Products by passing any category without passing any Keyword.
You would probably want to perform a BrowseNodeLookup. This operation will let you iteratively navigate up and down the tree of ancestors/children based on the passed Browse Node ID.
Here is the documentation for that operation:
http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BrowseNodeLookup.html
The list of top level Browse Node ID's is here:
http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BrowseNodeIDs.html
You could then use the Browse Node Id that you are interested in and pass that in to the ItemSearch as a parameter value. You would not need to include the keyword parameter at all in this case.
Operation might look like:
$browse_node_id = '409488'; // browse node id for Software in US or other browse node determined by using BrowseNodeLoookup
$single = array(
"Operation" => "ItemSearch",
"BrowseNode" => $browse_node_id,
"SearchIndex" => "All", // we don't need to limit to certain category here as browse node does this
"Condition" => "All",
"ResponseGroup" => "Medium,Reviews"
);

Categories