Как вставить текст с помощью Google Docs API php - PullRequest
1 голос
/ 29 апреля 2020

Я пытаюсь создать копию документа с помощью 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: Я изменил сценарий, чтобы отразить решение Танаике

1 Ответ

0 голосов
/ 30 апреля 2020

Я считаю, что ваша ситуация и цель следующие.

  • Вы уже можете использовать 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.

Ссылка:

...