首页 > 解决方案 > 如何使用 google docs api php 插入文本

问题描述

我正在尝试使用 Google Docs Api 创建文档的副本,然后通过在其中插入文本来编辑该副本。所以,我查看了文档,似乎完全按照它所说的方式实现了它。

<?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;
                }
            }

        ?>

此处定义了 GoogleDrive::getClient 以防万一

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;

    }

}


但是,当我运行前面的代码时,我得到了这个错误。

"{
  "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"
  }
}
"

任何帮助或指导将不胜感激。

编辑 1:我更改了脚本以反映 Tanaike 的解决方案

标签: phpjsongoogle-drive-apigoogle-docs

解决方案


我相信你的情况和目标如下。

  • 您已经能够使用 Google Docs API。
  • 工作的脚本a copy of a document
  • 您想删除问题中的错误。

对于这个,这个修改怎么样?

从:

$desiredRequests = new Google_Service_Docs_Request(array(
    'insertText' => array(
    'text' => 'Hello world!',
    'location' => array(
    'index' => 25))));
  • 在您的脚本中,当$batchUpdateRequests被检索时,它变为如下。

    {"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":{}}}
    
    • 我认为这是您的问题的原因。

到:

$desiredRequests = array(new Google_Service_Docs_Request(array(
    'insertText' => array(
    'text' => 'Hello world!',
    'location' => array(
    'index' => 25)))));
  • 在这个修改后的脚本中,当$batchUpdateRequests被检索到时,变成如下。

    {"requests":[{"insertText":{"text":"Hello world!","location":{"index":25,"segmentId":null}}}]}
    
    • 在这个请求正文中,我可以确认它有效。

笔记:

  • 如果出现类似的错误Invalid requests[0].insertText: Index 25 must be less than the end index of the referenced segment,请修改'index' => 25'index' => 1.

参考:


推荐阅读