]> 91.132.146.200 Git - bibliotheca-php.git/commitdiff
added google books fetch by isbn
authorBanana <mail@bananas-playground.net>
Sat, 8 Apr 2023 09:55:27 +0000 (11:55 +0200)
committerBanana <mail@bananas-playground.net>
Sat, 8 Apr 2023 09:55:27 +0000 (11:55 +0200)
15 files changed:
CHANGELOG
TODO
documentation/tools.txt
upgrade/from-version-1.3.tx [deleted file]
upgrade/from-version-1.3.txt [new file with mode: 0644]
upgrade/from-version-1.4.txt [new file with mode: 0644]
webclient/config/config-googlebooks.php.default [new file with mode: 0644]
webclient/config/config-imdbweb.php.default
webclient/config/config-musicbrainz.php.default
webclient/lib/googlebookparser.class.php [new file with mode: 0644]
webclient/lib/musicbrainz.class.php
webclient/setup/bibliotheca.sql.default
webclient/view/default/tool/tool-googlebooks.html [new file with mode: 0644]
webclient/view/default/tool/tool-googlebooks.php [new file with mode: 0644]
webclient/view/default/tool/tool-musicbrainz.php

index 7446ecc2aeffbb717f2afe2779296c1484e97d28..de9f3f2cb3845525077411572261e1b21b621747 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,6 @@
 1.5 - Sacred Passage
+       * Fixed global search in navigation.
+       * Added google books parser. See upgrade file for more infos.
 
 1.4 - Depths Of Rrajigar 2022-12-18
        * Added new default sort direction field in collection edit view. See upgrade file for more needed details
diff --git a/TODO b/TODO
index 218576ced63628cb5bf794994402170d222caef6..4f97bf777caacf51e0eb0f3a9e8a9417bf5dc98d 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,3 +1,4 @@
+* central user-agent and browser info in config. Remove from tools
 * i18n support
 * Automatic upgrades of DB
 * drop in updates
index 2e943f8f210712f1684c7540a9182cd328649fc9..9c3b067f557dde53164f22ba23caabe13db5e411 100644 (file)
@@ -1,6 +1,7 @@
 Each collection can have additional tools. The availability is configured in collection management.
 
-A tool needs an DB entry in _tool and matching files in view/THEME/tool/.
+A tool needs an DB entry in _tool and matching files in view/THEME/tool/. Best is to copy an entry
+and change name, description and action. The other settings can be left as they are, unless you know what they do.
 Filenames are tool-ACTION.html|php
 A optional configuration file config/config-ACTION.php
 A documentation is a must.
