]> 91.132.146.200 Git - scientia.git/commitdiff
edit by id. Work in progress
authorBanana <mail@bananas-playground.net>
Sun, 4 Aug 2024 08:54:25 +0000 (10:54 +0200)
committerBanana <mail@bananas-playground.net>
Sun, 4 Aug 2024 08:54:25 +0000 (10:54 +0200)
Signed-off-by: Banana <mail@bananas-playground.net>
client/go-cli/scientia/cmd/edit.go
client/go-cli/scientia/cmd/edit_list.go [deleted file]
client/go-cli/scientia/cmd/list.go [new file with mode: 0644]
client/go-cli/scientia/cmd/root.go
documentation/scructure/structure-edit.d2
webroot/get.php
webroot/lib/entry.class.php
webroot/view/list/list.php

index 872272e490d80540ae86310945a95a03cba5ecab..dadc1c02dabed64ae9a2c93e5a15ae3a55a99ac5 100644 (file)
@@ -1,8 +1,11 @@
 package cmd
 
 import (
+       "fmt"
        "github.com/spf13/cobra"
        "os"
+       "os/exec"
+       Helper "scientia/lib"
 )
 
 /**
@@ -22,14 +25,51 @@ import (
  */
 
 var editCmd = &cobra.Command {
-       Use: "edit",
-       Short: "Modify an entry",
-       Long: "Edit an existing entry.",
+       Use: "edit ID",
+       Short: "Modify an entry by its ID",
+       Long: "Edit an existing entry. Get the ID from the list command.",
        Run: func(cmd *cobra.Command, args []string) {
-               if len(args) == 0 {
+               var entryId string
+
+               if len(args) == 1 {
+                       entryId = args[0]
+               } else {
                        cmd.Help()
                        os.Exit(0)
                }
+
+               response := getEndpointRequest("?p=entry&id=" + entryId);
+
+               body := response.Data[0].Body
+               ident := response.Data[0].Ident
+
+               fh, err := os.CreateTemp("", ident)
+               Helper.ErrorCheck(err, "Can not create tmp file for editing.")
+               _, err = fmt.Fprintf(fh, body)
+
+               // default editor
+               var editor = "vim"
+
+               if e := os.Getenv("VISUAL"); e != "" {
+                       editor = e
+               } else if e := os.Getenv("EDITOR"); e != "" {
+                       editor = e
+               }
+
+               editCmd := exec.Command(editor, fh.Name())
+               editCmd.Stdin = os.Stdin
+               editCmd.Stdout = os.Stdout
+               editCmd.Stderr = os.Stderr
+               err = editCmd.Start()
+               Helper.ErrorCheck(err, "Can not open tmp file")
+
+               fmt.Println("Waiting for command to finish...")
+               err = editCmd.Wait()
+               Helper.ErrorCheck(err, "Command finished with error")
+               fmt.Println("Done.")
+
+               defer os.Remove(fh.Name())
+
        },
 }
 
diff --git a/client/go-cli/scientia/cmd/edit_list.go b/client/go-cli/scientia/cmd/edit_list.go
deleted file mode 100644 (file)
index e7adfe2..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-package cmd
-
-import (
-       "fmt"
-       "github.com/spf13/cobra"
-)
-
-/**
- * scientia
- *
- * Copyright 2023 - 2024 Johannes Keßler
- *
- * https://www.bananas-playground.net/projekt/scientia/
- *
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
- *
- * You should have received a copy of the
- * COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
- * along with this program.  If not, see http://www.sun.com/cddl/cddl.html
- */
-
-
-// Subcommand of edit
-// to list all available entries
-
-var editListCmd = &cobra.Command {
-       Use:   "list",
-       Short: "List all available entries",
-       Long:  "List all available entries",
-       Run: func(cmd *cobra.Command, args []string) {
-               listEntries()
-       },
-}
-
-func init() {
-       editCmd.AddCommand(editListCmd)
-}
-
-func listEntries() {
-       if FlagVerbose {
-               fmt.Println("Starting to request entries")
-       }
-}
diff --git a/client/go-cli/scientia/cmd/list.go b/client/go-cli/scientia/cmd/list.go
new file mode 100644 (file)
index 0000000..680e3ee
--- /dev/null
@@ -0,0 +1,95 @@
+package cmd
+
+import (
+       "encoding/json"
+       "fmt"
+       "github.com/spf13/cobra"
+       "io"
+       "net/http"
+       Helper "scientia/lib"
+       "strings"
+)
+
+/**
+ * scientia
+ *
+ * Copyright 2023 - 2024 Johannes Keßler
+ *
+ * https://www.bananas-playground.net/projekt/scientia/
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
+ *
+ * You should have received a copy of the
+ * COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+ * along with this program.  If not, see http://www.sun.com/cddl/cddl.html
+ */
+
+
+// to list all available entries
+
+var listCmd = &cobra.Command {
+       Use:   "list",
+       Short: "List all available entries",
+       Long:  "List all available entries with its ID, date and content preview.",
+       Run: func(cmd *cobra.Command, args []string) {
+               listEntries()
+       },
+}
+
+func init() {
+       rootCmd.AddCommand(listCmd)
+}
+
+func listEntries() {
+       response := getEndpointRequest("")
+
+       for _, entry := range response.Data {
+               leftOfDelimiter, _, _ := strings.Cut(entry.Body, "\n")
+               fmt.Println(entry.Ident, entry.Date, leftOfDelimiter)
+       }
+}
+
+
+func getEndpointRequest(params string) GetResponse {
+       if FlagVerbose {
+               fmt.Println("Starting to request get endpoint")
+       }
+
+       req, err := http.NewRequest(http.MethodGet, ScientiaConfig.Endpoint.Get + params, nil)
+       Helper.ErrorCheck(err, "Can not create http request")
+       // We need to set the content type from the writer, it includes necessary boundary as well
+       req.Header.Set("User-Agent", "scientiaAgent/1.0")
+       req.Header.Set("X-ASL", ScientiaConfig.Endpoint.Secret)
+
+       // Do the request
+       client := &http.Client{}
+       response, err := client.Do(req)
+       Helper.ErrorCheck(err, "GET request failed")
+
+       responseBody, err := io.ReadAll(response.Body)
+       Helper.ErrorCheck(err, "Can not read response body")
+
+       if FlagVerbose {
+               fmt.Println("Request done")
+       }
+       if FlagDebug {
+               fmt.Printf("DEBUG Response status code: %d\n", response.StatusCode)
+               fmt.Printf("DEBUG Response headers: %#v\n", response.Header)
+               fmt.Println("DEBUG Response body:\n", string(responseBody))
+       }
+
+       returnResponse := GetResponse{}
+       if response.StatusCode != 200 {
+               returnResponse = GetResponse {
+                       Message: "Status not as expected.",
+                       Status: response.StatusCode,
+                       Data: []GetResponseEntry{}}
+       } else {
+               err := json.Unmarshal([]byte(responseBody), &returnResponse)
+               Helper.ErrorCheck(err, "Can not parse return json")
+       }
+
+       return returnResponse
+}
index 93b37ab521f6262684e6de4005caed331b0e5cc2..d29855d6acad5990fdb6df70827e7b1bc38dc0b2 100644 (file)
@@ -6,7 +6,6 @@ import (
        "github.com/adrg/xdg"
        "github.com/spf13/cobra"
        "gopkg.in/yaml.v3"
-       "log"
        "os"
        Helper "scientia/lib"
 )
@@ -26,6 +25,19 @@ type ConfigStruct struct {
        } `yaml:"endpoint"`
 }
 
