Can't see created folder in teamdrive root - php

I'm creating a folder inside teamdrive root with google-drive-sdk and it works but with some delay after API call finished. If I try to query root folder with the name of newly created folder right after creation - I get an empty array. But if I do the same after couple of seconds I see the new item.
$file = $service->files->create(
$folder,
[
"supportsTeamDrives" => true
]
);
printf("Folder ID: %s\n", $file->id);
I see the folder ID
$params = [
"q" => "'{$teamDriveId}' in parents and trashed = false and mimeType = 'application/vnd.google-apps.folder' and name ='$path'",
"pageSize" => 1,
"corpora" => "teamDrive",
"includeTeamDriveItems" => true,
"supportsTeamDrives" => true,
"teamDriveId" => $teamDriveId
];
$files = $service->files->listFiles($params);
$list = $files->getFiles();
var_dump($list);
Empty array
But if I do 'sleep(3)' before query - an array is not empty and contains new folder.
I didn't find any information about this delay in documentation. What is it and is there a way to get the result without delays?

While I can't speak to the internals of the Drive API, I can imagine that any delay between creating the folder, and the folder being queryable from Files.list(), is due to internal indexing and data propagation for Team Drives, since they are different than the regular Drive files.
Note that such an use case -- I create this file then immediately need to find it -- is avoidable - the act of creating the file has a return value that includes the direct handle to the file created.
Response
If successful, this method returns a Files resource in the response body.

Related

PHP - Rackspace CloudFiles API check if the file path already exists?

I'm working with the Rackspace CloudFiles API, where I've got a requirement to check for folder exists inside a container.
I have searched across different areas I could find solution to find if container exists or the object exists.
For example:
Format: container/folder/subfolder/file
Actual file stored location:
test/test_folder/test_subfolder/test.txt
I want to know is my container has already got a folder called test_folder
And I came across something which says path, but am not sure we have this method exists!
getObjects ->> 'path', 'file path to search'
I can't really answer this question in the context of PHP or Guzzle, but I can provide some info on Cloud Files and some command line curl examples that might help.
Rackspace Cloud Files does not really have the concept of "folders" inside containers. You have a URL with the following pieces:
https://{storage_endpoint}/{account_name}/{container_name}/{object_name}
You can however emulate folders by creating objects with the "/" character in the name. Then when performing a container listing, you can set the "prefix" and "delimiter" query string parameters to emulate a folder-like behavior.
For example, say you do a listing of your container to see all your objects:
$ curl -i -XGET -H"x-auth-token: $AUTH_TOKEN" https://storage101.iad3.clouddrive.com/v1/$ACCOUNT_NAME/$CONTAINER_NAME
HTTP/1.1 200 OK
...
Date: Thu, 01 Dec 2016 02:16:53 GMT
foo/file1.txt
foo/bar/file2.txt
baz/file3.txt
baz/file4.txt
Here we have four objects named "foo/file1.txt", "foo/bar/file2.txt", "baz/file3.txt" and "baz/file4.txt".
The easiest way to test for the existence of the folder "foo" would be to set the prefix to "foo/" and the delimiter to "/" as follows:
$ curl -i -XGET -H"x-auth-token: $AUTH_TOKEN" https://storage101.iad3.clouddrive.com/v1/$ACCOUNT_NAME/$CONTAINER_NAME?prefix=foo/&delimiter=/
HTTP/1.1 200 OK
...
Date: Thu, 01 Dec 2016 02:16:45 GMT
foo/file1.txt
foo/bar/file2.txt
As you can see, if any objects exist with that prefix, then a HTTP 200 is returned along with a listing of the objects that matched the prefix. If no objects exist with that prefix, the "folder" does not exist and a HTTP 204 will be returned.
If you now want to test for a "sub-folder" inside "foo", you can just perform another container listing changing the prefix to "foo/bar/" and keeping the delimiter of "/".
Further, if you want to create a folder "images" and have it contain "cat.jpg", you don't need to create a folder first, you just create an object called "images/cat.jpg" that contains the data for cat.jpg.
You can find more information about Rackspace Cloud Files and Pseudo-Hierarchical folders here:
https://developer.rackspace.com/docs/cloud-files/v1/general-api-info/pseudo-hierarchical-folders-and-directories/
Even though #hurricanerix answer helped me, I want to post exact PHP method and snippet to help other is future.
$client = new Rackspace(Rackspace::US_IDENTITY_ENDPOINT, array(
'username' => 'XXXXXXXX',
'apiKey' => 'XXXXXXXXXXXXXXXXXXX'
));
$total = 0;
$containerObjects = array();
$objectStoreService = $client->objectStoreService(null, 'XX');
$container = $objectStoreService->getContainer('test');
$objData = $container->ObjectList(array('prefix'=>"test_folder/", 'delimiter'=>"/"));
if(is_object($objData))
{
$total = $objData->count();
if ($total == 0)
break;
foreach ($objData as $object) {
$containerObjects[] = $object->getName();
}
}
var_dump($containerObjects);
Output
array (size=1)
0 => string 'test/test_folder/test_subfolder/' (length=32)
Hope this will help.

Any way to offset results with AWS SDK for PHP?

