Skip to content

Commit

Permalink
Add --recursive mode for folders, update docs, improve headings parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
zoka123 authored and forikal-uk committed Jun 12, 2018
1 parent 09663d8 commit c5402b6
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 16 deletions.
9 changes: 6 additions & 3 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Installation
- Clone this project
- Run `composer install`
- test the console app: `php bin/console.php --help`
- test the console app: `php bin/gsheet-to-xml.php --help`

__Note__ Make sure you're using at least PHP 7.1

Expand All @@ -11,15 +11,18 @@ See: [How to: Google API Setup](https://github.com/forikal-uk/xml-authoring-libr


# Usage
`php bin/console.php forikal:gsheet-to-xml {URL} [--credentials=client_secret.json]`
`php bin/gsheet-to-xml.php {URL} [--credentials=client_secret.json] [--recursive]`

`{URL}` should be either Drive or Sheets URL in one of following formats
- https://drive.google.com/drive/folders/xxxxxxxxxx-xxxxxxxxx-xxxxxxxxxxxx
- https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/edit

`--credentials` is optional parameter that specifies path to the credentials file with Google secret. Path
`-c, --credentials` is optional parameter that specifies path to the credentials file with Google secret. Path
must be relative to the directory you're calling the script from.

`-r, --recursive` if the Google Drive entity is a Google Drive folder, this option specifies whether or not to recurse
through sub-directories to find sheets.

# Behavior

- Empty rows are skipped without notice.
Expand Down
16 changes: 13 additions & 3 deletions src/Application/Service/GoogleDriveFolderReadService.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

class GoogleDriveFolderReadService
{
const FOLDER_MIME_TYPE = 'application/vnd.google-apps.folder';
const SPREADSHEET_MIME_TYPE = 'application/vnd.google-apps.spreadsheet';

/** @var Google_Client */
private $client;

Expand All @@ -16,7 +19,7 @@ public function __construct(Google_Client $client)
$this->client = $client;
}

public function listSpreaadsheetsInFolder($folderId)
public function listSpreaadsheetsInFolder($folderId, bool $recursive)
{
$service = new Google_Service_Drive($this->client);

Expand All @@ -27,7 +30,7 @@ public function listSpreaadsheetsInFolder($folderId)
// In the Drive API, a folder is essentially a file — one identified by the special
// folder MIME type application/vnd.google-apps.folder
$mimeType = $file->getMimeType();
if ('application/vnd.google-apps.folder' !== $mimeType) {
if (self::FOLDER_MIME_TYPE !== $mimeType) {
throw new \Exception("File with ID $folderId is not Google Drive Folder");
}

Expand All @@ -40,7 +43,14 @@ public function listSpreaadsheetsInFolder($folderId)
$fileIds = [];
/** @var Google_Service_Drive_DriveFile $childrenFile */
foreach ($files as $childrenFile) {
if ('application/vnd.google-apps.spreadsheet' !== $childrenFile->getMimeType()) {

if (self::FOLDER_MIME_TYPE === $childrenFile->getMimeType() && true === $recursive) {
$subfolderSpreadsheets = $this->listSpreaadsheetsInFolder($childrenFile->getId(), true);
$fileIds = array_merge($fileIds, $subfolderSpreadsheets);
continue;
}

if (self::SPREADSHEET_MIME_TYPE !== $childrenFile->getMimeType()) {
continue;
}

Expand Down
9 changes: 4 additions & 5 deletions src/Application/Service/GoogleDriveProcessService.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ public function __construct(
$this->xmlSerializer = $xmlSerializer;
}

public function process($url)
public function process(string $url, bool $recursive)
{
if ($this->isSpreadsheet($url)) {
return $this->processSpreadsheet($url);
}

if ($this->isFolder($url)) {
return $this->processFolder($url);
return $this->processFolder($url, $recursive);
}

throw new Exception('URL is not either Google Spreadsheet nor Google Drive Folder');
Expand Down Expand Up @@ -103,7 +103,7 @@ public function processSpreadsheet(string $url): string
return $xml;
}

public function processFolder(string $url)
public function processFolder(string $url, bool $recursive)
{
$folderId = $this->parseFolderIdFromUrl($url);
if (true === empty($folderId)) {
Expand All @@ -112,12 +112,11 @@ public function processFolder(string $url)

$client = $this->makeClient();
$driveService = new GoogleDriveFolderReadService($client);
$spreadsheetFileIds = $driveService->listSpreaadsheetsInFolder($folderId);
$spreadsheetFileIds = $driveService->listSpreaadsheetsInFolder($folderId, $recursive);

/**
* Each Google Sheet tab represents one of these: <Product><Inventory>...data here..</Inventory></Product>.
*/

$spreadsheetService = new GoogleSpreadsheetReadService($client);
$inventories = [];
foreach ($spreadsheetFileIds as $spreadsheetFileId) {
Expand Down
36 changes: 34 additions & 2 deletions src/Application/Service/GoogleSpreadsheetReadService.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,12 @@ private function combineSheetDataWithHeadings(array $data): array
continue;
}

// First non-empty row are headings
if (true === empty($headings)) {
// Skip non-headings rows until we find headings
if (true === empty($headings) && false === $this->isHeadingsRow($row)) {
continue;
}

if (true === empty($headings) && true === $this->isHeadingsRow($row)) {
$headings = $row;
continue;
}
Expand Down Expand Up @@ -127,4 +131,32 @@ private function isEmptyRow(?array $row): bool

return false;
}

private function isHeadingsRow(?array $row): bool
{
if (true === empty($row)) {
return false;
}

$firstCellValue = $row[0] ?? null;
if (true === empty($firstCellValue)) {
return false;
}

$headingValues = [
'Name',
'KNumberExists',
'KNumber',
'Quantity',
'AlternativeNumber',
'Purpose',
'PurposeOther',
];

if (true === in_array(trim($firstCellValue), $headingValues)) {
return true;
}

return false;
}
}
2 changes: 1 addition & 1 deletion src/Application/Service/XmlSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ private function buildInventoryElement(DOMDocument $dom, Inventory $inventory)
{
$inventoryXmlElement = $dom->createElement('Inventory');
$inventoryXmlElement->setAttribute('src-sheet', $inventory->getSpreadsheetName());
$inventoryXmlElement->setAttribute('src-sheet-url', $inventory->getSpreadsheetUrl());
$inventoryXmlElement->setAttribute('src-tab', $inventory->getSheetName());
$inventoryXmlElement->setAttribute('src-sheet-url', $inventory->getSpreadsheetUrl());

/** @var StockItem $stockItem */
foreach ($inventory->getStockItems() as $stockItem) {
Expand Down
10 changes: 9 additions & 1 deletion src/Command/GsheetToXmlCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,19 @@ protected function configure()
InputOption::VALUE_OPTIONAL,
'Path to the Google credentials JSON relative to the current working directory',
'client_secret.json'
)
->addOption(
'recursive',
'r',
InputOption::VALUE_NONE,
'if the Google Drive entity is a Google Drive folder, this option specifies whether or not to recurse through sub-directories to find sheets.'
);
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$url = $input->getArgument('drive-url');
$recursive = $input->getOption('recursive');

$credentialsPath = $input->getOption('credentials');
$credentialsPath = getcwd() . '/' . ltrim($credentialsPath, '/');
Expand All @@ -49,7 +56,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
$inventoryFactory = new InventoryFactory();

$service = new GoogleDriveProcessService($credentialsPath, $inventoryFactory, $serializer);
$xml = $service->process($url);
$xml = $service->process($url, $recursive
);
$output->writeln($xml);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function testSingleInventory()
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Products>
<Product>
<Inventory src-sheet="Spreadsheet x" src-sheet-url="https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/edit" src-tab="Sheet 1">
<Inventory src-sheet="Spreadsheet x" src-tab="Sheet 1" src-sheet-url="https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/edit">
<StockItem>
<KNumberExists>true</KNumberExists>
<KNumber>111111</KNumber>
Expand Down

0 comments on commit c5402b6

Please sign in to comment.