+// GetResponse struct for the get.php request
+type GetResponse struct {
+       Data []GetResponseEntry `json:"data"`
+       Status int `json:"status"`
+       Message string `json:"message"`
+}
+// GetResponseEntry struct is the entry itself
+type GetResponseEntry struct {
+       Ident string `json:"ident"`
+       Date string `json:"date"`
+       Body string `json:"body"`
+}
+
 // The ScientiaConfig used globally
 var ScientiaConfig ConfigStruct
 
@@ -84,7 +96,7 @@ func loadConfig() {
        Helper.ErrorCheck(err, "Can not decode config file")
 
        if ScientiaConfig.Endpoint.Add == "" || ScientiaConfig.Endpoint.Get == "" || ScientiaConfig.Endpoint.Secret == "" {
-               log.Fatal("Empty or outdated config?")
+               fmt.Println("WARNING Empty or outdated config?")
        }
 
        if FlagDebug {
index a23f2ccb4ec27ee3989a2c01bd2ba22476b3c401..c566afa0a0577b2d5080a0c650aa01c6e9f8d3f7 100644 (file)
@@ -1,10 +1,7 @@
-edit_list: list
 edit_id: id
 
 server: server
 server.shape: cloud
 
-edit -> edit_list
 edit -> edit_id
-edit_list <-> server
 edit_id <-> server
index c9ae3a31a4c19a4ae6f6f6e31149087808223c4f..aaa0cd810ce8df5ff4d6607b2d72b6919617d7ab 100644 (file)
@@ -50,3 +50,61 @@ date_default_timezone_set(TIMEZONE);
 
 # required libs
 require_once('lib/summoner.class.php');
+
+# validate key
+if(!isset($_SERVER['HTTP_X_ASL']) || empty($_SERVER['HTTP_X_ASL']) || !isset(UPLOAD_SECRET[$_SERVER['HTTP_X_ASL']])) {
+    header('X-PROVIDED-BY: scientia');
+    http_response_code(400);
+    exit();
+}
+
+
+$_requestMode = "list";
+if(isset($_GET['p']) && !empty($_GET['p'])) {
+    $_requestMode = trim($_GET['p']);
+    $_requestMode = Summoner::validate($_requestMode,'nospace') ? $_requestMode : "list";
+}
+$_id = '';
+if(isset($_GET['id']) && Summoner::validate($_GET['id'], 'shortlink',4)) {
+    $_id = trim($_GET['id']);
+    $_view = 'entry';
+}
+
+# default response
+$contentType = 'Content-Type: application/json; charset=utf-8';
+$httpResponseCode = 200;
+$contentBody = array (
+    'data' => array(),
+    'message' => '',
+    'status' => $httpResponseCode
+);
+
+## DB connection
+$DB = new mysqli(DB_HOST, DB_USERNAME,DB_PASSWORD, DB_NAME);
+if ($DB->connect_errno) exit('Can not connect to MySQL Server');
+$DB->set_charset("utf8mb4");
+$DB->query("SET collation_connection = 'utf8mb4_bin'");
+$driver = new mysqli_driver();
+$driver->report_mode = MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT;
+
+require_once 'lib/entry.class.php';
+$Entry = new Entry($DB);
+
+switch($_requestMode) {
+    case "entry":
+        if(!empty($_id)) {
+            $contentBody['data'][] = $Entry->loadById($_id);
+        }
+    break;
+
+    case "list":
+    default:
+        $contentBody['data'] = $Entry->list();
+}
+
+## return
+header('X-PROVIDED-BY: scientia');
+header($contentType);
+http_response_code($httpResponseCode);
+echo json_encode($contentBody);
+$DB->close();
index bbf236dc5af0e2d50a2cc394f0b38cce05b68b6c..5c495316b6637e518347a5864ef120471b7b871f 100644 (file)
@@ -100,6 +100,35 @@ class Entry {
         return $ret;
     }
 
+    /**
+     * Load an entry by given $id.
+     * Used by get api
+     *
+     * @param string $id Id of the entry
+     * @return array
+     */
+    public function loadById(string $id): array {
+        $ret = array();
+
+        if(!empty($id)) {
+            $queryStr = "SELECT `ident`,`date`,`body`
+                            FROM `".DB_PREFIX."_entry`
+                            WHERE `ident` = '".$this->_DB->real_escape_string($id)."'";
+            if(QUERY_DEBUG) error_log("[QUERY] ".__METHOD__." query: ".var_export($queryStr,true));
+            try {
+                $query = $this->_DB->query($queryStr);
+                if($query !== false && $query->num_rows > 0) {
+                    $ret = $query->fetch_assoc();
+                }
+            }
+            catch(Exception $e) {
+                error_log("[ERROR] ".__METHOD__." catch: ".$e->getMessage());
+            }
+        }
+
+        return $ret;
+    }
+
     /**
      * Update an entry by given $id and $data
      *
@@ -154,6 +183,42 @@ class Entry {
         return $ret;
     }
 
+    /**
+     * Get all entries which match the specified options
+     * Body is trimmed to the first 100 chars
+     *
+     * @param String $searchTerm
+     * @param String $intervalStart
+     * @param String $intervalEnd
+     * @param int $limit
+     * @return array
+     */
+    public function list(string $searchTerm='', string $intervalStart='', string $intervalEnd='', int $limit=100): array {
+        $ret = array();
+
+        $queryStr = "SELECT e.ident, e.date, SUBSTRING(e.body,1,100) AS body 
+                    FROM `".DB_PREFIX."_entry` AS e";
+        if(!empty($intervalStart) && !empty($intervalEnd)) {
+            $queryStr .= " WHERE e.date >= '".$intervalStart."' AND e.date <= '".$intervalEnd."'";
+        }
+        if(!empty($searchTerm)) {
+            $queryStr .= " AND MATCH(e.words) AGAINST('".$this->_DB->real_escape_string($searchTerm)."' IN BOOLEAN MODE)";
+        }
+        $queryStr .= " ORDER BY `created` DESC";
+        $queryStr .= " LIMIT $limit";
+
+        if(QUERY_DEBUG) error_log("[QUERY] ".__METHOD__." query: ".var_export($queryStr,true));
+        try {
+            $query = $this->_DB->query($queryStr);
+            $ret = $query->fetch_all(MYSQLI_ASSOC);
+        }
+        catch(Exception $e) {
+            error_log("[ERROR] ".__METHOD__." catch: ".$e->getMessage());
+        }
+
+        return $ret;
+    }
+
     /**
      * Create unique words from the given data
      *
index 23a03be8ba300c46e5adf0e8643ddfad29108b69..705f8a39428b21148a7fc3dc9f576e93a20dd025 100644 (file)
@@ -17,8 +17,8 @@
 
 $TemplateData['entries'] = array();
 
-$queryStr = "SELECT e.ident, e.date, e.words, SUBSTRING(e.body,1,100) AS body FROM `".DB_PREFIX."_entry` AS e";
-$queryLimit = " LIMIT 100";
+require_once 'lib/entry.class.php';
+$Entry = new Entry($DB);
 
 $searchTerm = '';
 if(isset($_POST['submitForm']) && isset($_POST['searchInput'])) {
@@ -32,10 +32,9 @@ if(isset($_POST['submitForm']) && isset($_POST['searchInput'])) {
 // the single date infos come from index.php
 $_groupByFormat = $_year;
 $breadcrumb = array('Y');
+$_intervalStart = '';
+$_intervalEnd = '';
 if(!empty($_requestDateProvided)) {
-    $_intervalStart = '';
-    $_intervalEnd = '';
-
     if($_requestDateProvided === 'Y-m-d') {
         $queryLimit = "";
         $_groupByFormat = $_year.'-'.$_month.'-'.$_day;
@@ -56,39 +55,18 @@ if(!empty($_requestDateProvided)) {
         $_intervalStart = $_groupByFormat.'-01-01';
         $_intervalEnd = $_groupByFormat.'-12-31';
     }
-
-    if(!empty($_intervalStart) && !empty($_intervalEnd)) {
-        $queryStr .= " WHERE e.date >= '".$_intervalStart."' AND e.date <= '".$_intervalEnd."'";
-        if(!empty($searchTerm)) {
-            $queryStr .= " AND MATCH(e.words) AGAINST('".$DB->real_escape_string($searchTerm)."' IN BOOLEAN MODE)";
-        }
-    }
 } else {
     $_requestDateProvided = 'Y';
-    if(!empty($searchTerm)) {
-        $queryStr .= " WHERE MATCH(e.words) AGAINST('".$DB->real_escape_string($searchTerm)."' IN BOOLEAN MODE)";
-    }
 }
 
-$queryStr .= " ORDER BY `created` DESC";
-$queryStr .= $queryLimit;
-if(QUERY_DEBUG) error_log("[QUERY] query: ".var_export($queryStr,true));
-
-try {
-    $query = $DB->query($queryStr);
-    if($query !== false && $query->num_rows > 0) {
-        while(($result = $query->fetch_assoc()) != false) {
-            $_d = new DateTime($result['date']);
-            $_breadcrumb = array();
-            foreach($breadcrumb as $_b) {
-                $_breadcrumb[] = $_d->format($_b);
-            }
-            $TemplateData['entries'][$_d->format($_requestDateProvided)]['breadcrumb'] = $_breadcrumb;
-            $TemplateData['entries'][$_d->format($_requestDateProvided)]['e'][$result['ident']] = $result;
-            $TemplateData['entries'][$_d->format($_requestDateProvided)]['e'][$result['ident']]['link'] = str_replace('-','/',$result['date']).'/'.$result['ident'];
-        }
+$entries = $Entry->list($searchTerm, $_intervalStart, $_intervalEnd);
+foreach($entries as $k=>$entry) {
+    $_d = new DateTime($entry['date']);
+    $_breadcrumb = array();
+    foreach($breadcrumb as $_b) {
+        $_breadcrumb[] = $_d->format($_b);
     }
-}
-catch(Exception $e) {
-    error_log("[ERROR] catch: ".$e->getMessage());
+    $TemplateData['entries'][$_d->format($_requestDateProvided)]['breadcrumb'] = $_breadcrumb;
+    $TemplateData['entries'][$_d->format($_requestDateProvided)]['e'][$entry['ident']] = $entry;
+    $TemplateData['entries'][$_d->format($_requestDateProvided)]['e'][$entry['ident']]['link'] = str_replace('-','/',$entry['date']).'/'.$entry['ident'];
 }