I'm trying to create a copy of a document using the Google Docs Api, and then edit it that copy by inserting text into it. So, I've looked at the documentation and seemingly implemented it exactly the way it says.
<?php
//That is, if this is just a regular login
//Personal Files
require("loginManager.php");
require("globals.php");
require("googleDrive.php");
//Moodle files
require("../config.php");
require("../my/lib.php");
require("../files/renderer.php");
require("../course/lib.php");
//Google Docs
$CREDENTIALS_PATH = "../../" . "vendor/autoload.php";
require ($CREDENTIALS_PATH);
//Example code
$copyTitle = 'Copy Title';
$documentId = "1vYyeGLbadFi0sl9g2LEJSZCB4YiGOpCb";
$copy = new Google_Service_Drive_DriveFile(array(
'name' => $copyTitle
));
//Initialize necessary client variables
$desiredPath = "../../credentials.json";
$authCode = (isset($_GET["code"]) ? $_GET["code"]:"");
GoogleDrive::setAuthCode($authCode);
$client = GoogleDrive::getClient($desiredPath, $FULLSCRIPT);
$docServices = new Google_Service_Docs($client);
$driveServices = new Google_Service_Drive($client);
$files = $driveServices->files;
$documents = $docServices->documents;
$driveResponse = $files->copy($documentId, $copy);
$documentCopyId = $driveResponse->id;
//Create desiredRequests
$desiredRequests = array(new Google_Service_Docs_Request(array(
'insertText' => array(
'text' => 'Hello world!',
'location' => array(
'index' => 25)))));
$batchUpdateRequests = new Google_Service_Docs_BatchUpdateDocumentRequest(array(
'requests' => $desiredRequests));
$docChangeResponse = $documents->batchUpdate($documentCopyId, $batchUpdateRequests);
echo $OUTPUT->header();
echo $OUTPUT->custom_block_region('content');
echo $OUTPUT->footer();
//Check if there's any get actions that need to be serviced
$getVariable = filter_input(INPUT_GET, "action");
if($getVariable == "openFileManager") {core_files_renderer::render_form_filemanager();}
else if($getVariable == "createCourse")
{
/*Important note: there are two types of ids when it comes to courses
*
* Programmer's Notes:
*
* -$instance is the instance of a record of from the enrol table
* -the enrol table stores instances of courses...so does mdl_course
* -idnumber and id, the latter is the actual primary key, the other is
* I guess is for school admins or course creators to be able to number
* the courses according to their own system. idnumber can be null.
*
*/
$enrollmentPlugin = enrol_get_plugin("manual");
if($enrollmentPlugin)
{
//Create data for course_request
$data = new stdClass();
$data->requester = $USER->id;
$data->id = 1;
$course_request_object = new course_request($data);
unset($data);
//create data for new course
$data = new stdClass();
$data->fullname = 'Math';
$data->shortname = 'Math 7';
$data->summary = 'Awesome!';
$data->summaryformat = FORMAT_PLAIN;
$data->format = 'topics';
$data->newsitems = 0;
$data->numsections = 5;
//$data->category = $course_request_object->get_category();
$data->category = 1;
$course = create_course($data);
//Instance is the record from the enrol table
$instanceid = $enrollmentPlugin->add_instance($course);
$instance = $DB->get_record('enrol', array('courseid'=>$course->id, 'enrol'=>'manual'), '*', MUST_EXIST);
$enrollmentPlugin->enrol_user($instance, $USER->id);
}
}
else if($getVariable == "appendDocument")
{
$courseID = filter_input(INPUT_GET, "courseID");
$fs = get_file_storage();
$data = array(
'contextid' => $courseID, // ID of context
'component' => 'course_myarea', // usually = table name
'filearea' => 'myarea', // usually = table name
'itemid' => 0, // usually = ID of row in table
'filepath' => '/', // any path beginning and ending in /
'filename' => 'myfile.txt'
);
$content = "hellp worldl";
$fs->create_file_from_string($data, $content);
}
else if($getvariable == null)
{
//if there are no get paramaters then it's a first time entry
//get all of user's courses, files, etc
$courses = enrol_get_all_users_courses($USER->id);
global $DB;
foreach($courses as $currentCourse)
{
$desiredID = $currentCourse->id;
$desiredFiles = $DB->get_record('files', array('contextid'=> $desiredID));
$contentHash = $desiredFiles->contenthash;
$dir1 = substr($contentHash, 0, 2); $dir2 = substr($contentHash, 2, 2);
$desiredPath = $CFG->dirrot."../../../../moodledata/filedir/"
.$dir1."/".$dir2."/".$contentHash;
$myFile = file_get_contents($desiredPath);
$type = mime_content_type($desiredPath);
$contentTypes = array("pdf" => "application/pdf",
"txt" => "text/plain");
//header("Content-Type: application/pdf");
//readfile($desiredPath, false, $foo);
$myFile = file_get_contents("goedel.pdf");
$foo = 3;
}
}
?>
Here's where GoogleDrive::getClient is defined in case it helps
class GoogleDrive
{
private static $AUTH_CODE;
public static function setAuthCode($desiredCode)
{
self::$AUTH_CODE = $desiredCode;
}
public static function getClient($credentialsPath, $callbackScript)
{
$client = new Google_Client();
$client->setApplicationName('MyApp');
$client->setScopes(Google_Service_Drive::DRIVE);
$client->setAuthConfig($credentialsPath);
$client->setAccessType('online');
$client->setPrompt('select_account consent');
$desiredVariable = self::$AUTH_CODE;
if($desiredVariable != null)
{
$accessToken = $client->fetchAccessTokenWithAuthCode($desiredVariable);
$client->setAccessToken($accessToken);
return $client;
}
// Load previously authorized token from a file, if it exists.
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
$tokenPath = 'token.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
// If there is no previous token or it's expired.
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
$client->setRedirectUri($callbackScript);
redirect($authUrl);
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Check to see if there was an error.
if (array_key_exists('error', $accessToken)) {
throw new Exception(join(', ', $accessToken));
}
}
// Save the token to a file.
if (!file_exists(dirname($tokenPath))) {
mkdir(dirname($tokenPath), 0700, true);
}
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
}
return $client;
}
}
However, when I run the previous code I get this error.
"{
"error": {
"code": 400,
"message": "This operation is not supported for this document",
"errors": [
{
"message": "This operation is not supported for this document",
"domain": "global",
"reason": "failedPrecondition"
}
],
"status": "FAILED_PRECONDITION"
}
}
"
Any help or direction will be greatly appreciated.
Edit 1: I've changed the script to reflect Tanaike's solution
I believe your situation and goal as follows.
You have already been able to use Google Docs API.
The script of a copy of a document worked.
You want to remove the error in your question.
For this, how about this modification?
From:
$desiredRequests = new Google_Service_Docs_Request(array(
'insertText' => array(
'text' => 'Hello world!',
'location' => array(
'index' => 25))));
In your script, when $batchUpdateRequests is retrieved, it becomes as follows.
{"requests":{"createNamedRangeType":{},"createNamedRangeDataType":{},"createParagraphBulletsType":{},"createParagraphBulletsDataType":{},"deleteContentRangeType":{},"deleteContentRangeDataType":{},"deleteNamedRangeType":{},"deleteNamedRangeDataType":{},"deleteParagraphBulletsType":{},"deleteParagraphBulletsDataType":{},"deletePositionedObjectType":{},"deletePositionedObjectDataType":{},"deleteTableColumnType":{},"deleteTableColumnDataType":{},"deleteTableRowType":{},"deleteTableRowDataType":{},"insertInlineImageType":{},"insertInlineImageDataType":{},"insertTableRowType":{},"insertTableRowDataType":{},"insertTextType":{},"insertTextDataType":{},"replaceAllTextType":{},"replaceAllTextDataType":{},"updateParagraphStyleType":{},"updateParagraphStyleDataType":{},"updateTextStyleType":{},"updateTextStyleDataType":{},"internal_gapi_mappings":{},"modelData":{},"processed":{},"insertText":{}}}
I think that this is the reason of your issue.
To:
$desiredRequests = array(new Google_Service_Docs_Request(array(
'insertText' => array(
'text' => 'Hello world!',
'location' => array(
'index' => 25)))));
In this modified script, when $batchUpdateRequests is retrieved, it becomes as follows.
{"requests":[{"insertText":{"text":"Hello world!","location":{"index":25,"segmentId":null}}}]}
In this request body, I could confirm that it worked.
Note:
If an error like Invalid requests[0].insertText: Index 25 must be less than the end index of the referenced segment occurs, please modify 'index' => 25 to 'index' => 1.
Reference:
Method: documents.batchUpdate
I am very new to PHP, I am using PHP Slim Framework. I have tried to research through Stack Overflow but didn't find an answer that answered my question.
I am trying add a car description on my school project, it captures all the fields well but the image is not being saved to the database and not being uploaded to the images folder, instead it saves the image in the database as a json as:
{
"car_images":
[
{
"file":"C:\\xampp\\tmp\\php8F2B.tmp"
}
]
}
instead of a91cffe8c9b5082f.jpg.
when I try to view the image in a browser on my localhost it goes to this path:
http://localhost/carbac/public/category_image/%7B%22car_images%22:[%7B%22file%22:%22C://xampp//tmp//php8F2B.tmp%22%7D]%7D
What could I be doing wrong?
Below is my function for capturing the details:
public function add(Request $request, Response $response, $args){
$car_category_id = $request->getParam('car_category_id');
$name = $request->getParam('name');
$description = $request->getParam('description');
$price = $request->getParam('price');
$mileage = $request->getParam('mileage');
$fuel_type = $request->getParam('fuel_type');
$transmission = $request->getParam('transmission');
$fuel_economy = $request->getParam('fuel_economy');
$air_condition = $request->getParam('air_condition');
$hourly_price = $request->getParam('hourly_price');
$daily_price = $request->getParam('daily_price');
$year = $request->getParam('year');
$directory = __DIR__ . '/../../../public/profile_image';
$uploadedFiles = $request->getUploadedFiles()['category_image'];
$avater = $request->getUploadedFiles();
foreach($uploadedFiles as $uploadedFile) {
if ($uploadedFile->getError() === UPLOAD_ERR_OK) {
$avater[] = \App\Helpers\FileUpload::moveUploadedFile($directory, $uploadedFile, ['png', 'jpeg', 'gif', 'jpg']);
} else {
$Flash = new Flash();
$Flash->addMessage('message', "Sorry, something went wrong from our end, please notify site owner");
$Flash->addMessage('status', "callout-danger");
return $response->withRedirect($this->router->pathFor('car_description'));
}
}
if( ! $avater ) {
$Flash = new Flash();
$Flash->addMessage('message', "Sorry, Please make image you are uploading is either a 'png', 'jpeg' or 'gif'");
$Flash->addMessage('status', "callout-danger");
return $response->withRedirect($this->router->pathFor('car_description'));
}
$car_description = CarDescription::create([
'car_category_id' => $car_category_id,
'name' => $name,
'description' => $description,
'year' => $year,
'mileage' => $mileage,
'price' => $price,
'fuel_type' => $fuel_type,
'transmission' => $transmission,
'fuel_economy' => $fuel_economy,
'air_condition' => $air_condition,
'hourly_price' => $hourly_price,
'daily_price' => $daily_price,
'images' => json_encode($avater)
]);
I started using the php quickstart to connect and create users. Everything works, but cannot add a second email address.
The help is confusing, and can't find an example.
My code so far:
// Get the API client and construct the service object.
$client = getClient();
$service = new Google_Service_Directory($client);
// USER DATA
$userName = 'Test';
$userSurname = 'User';
$userDocument = '12345678';
$userEmail = 'test#mail.com';
$name = new Google_Service_Directory_UserName();
$email = new Google_Service_Directory_UserEmail();
$user = new Google_Service_Directory_User();
// CREATE USER TO INSERT
$name->setGivenName($userName);
$name->setFamilyName($userSurname);
$name->setFullName($userName . ' ' . $userSurname);
$email->setAddress($userEmail);
$email->setType('home');
$user->setName($name);
$user->setHashFunction('SHA-1');
$user->setPassword(hash('sha1', $userDocument));
$user->setPrimaryEmail($userName . '.' . $userSurname . '#domain.com');
$user->setSuspended(false);
$user->setChangePasswordAtNextLogin(true);
$user->setEmails(array('address' => 'test#mail.com', 'type' => 'home', 'customType' => '', 'primary' => false)); // don't work
// $user->setEmails($email); // don't work either
$user->setOrgUnitPath('/org/path');
try
{
$createUserResult = $service->users->insert($user);
}
I find the error. The setEmails method receives an multidimensional array, so:
$user->setEmails(array(array('address' => 'test#mail.com', 'type' => 'home', 'customType' => '', 'primary' => false)));
I am trying to get data from Google spreadsheet by some specific value, currently I have tried the following method:
$spreadsheetService = new Google\Spreadsheet\SpreadsheetService();
$spreadsheetFeed = $spreadsheetService->getSpreadsheets();
$spreadsheet = $spreadsheetFeed->getByTitle(APPLICATION_GOOGLE_SPREADSHEETS_BOOK);
$worksheetFeed = $spreadsheet->getWorksheets();
$worksheet = $worksheetFeed->getByTitle(APPLICATION_GOOGLE_SPREADSHEETS_SHEET);
It works fine when I use this:
$listFeed = $worksheet->getListFeed(array("sq" => "name = henryhwong", "reverse" => "true"));
but when it do the same for email it gives error:
$listFeed = $worksheet->getListFeed(array("sq" => "email = henryhwong#gmail.com", "reverse" => "true"));
The error is because of "#", if search anything else which doesn't contain "#" sign then it works perfectly, I am unable to find the cause behind this.
Had a similar problem before. Try put email in double quotes:
$listFeed = $worksheet->getListFeed(array("sq" => 'email = "henryhwong#gmail.com"', "reverse" => "true"));
Try this code below. Hope it helps you.
$listFeed = $worksheet->getListFeed(array("sq" => "email" = "henryhwong#gmail.com", "reverse" => "true"));
I am using the library googleads/googleads-php-lib from github.
I am trying to create a text ad, but I am getting an error that I cannot set the URL field. The code has been working for quite some time but has suddenly stopped due to this error.
The SoapFault exception that is thrown is:
[AdError.CANNOT_SET_FIELD # operations[0].operand.ad.url]
My code is as follows:
require_once('Google/Api/Ads/AdWords/Lib/AdWordsUser.php');
$developerToken = '*removed*';
$clientCustomerId = '*removed*';
$userAgent = 'test';
$settingsIniPath = './vendor/googleads/googleads-php-lib/src/Google/Api/Ads/AdWords/settings.ini';
$oAuth = array(
'client_id' => '*removed*',
'client_secret' => '*removed*',
'refresh_token' => '*removed*',
);
$adWordsUser = new AdWordsUser(null, $developerToken, $userAgent, $clientCustomerId, $settingsIniPath, $oAuth);
$adWordsUser->SetDefaultVersion('v201409');
$adGroupId = *removed*;
$textAd = new TextAd();
$textAd->headline = 'headline text';
$textAd->description1 = 'description1 text';
$textAd->description2 = 'description2 text';
$textAd->displayUrl = 'www.example.com';
$textAd->url = 'http://www.example.com/';
$adGroupAd = new AdGroupAd($adGroupId, $textAd);
$operations = array(new AdGroupAdOperation($adGroupAd, null, 'ADD'));
$adGroupAdService = $adWordsUser->GetService('AdGroupAdService');
$result = $adGroupAdService->mutate($operations);
I am not sure what could be causing this error. Any help would be greatly appreciated.
got caught with that too. The problem seems to be that "url" is no longer supported, you have to use "targetUrls" of upgraded URLs API instead:
http://googleadsdeveloper.blogspot.cz/2015/05/reminder-adwords-destination-urls-will.html