diff --git a/upgrade/from-version-1.3.tx b/upgrade/from-version-1.3.tx
deleted file mode 100644 (file)
index e8521d1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copy the following directories and files to your installation folder, overriding the existing ones:
-webclient/config/
-webclient/lib/
-webclient/view/
-webclient/.htaccess
-webclient/api.php
-webclient/index.php
-
-# New syntax in config files
-"define(.." syntax needs to be replace with "const" syntax in all the config files.
-See the default ones about the changes.
-
-# DB changes. Run each line against your bibliotheca DB.
-# Replace #REPLACEME# with your table prefix. Default is bib
-ALTER TABLE `#REPLACEME#_collection` ADD `defaultSortOrder` VARCHAR(4) NOT NULL AFTER `defaultSortField`;
-ALTER TABLE `#REPLACEME#_menu` ADD `contextaction` VARCHAR(64) NOT NULL AFTER `action`;
-UPDATE `#REPLACEME#_menu` SET `contextaction` = 'collection' WHERE `#REPLACEME#_menu`.`id` = 4;
-UPDATE `#REPLACEME#_menu` SET `contextaction` = 'collection' WHERE `#REPLACEME#_menu`.`id` = 6;
diff --git a/upgrade/from-version-1.3.txt b/upgrade/from-version-1.3.txt
new file mode 100644 (file)
index 0000000..e8521d1
--- /dev/null
@@ -0,0 +1,18 @@
+# Copy the following directories and files to your installation folder, overriding the existing ones:
+webclient/config/
+webclient/lib/
+webclient/view/
+webclient/.htaccess
+webclient/api.php
+webclient/index.php
+
+# New syntax in config files
+"define(.." syntax needs to be replace with "const" syntax in all the config files.
+See the default ones about the changes.
+
+# DB changes. Run each line against your bibliotheca DB.
+# Replace #REPLACEME# with your table prefix. Default is bib
+ALTER TABLE `#REPLACEME#_collection` ADD `defaultSortOrder` VARCHAR(4) NOT NULL AFTER `defaultSortField`;
+ALTER TABLE `#REPLACEME#_menu` ADD `contextaction` VARCHAR(64) NOT NULL AFTER `action`;
+UPDATE `#REPLACEME#_menu` SET `contextaction` = 'collection' WHERE `#REPLACEME#_menu`.`id` = 4;
+UPDATE `#REPLACEME#_menu` SET `contextaction` = 'collection' WHERE `#REPLACEME#_menu`.`id` = 6;
diff --git a/upgrade/from-version-1.4.txt b/upgrade/from-version-1.4.txt
new file mode 100644 (file)
index 0000000..7eb3881
--- /dev/null
@@ -0,0 +1,14 @@
+# Copy the following directories and files to your installation folder matching the correct path.
+webclient/view/default/tool/tool-googlebooks.html
+webclient/view/default/tool/tool-googlebooks.php
+webclient/lib/googlebookparser.class.php
+webclient/config/config-googlebooks.php.default -> also copy and rename to config-googlebooks.php
+
+# DB changes. Run each line against your bibliotheca DB.
+# Replace #REPLACEME# with your table prefix. Default is bib
+INSERT INTO `#REPLACEME#_tool` (`id`, `name`, `description`, `action`, `target`, `owner`, `group`, `rights`) VALUES (NULL, 'Google Books', 'Book infos from Google', 'googlebooks', '_self', '1', '1', 'rw-r--r--');
+UPDATE `#REPLACEME#_sys_fields` SET `createstring` = '`isbn` varchar(32) NULL, ADD INDEX (`isbn`)', `apiinfo` = 'varchar 32' WHERE `#REPLACEME#_sys_fields`.`identifier` = 'isbn';
+UPDATE `#REPLACEME#_sys_fields` SET `type` = 'text', `searchtype` = 'entrySingleText' WHERE `#REPLACEME#_sys_fields`.`identifier` = 'isbn';
+
+# if you use the field ISBN already run this and change the collection id
+ALTER TABLE `#REPLACEME#_collection_entry_#CHANGE_ID#` CHANGE `isbn` `isbn` VARCHAR(32) NULL DEFAULT NULL;
diff --git a/webclient/config/config-googlebooks.php.default b/webclient/config/config-googlebooks.php.default
new file mode 100644 (file)
index 0000000..214c2ed
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Bibliotheca
+ *
+ * Copyright 2018-2023 Johannes Keßler
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Options for the Googlebook class
+ *
+ * TOOL_GOOGLEBOOKS_FIELDS_TO is a array to define which fields should be saved into
+ *             a bibliotheca field. Those or the fields a collection can have. Use the identifier of a field.
+ *             Depends on your settings so make sure everything is setup first. Leave it commented if not needed.
+ *             nameFromService or class => bibFieldName
+ * TOOL_GOOGLEBOOKS_BROWSER_AGENT a current browser agent string. Should be updated from time to time. See default config file.
+ * TOOL_GOOGLEBOOKS_BROWSER_ACCEPT A string what the browser does accept. Should be updated from time to time. See default config file.
+ * TOOL_GOOGLEBOOKS_BROWSER_ACCEPT_LANG should define in which language the content returns
+ */
+
+const TOOL_GOOGLEBOOKS_BROWSER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0';
+const TOOL_GOOGLEBOOKS_BROWSER_ACCEPT = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
+const TOOL_GOOGLEBOOKS_BROWSER_ACCEPT_LANG = 'en-US,en;q=0.5';
+
+const TOOL_GOOGLEBOOKS_FIELDS_TO = array(
+       'title' => 'title',
+       'cover' => 'coverimage',
+       'description' => 'content',
+       'subtitle' => 'description',
+       'isbn' => 'isbn',
+       'authors' => 'writers',
+       'publisher' => 'publisher',
+       'publishedDate' => 'year',
+       'categories' => 'genres'
+);
index 262481a86ccd7fc23aeaa6c6de88df2d79b05b67..6c2daf2fd73c040aea18ca72fdb3285668b9a530 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Bibliotheca
  *