I'm currently working on scanning a folder in my S3 bucket and removing files that are no longer in my database. The problem is that I have millions of files, so no way of scanning this in one go.
// get files
$files = $s3->getIterator('ListObjects', array(
"Bucket" => $S3Bucket,
"Prefix" => 'collections/items/',
"Delimiter" => '/'
), array(
'return_prefixes' => true,
'names_only' => true,
'limit' => 10
));
The documentation included something about limiting results, but I can't find anything about offsetting. I want to be able to start from 0, scan 500 items, remove them, stop, save the last scanned index and then run the script again, start from the saved index (501), scan 500 items, and so on.
Does the SDK offer some sort of offset option? Is it called something else? Or can you recommend a different method of scanning such a large folder?
Remember the last key you processed and use it as the Marker parameter.
$files = $s3->getIterator('ListObjects', array(
"Bucket" => "mybucket",
"Marker" => "last/key"
));
BTW, dont set Limit, its slowing down. Limit 10 will cause a request to the API every 10 objects, the API can return up to 1000 objects per request.

docusign POST template to a folder using REST API not working

How to post docusign template in a specified folder? so far as per API I have used
"envelopeTemplateDefinition" => array(
"name"=> 'SpecialTPL_'. 'TestName',
"folderName" => "testFolder",
"folderId" => "A Long ID fetched earlier by API's /folders call",
"folderUri" => "/folders/A Long ID fetched earlier by API's /folders call",
)
But this is posting templates nto default "template" Folder only, and not into "testFolder".
The POST request defaults to the template being placed into the Parent folder (i.e. My Templates) regardless of the fact that you specified your subfolder folderId.
You'll need to first run your template POST call, then a Move Envelope (Template) PUT call after to place the template into the subfolder. Steps would be:
1) POST your Template into the default folder i.e. POST https://demo.docusign.net/restapi/v2/accounts/[account ID]/templates
2) GET your Template Subfolder and Parent Folder folderIds i.e. GET https://demo.docusign.net/restapi/v2/accounts/[account ID]/folders?template=only
3) PUT a Move Template request using the Subfolder and Parent Folder folderIds returned in step 2 i.e. https://demo.docusign.net/restapi/v2/accounts/[account ID]/folders/[subfolder ID]
Your JSON body for step 3 would be:
{
"envelopeIds": ["Template ID returned in step 1"],
"fromFolderId": "Parent Template Folder ID returned in step 2"
}
Note that envelopeIds is a list of template IDs and the IDs themselves need to be wrapped by [ ] even if your only specifying just one template

DynamoDB PHP getItem() - How to tell if item does not exist

I am writing a "Get or Create" method that attempts to get an item, but if it doesn't exist, it will create a fresh new version of it. Obviously, I want to know for certain that the item didn't exist when I attempted to get it, so that it never overwrites existing data.
Am I correct in assuming $result["Item"] === null if and only if the item did not exist in the database at the time of the request? That is, if the item existed prior to the request, will this condition always evaluate to false, regardless of API errors, etc.? Or is there something else I should check for instead?
$result = $this->client->getItem(
array(
"TableName" => $tableName,
"Key" => array(
$keyName => array(Type::STRING => $key),
)
)
);
if ( $result["Item"] === null )
{
//Item does not exist; create it and write it to dynamoDb (code not shown)
}
return $result["Item"];
I would add 'ConsistentRead' => true in order to make sure your read is getting the absolute, most up-to-date data.
You are still going to have a potential race condition here where if multiple processes try to get the item and see that it is not there, then they will all try to write the item, but only one process won't have its data clobbered. As long as there is no chance that they will write different data, then it doesn't matter.
Consider a conditional put where you specify that the key must not exist before doing the put. This avoids any race condition, and takes only a single call. The only downside is that you must send the entire new item over the wire, even if it already exists.
Scroll down to the "specifying optional parameters" section here: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelJavaItemCRUD.html#PutLowLevelAPIJava
The code should look something like this:
// Optional parameters Expected and ReturnValue.
Map<String, ExpectedAttributeValue> expected = new HashMap<>();
expected.put(
"hashKeyAttributeName",
new ExpectedAttributeValue()
.withValue(new AttributeValue().withS("hashKeyValue"))
.withExists(false)
);

Store information about a directory

Other than the foldername, is there a way to get/set information about a directory to the actual folder itself?
I want to set a directory priority so folders are displayed in a certain order by assigning a number to each.
This is possible with Extended File Attributes:
https://secure.wikimedia.org/wikipedia/en/wiki/Extended_file_attributes
Extended file attributes is a file system feature that enables users to associate computer files with metadata not interpreted by the filesystem, whereas regular attributes have a purpose strictly defined by the filesystem (such as permissions or records of creation and modification times).
Try the xattr API to get/set them:
http://docs.php.net/manual/en/book.xattr.php
Example from Manual:
$file = 'my_favourite_song.wav';
xattr_set($file, 'Artist', 'Someone');
xattr_set($file, 'My ranking', 'Good');
xattr_set($file, 'Listen count', '34');
/* ... other code ... */
printf("You've played this song %d times", xattr_get($file, 'Listen count'));
You can do it for NTFS for sure: http://en.wikipedia.org/wiki/NTFS#Alternate_data_streams_.28ADS.29
Don't know if such a feature exist for *nix file systems.
Why do you want to anchor your program logic in the filesystem of the OS? That isn't a proper way to store such a information. One reason is that you leave your application domain and other programs could override your saved information.
Or if you move your application to a newer server, you may run in trouble that you cant transfer this information (e.g. as the new environment has another filesystem).
It is also bad practice to suppose a specific filesystem where your application is running.
A better way is to store this in your application (e.g. database if you need it persistent).
A simple array can do this job, with key as priority and value an array with objects of Directory for example.
It could look like this:
array(
0 => array( // highest prio
0 => DirObject,
1 => DirObject,
2 => DirObject
),
1 => array(
0 => DirObject,
1 => DirObject,
...
), ...
Then you can present your folders with an flatten function or a simple foreach. And can easily save it as serialized/jsoned string in a database.

Categories