- * Copyright 2018-2021 Johannes Keßler
+ * Copyright 2018-2023 Johannes Keßler
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * TOOL_IMDBWEB_FIELDS_TO is a array to define which imdbwebfield (see TOOL_IMDBWEB_FIELDS) should be saved into
  *             a bibliotheca field. Those or the fields a collection can have. Use the identifier of a field.
  *             Depends on your settings so make sure everything is setup first. Leave it commented if not needed.
+ *      nameFromService => bibFieldName
  * TOOL_IMDBWEB_BROWSERSTRING a current browser agent string. Should be updated from time to time. See default config file.
  * TOOL_IMDBWEB_BROWSER_ACCEPT_LANG should define in which language the content returns
 */
-const = TOOL_IMDBWEB_SEARCH = 'movie';
-const = TOOL_IMDBWEB_FIELDS =
-       array(
-               'getCast = 'getDescription =  'getDirector =  'getGenre =  'getPlot =  'getRating =  'getRuntime = 'getTitle =
-               'getWriter =  'getYear'
-       )
-;
+const TOOL_IMDBWEB_SEARCH = 'movie';
+const TOOL_IMDBWEB_FIELDS = array(
+       'getCast', 'getDescription', 'getDirector', 'getGenre', 'getPlot', 'getRating', 'getRuntime', 'getTitle',
+       'getWriter', 'getYear'
+);
 /*
-const = TOOL_IMDBWEB_FIELDS_TO =
-       array(
-               'getCast' => 'actors = 'getDescription' => 'description =  'getDirector' => 'directors =  'getGenre' => 'genres =
-               'getPlot' => 'content =  'getRating' => 'imdbrating =  'getRuntime' => 'runtime = 'getTitle' => 'title =
-               'getWriter' => 'writers =  'getYear' => 'year'
-       )
-;
+const TOOL_IMDBWEB_FIELDS_TO = array(
+       'getCast' => 'actors', 'getDescription' => 'description', 'getDirector' => 'directors', 'getGenre' => 'genres',
+       'getPlot' => 'content', 'getRating' => 'imdbrating', 'getRuntime' => 'runtime', 'getTitle' => 'title',
+       'getWriter' => 'writers', 'getYear' => 'year'
+);
 */
 
-const TOOL_IMDBWEB_BROWSER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0';
-const TOOL_IMDBWEB_BROWSER_ACCEPT = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
-const TOOL_IMDBWEB_BROWSER_ACCEPT_LANG = 'en-US,en;q=0.5';
+const TOOL_IMDBWEB_BROWSER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0';
+const TOOL_IMDBWEB_BROWSER_ACCEPT = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
+const TOOL_IMDBWEB_BROWSER_ACCEPT_LANG = 'en-US,en;q=0.5';
index 6ce41df02c24185f4c0619307591953687989f90..a20a021ff909f4c87cf44e1bae60bc0166b2b8e7 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Bibliotheca
  *
- * Copyright 2018-2021 Johannes Keßler
+ * Copyright 2018-2023 Johannes Keßler
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 /**
  * Options for the musicbrainz class
-
- * Currently available fields are:
- *             album,date,artist,tracks,image,runtime
+ *
  * TOOL_BRAINZ_FIELDS_TO is a array to define which fields should be saved into
  *             a bibliotheca field. Those or the fields a collection can have. Use the identifier of a field.
  *             Depends on your settings so make sure everything is setup first. Leave it commented if not needed.
+ *      nameFromService => bibFieldName
  * TOOL_BRAINZ_BROWSER_AGENT a current browser agent string. Should be updated from time to time. See default config file.
  * TOOL_BRAINZ_BROWSER_ACCEPT A string what the browser does accept. Should be updated from time to time. See default config file.
  * TOOL_BRAINZ_BROWSER_ACCEPT_LANG should define in which language the content returns
  * TOOL_BRAINZ_RESULT_LIMIT How many entries the search will display
  */
 
-const TOOL_BRAINZ_BROWSER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0';
-const TOOL_BRAINZ_BROWSER_ACCEPT = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
-const TOOL_BRAINZ_BROWSER_ACCEPT_LANG = 'en-US,en;q=0.5';
+const TOOL_BRAINZ_BROWSER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0';
+const TOOL_BRAINZ_BROWSER_ACCEPT = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
+const TOOL_BRAINZ_BROWSER_ACCEPT_LANG = 'en-US,en;q=0.5';
 
-const TOOL_BRAINZ_RESULT_LIMIT = 10;
+const TOOL_BRAINZ_RESULT_LIMIT = 10;
 
 /*
-const = TOOL_BRAINZ_FIELDS_TO =
-       array(
-               'album' => 'title = 'date' => 'year =  'artist' => 'artist =  'image' => 'coverimage =  'tracks' => 'content =
-               'runtime' => 'runtime'
-       )
-;
+const TOOL_BRAINZ_FIELDS_TO = array(
+       'album' => 'title',
+       'date' => 'year',
+       'artist' => 'artist',
+       'image' => 'coverimage',
+       'tracks' => 'content',
+       'runtime' => 'runtime'
+);
 */
diff --git a/webclient/lib/googlebookparser.class.php b/webclient/lib/googlebookparser.class.php
new file mode 100644 (file)
index 0000000..593b3ee
--- /dev/null
@@ -0,0 +1,228 @@
+<?php
+/**
+ * Bibliotheca
+ *
+ * Copyright 2018-2023 Johannes Keßler
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Class GoogleBooks
+ *
+ * Search for book information with google books
+ *
+ * https://developers.google.com/books/docs/overview
+ *
+ * possible alternative if google does  limit the access: https://openlibrary.org/dev/docs/api/books
+ */
+class GoogleBooks {
+
+       /**
+        * @var String The google api endpoint
+        */
+       private string $_VOLUMES_ENDPOINT = 'https://www.googleapis.com/books/v1/volumes';
+
+       /**
+        * @var bool DEBUG
+        */
+       private bool $_DEBUG = false;
+
+       /**
+        * @var string The user agent used to make curl calls
+        */
+       private string $_BROWSER_AGENT = '';
+
+       /**
+        * @var string The user agent lang used to make curl calls
+        */
+       private string $_BROWSER_LANG = '';
+
+       /**
+        * @var string The user agent accept used to make curl calls
+        */
+       private string $_BROWSER_ACCEPT = '';
+
+       public function __construct(array $options) {
+               if(isset($options['debug']) && !empty($options['debug'])) {
+                       $this->_DEBUG = true;
+               }
+
+               $this->_BROWSER_AGENT = $options['browserAgent'];
+               $this->_BROWSER_LANG = $options['browserLang'];
+               $this->_BROWSER_ACCEPT = $options['browserAccept'];
+       }
+
+       /**
+        * Use a given ISBN and query the google books API with it.
+        * https://developers.google.com/books/docs/overview
+        * for example: https://www.googleapis.com/books/v1/volumes?q=isbn:9780812972153
+        */
+       public function searchForISBN(string $isbn) : array {
+               $data = array();
+
+               if(!empty($isbn)) {
+                       $isbn = urlencode($isbn);
+                       $url = $this->_VOLUMES_ENDPOINT;
+                       $url .= '?q=isbn:'.$isbn;
+
+                       if(DEBUG) error_log("[DEBUG] ".__METHOD__." isbn query url: $url");
+
+                       $do = $this->_curlCall($url);
+                       if(!empty($do)) {
+                               $data = json_decode($do, true);
+                               if(!empty($data)) {
+                                       if(DEBUG) error_log("[DEBUG] ".__METHOD__." isbn json data:".var_export($data,true));
+                                       $data = $this->_buildDataFromISBNsearch($data);
+                               }
+                               else {
+                                       error_log("[ERROR] ".__METHOD__." invalid isbn json data:".var_export($do,true));
+                               }
+                       }
+
+               }
+
+               return $data;
+       }
+
+       /**
+        * Download given URL to a tmp file
+        * make sure to remove the tmp file after use
+        *
+        * @param string $url
+        * @return string
+        */
+       public function downloadCover(string $url): string {
+               $ret = '';
+
+               // replace zoom=1 with zoom=0 or even remove to get the full picture
+               // http://books.google.com/books/content?id=yyaxyKjyp2YC&printsec=frontcover&img=1&zoom=1&source=gbs_api
+
+               $url = str_replace("zoom=1", "zoom=0",$url);
+
+               $_tmpFile = tempnam(sys_get_temp_dir(), "bibliotheca-");
+               $fh = fopen($_tmpFile,"w+");
+               if($this->_DEBUG) {
+                       error_log('[DEBUG] '.__METHOD__.' url '.var_export($url,true));
+               }
+
+               if($fh !== false) {
+
+                       // modified curl call for fetching an image
+                       $ch = curl_init($url);
+                       curl_setopt($ch, CURLOPT_FILE, $fh);
+
+                       curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
+                       curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+                       curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+                       curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
+                       curl_setopt($ch, CURLOPT_USERAGENT, $this->_BROWSER_AGENT);
+
+                       curl_exec($ch);
+                       curl_close($ch);
+
+                       $ret = $_tmpFile;
+               }
+               fclose($fh);
+
+               return $ret;
+       }
+
+       /**
+        * Use the given isb search data and build a nice return array
+        * Since the search is for a isbn, there should be only one result
+        *
+        * @param array $rawData
+        * @return array
+        */
+       private function _buildDataFromISBNsearch(array $rawData) : array {
+               $data = array();
+
+               if(!empty($rawData) && isset($rawData['items'][0]['volumeInfo'])) {
+                       $_d = $rawData['items'][0]['volumeInfo'];
+
+                       $data['title'] = $_d['title'] ?? '';
+                       $data['subtitle'] = $_d['subtitle'] ?? '';
+                       $data['publisher'] = $_d['publisher'] ?? '';
+                       $data['publishedDate'] = $_d['publishedDate'] ?? '';
+                       $data['description'] = $_d['description'] ?? '';
+                       $data['authors'] = isset($_d['authors']) ? implode(",", $_d['authors']) : '';
+                       $data['categories'] = isset($_d['categories']) ? implode(",", $_d['categories']) : '';
+                       $data['cover'] = $_d['imageLinks']['thumbnail'] ?? '';
+
+                       $data['isbn'] = '';
+                       if(isset($_d['industryIdentifiers']) && is_array($_d['industryIdentifiers'])) {
+                               foreach($_d['industryIdentifiers'] as $k=>$v) {
+                                       if($v['type'] == "ISBN_13") {
+                                               $data['isbn'] = $v['identifier'];
+                                       }
+                               }
+                       }
+               }
+
+               return $data;
+       }
+
+       /**
+        * execute a curl call to the given $url
+        *
+        * @param string $url The request url
+        * @return string
+        */
+       private function _curlCall(string $url): string {
+               $ret = '';
+
+               $ch = curl_init();
+
+               curl_setopt($ch, CURLOPT_URL, $url);
+               curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+               curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
+               curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+               curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+               curl_setopt($ch, CURLOPT_MAXREDIRS, 2);
+               curl_setopt($ch, CURLOPT_USERAGENT, $this->_BROWSER_AGENT);
+               curl_setopt($ch, CURLOPT_HTTPHEADER, array(
+                               'Accept: '.$this->_BROWSER_ACCEPT,
+                               'Accept-Language: '.$this->_BROWSER_LANG)
+               );
+
+               $_headers = array();
+               if($this->_DEBUG) {
+                       curl_setopt($ch, CURLOPT_VERBOSE, true);
+
+                       curl_setopt($ch, CURLOPT_HEADERFUNCTION,
+                               function($curl, $header) use (&$_headers) {
+                                       $len = strlen($header);
+                                       $header = explode(':', $header, 2);
+                                       if (count($header) < 2) { // ignore invalid headers
+                                               return $len;
+                                       }
+                                       $_headers[strtolower(trim($header[0]))][] = trim($header[1]);
+                                       return $len;
+                               }
+                       );
+               }
+
+               $do = curl_exec($ch);
+               if(is_string($do) === true) {
+                       $ret = $do;
+               }
+               curl_close($ch);
+
+               if($this->_DEBUG) {
+                       error_log('[DEBUG] '.__METHOD__.' headers '.var_export($_headers,true));
+               }
+
+               return $ret;
+       }
+
+}
index 1a99b9aece163d46227b8d44a380f8d25044e55b..b29bb0ba9f640153a2b8cb188d32e9f32f4a83c9 100644 (file)
@@ -199,7 +199,7 @@ class Musicbrainz {
                                foreach($data['media'] as $media) {
                                        foreach($media['tracks'] as $track) {
                                                $ret['runtime'] += $track['length'];
-                                               $l = $track['length'] / 1000;
+                                               $l = (int) round($track['length'] / 1000);
                                                $l = date("i:s",$l);
                                                $ret['tracks'] .= $track['number'].' - '.$track['title'].' - '.$l."\n";
                                        }
@@ -281,10 +281,9 @@ class Musicbrainz {
         * execute a curl call to the given $url
         *
         * @param string $url The request url
-        * @param integer $port
         * @return string
         */
-       private function _curlCall(string $url, int $port=80): string {
+       private function _curlCall(string $url): string {
                $ret = '';
 
                $ch = curl_init();
@@ -293,7 +292,6 @@ class Musicbrainz {
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
                curl_setopt($ch, CURLOPT_TIMEOUT, 30);
-               curl_setopt($ch, CURLOPT_PORT, $port);
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
                curl_setopt($ch, CURLOPT_MAXREDIRS, 2);
                curl_setopt($ch, CURLOPT_USERAGENT, $this->_BROWSER_AGENT);
index 8f88a2239ef03a1d1931dbb8e676ef5ede1c1185..cfe1d6b2e06d1f4cce5251bf0111a23cfb113b58 100644 (file)
@@ -166,7 +166,7 @@ INSERT INTO `#REPLACEME#_sys_fields` (`id`, `identifier`, `displayname`, `type`,
 (30, 'sysReq', 'System Requirements', 'text3', 'entryText', '`sysReq` varchar(255) NULL DEFAULT NULL, ADD FULLTEXT (`sysReq`)', '', NULL, 'string 255', '2021-04-25 21:21:54', '2021-04-25 21:21:54', 0, 1, 1, 'rw-r--r--'),
 (31, 'artist', 'Artist', 'text', 'entrySingleText', '`artist` varchar(128) NULL DEFAULT NULL', '', NULL, 'string 128', '2021-07-09 08:30:11', '2021-07-09 08:38:33', NULL, 1, 1, 'rw-r--r--'),
 (32, 'artists', 'Artists', 'lookupmultiple', 'tag', NULL, 'allowSpace', NULL, 'string 64', '2021-07-18 11:19:03', '2021-07-18 11:19:03', NULL, 1, 1, 'rw-r--r--'),
-(33, 'isbn', 'ISBN', 'number', 'entrySingleNum', '`isbn` int(10) NULL, ADD INDEX (`isbn`)', '', NULL, 'int 10', '2022-10-03 09:26:53', '2022-10-03 09:26:53', NULL, 1, 1, 'rw-r--r--');
+(33, 'isbn', 'ISBN', 'text', 'entrySingleText', '`isbn` varchar(32) NULL, ADD INDEX (`isbn`)', '', NULL, 'varchar 32', '2022-10-03 09:26:53', '2022-10-03 09:26:53', NULL, 1, 1, 'rw-r--r--');
 
 -- --------------------------------------------------------
 
@@ -194,6 +194,7 @@ INSERT INTO `#REPLACEME#_tool` (`id`, `name`, `description`, `action`, `target`,
 (1, 'IMDB web', 'Web parser', 'imdbweb', '_self', 1, 1, 'rw-r--r--'),
 (2, 'Game infos', 'Game infos', 'gameinfo', '_self', 1, 1, 'rw-r--r--'),
 (3, 'Musicbrainz', 'Album infos', 'musicbrainz', '_self', 1, 1, 'rw-r--r--');
+(4, 'Google Books', 'Book infos from Google', 'googlebooks', '_self', 1, 1, 'rw-r--r--');
 
 -- --------------------------------------------------------
 
diff --git a/webclient/view/default/tool/tool-googlebooks.html b/webclient/view/default/tool/tool-googlebooks.html
new file mode 100644 (file)
index 0000000..92228be
--- /dev/null
@@ -0,0 +1,55 @@
+<p><b>Limitations</b></p>
+<p>Data will be overwritten</p>
+
+<form class="uk-form-horizontal uk-margin-small" method="post" enctype="multipart/form-data">
+       <div class="uk-margin">
+               <label class="uk-form-label" for="search">Search ISBN</label>
+               <div class="uk-form-controls">
+                       <input class="uk-input" id="search" type="text" autocomplete="off"
+                              name="fdata[search]"
+                              value="<?php echo Summoner::ifset($TemplateData['editEntry'], 'isbn'); ?>"
+                       >
+               </div>
+               <div class="uk-margin">
+                       <button class="uk-button uk-button-primary" type="submit" name="submitFormSearch">
+                               Search
+                       </button>
+               </div>
+       </div>
+</form>
+
+<?php if($TemplateData['showMatchingForm']) { ?>
+<form class="uk-form-horizontal uk-margin-small uk-grid-small"
+      method="post" enctype="multipart/form-data" uk-grid>
+
+       <?php
+       if(!empty($TemplateData['bookData'])) {
+               foreach($TemplateData['bookData'] as $k=>$v) {
+       ?>
+       <input name="fdata[from][<?php echo $k; ?>]" type="hidden" value="<?php echo $v; ?>"  />
+       <div class="uk-width-1-2@s uk-overflow-hidden">
+               <p>
+                       <b><?php echo $k; ?></b><br />
+                       <?php echo nl2br($v); ?>
+               </p>
+       </div>
+       <div class="uk-width-1-2@s">
+               <select class="uk-select" name="fdata[into][<?php echo $k; ?>]">
+                       <option value="">None</option>
+                       <?php echo toolMethod_GetTargetSelection($TemplateData['saveToSelection'],$k); ?>
+               </select>
+       </div>
+
+       <?php
+               }
+       }
+       ?>
+
+       <div class="uk-margin">
+               <button class="uk-button uk-button-primary" type="submit" name="submitFormSave">
+                       Save
+               </button>
+       </div>
+
+</form>
+<?php } ?>
diff --git a/webclient/view/default/tool/tool-googlebooks.php b/webclient/view/default/tool/tool-googlebooks.php
new file mode 100644 (file)
index 0000000..1dac5d2
--- /dev/null
@@ -0,0 +1,167 @@
+<?php
+/**
+ * Bibliotheca
+ *
+ * Copyright 2018-2023 Johannes Keßler
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * this is the special file for a tool.
+ * Requirements and more information come from the main tool.php file
+ */
+
+require_once 'lib/googlebookparser.class.php';
+if(file_exists(PATH_ABSOLUTE.'/config/config-googlebooks.php')) {
+       require_once 'config/config-googlebooks.php';
+}
+
+$GOOGLEBOOKS = new GoogleBooks(array(
+       'browserAgent' => TOOL_GOOGLEBOOKS_BROWSER_AGENT,
+       'browserLang' => TOOL_GOOGLEBOOKS_BROWSER_ACCEPT_LANG,
+       'browserAccept' => TOOL_GOOGLEBOOKS_BROWSER_ACCEPT,
+       'debug' => true
+));
+
+$TemplateData['bookData'] = array();
+$TemplateData['saveToSelection'] = '';
+$TemplateData['showMatchingForm'] = false;
+
+// prepare fields to save into selection
+// create one time and then reuse it
+$collectionFields = $ManangeCollectionsFields->getExistingFields(false, true);
+if(!empty($collectionFields)) {
+       foreach ($collectionFields as $k=>$v) {
+               $TemplateData['saveToSelection'] .= "<option value='".$k."' sel_".$v['identifier'].">".$v['displayname']."</option>\n";
+       }
+}
+
+if(isset($_POST['submitFormSearch'])) {
+       $fdata = $_POST['fdata'];
+       if (!empty($fdata)) {
+               $search = trim($fdata['search']);
+               $search = Summoner::validate($search) ? $search : false;
+
+               if(!empty($search)) {
+                       $booksearch = $GOOGLEBOOKS->searchForISBN($search);
+
+                       if(!empty($booksearch)) {
+                               $TemplateData['bookData'] = $booksearch;
+                               $TemplateData['showMatchingForm'] = true;
+                       } else {
+                               $TemplateData['message']['content'] = "Nothing found.";
+                               $TemplateData['message']['status'] = "error";
+                       }
+               }
+               else {
+                       $TemplateData['message']['content'] = "Invalid search term";
+                       $TemplateData['message']['status'] = "error";
+               }
+       }
+}
+
+if(isset($_POST['submitFormSave'])) {
+       $fdata = $_POST['fdata'];
+       if (!empty($fdata)) {
+
+               // build data array based on submit
+               // see creation log for structure
+               $_data = array();
+               foreach($fdata['into'] as $k=>$v) {
+                       if(!empty($v) && isset($fdata['from'][$k])) {
+                               if(isset($collectionFields[$v])) {
+
+                                       $_data[$v] = $collectionFields[$v];
+                                       $_data[$v]['valueToSave'] = $fdata['from'][$k];
+
+                                       // special case for image
+                                       if($k == "cover") {
+
+                                               $fieldData = array();
+
+                                               $_f = $GOOGLEBOOKS->downloadCover($fdata['from'][$k]);
+                                               if($_f && is_file($_f)) {
+                                                       $_e = UPLOAD_ERR_OK;
+                                                       // build _FILES based on regular add form
+                                                       $fieldData['name'][$_data[$v]['identifier']] = 'cover.jpg';
+                                                       $fieldData['type'][$_data[$v]['identifier']] = mime_content_type($_f);
+                                                       $fieldData['size'][$_data[$v]['identifier']] = filesize($_f);
+                                                       $fieldData['tmp_name'][$_data[$v]['identifier']] = $_f;
+                                                       $fieldData['error'][$_data[$v]['identifier']] = UPLOAD_ERR_OK;
+                                                       $fieldData['rebuildUpload'][$_data[$v]['identifier']] = true;
+                                               }
+
+                                               $_data[$v]['uploadData'] = $fieldData;
+                                       }
+                               }
+                       }
+               }
+
+               $_r = $Tools->getDefaultCreationInfo();
+               if(!empty($TemplateData['editEntry'])) {
+                       // update existing one
+                       $do = $Manageentry->create($_data,
+                               $_r['id'],
+                               $_r['group'],
+                               $_r['rights'],
+                               $TemplateData['editEntry']['id']
+                       );
+                       $TemplateData['message']['content'] = "Date saved successfully";
+               }
+               else {
+                       // create into loaded collection
+                       $do = $Manageentry->create($_data,
+                               $_r['id'],
+                               $_r['group'],
+                               $_r['rights']
+                       );
+                       $TemplateData['message']['content'] = "Date saved successfully: 
+                                               <a href='index.php?p=manageentry&collection=".$collection['id']."&id=".$do."'>Here</a>";
+               }
+
+               if(!empty($do)) {
+                       $TemplateData['message']['status'] = "success";
+               }
+               else {
+                       $TemplateData['message']['content'] = "Data could not be saved. See logs for more.";
+                       $TemplateData['message']['status'] = "error";
+               }
+
+               // remove tmp file
+               if(isset($_f) && is_file($_f) && file_exists($_f)) {
+                       unlink($_f);
+               }
+       }
+}
+
+
+/**
+ * Helper function. Takes the prebuild options for the target selection field and search for a matching key.
+ * Since the optionString is prebuild, avoiding looping over and over again, the selection needs to be done
+ * by search and replace.
+ * Checks if TOOL_GOOGLEBOOKS_FIELDS_TO is defined and a matching key=>value pair is available
+ *
+ * @param string $optionString
+ * @param string $googleKey
+ * @return string
+ */
+function toolMethod_GetTargetSelection(string $optionString, string $googleKey): string {
+       if(defined('TOOL_GOOGLEBOOKS_FIELDS_TO') & !empty($googleKey)) {
+               if(isset(TOOL_GOOGLEBOOKS_FIELDS_TO[$googleKey])) {
+                       $_k = "sel_".TOOL_GOOGLEBOOKS_FIELDS_TO[$googleKey];
+                       $optionString = str_replace($_k,'selected="selected"',$optionString);
+               }
+       }
+
+       return $optionString;
+}
index a6f50fbbf95bf73773742b14e06e667450be3fc4..d11019e72b993070243285cfd148ded81386e319 100644 (file)
@@ -2,7 +2,7 @@
 /**
  * Bibliotheca
  *
- * Copyright 2018-2021 Johannes Keßler
+ * Copyright 2018-2023 Johannes Keßler
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ $Brainz = new Musicbrainz(array(
        'browserAgent' => TOOL_BRAINZ_BROWSER_AGENT,
        'browserLang' => TOOL_BRAINZ_BROWSER_ACCEPT_LANG,
        'browserAccept' => TOOL_BRAINZ_BROWSER_ACCEPT,
-       'debug' => true
+       'debug' => false
 ));
 
 $TemplateData['releases'] = array();
@@ -165,6 +165,11 @@ if(isset($_POST['submitFormSave'])) {
                        $TemplateData['message']['content'] = "Data could not be saved. See logs for more.";
                        $TemplateData['message']['status'] = "error";
                }
+
+               // remove tmp file
+               if(isset($_f) && is_file($_f) && file_exists($_f)) {
+                       unlink($_f);
+               }
        }
 }