{{ . }}
diff --git a/internal/dis/component/control/static/templates/_base.html b/internal/dis/component/control/static/templates/_base.html
index 4faa834..b1c40c1 100644
--- a/internal/dis/component/control/static/templates/_base.html
+++ b/internal/dis/component/control/static/templates/_base.html
@@ -2,6 +2,7 @@
+
{{ block "block" . }}Distillery Control Page{{ end }}
{{ block "styles" . }}styles{{ end }}
diff --git a/internal/phpx/serialize.go b/internal/phpx/serialize.go
new file mode 100644
index 0000000..958fc7f
--- /dev/null
+++ b/internal/phpx/serialize.go
@@ -0,0 +1,49 @@
+package phpx
+
+import "encoding/json"
+
+// BooleanIsh represents a boolean php value.
+//
+// The value can be serialized to and from php and will behave accordingly.
+//
+// The value will always be Marshaled as "true" or "false".
+//
+// When Unmarshaled, it behaves as described on https://www.php.net/manual/en/language.types.boolean.php#language.types.boolean.casting.
+type BooleanIsh bool
+
+func (bi BooleanIsh) MarshalJSON() ([]byte, error) {
+ if bi {
+ return []byte("true"), nil
+ }
+ return []byte("false"), nil
+}
+func (bi *BooleanIsh) UnmarshalJSON(data []byte) (err error) {
+ // unmarshal into a generic value
+ var value any
+ err = json.Unmarshal(data, &value)
+ if err != nil {
+ return err
+ }
+
+ // check if it is false ish
+ var isFalseIsh bool
+ switch d := value.(type) {
+ case bool:
+ isFalseIsh = !d
+ case int:
+ isFalseIsh = d == 0
+ case float64:
+ isFalseIsh = d == 0
+ case string:
+ isFalseIsh = d == "" || d == "0"
+ case []any:
+ isFalseIsh = len(d) == 0
+ case map[string]any:
+ isFalseIsh = len(d) == 0
+ case nil:
+ isFalseIsh = true
+ }
+ *bi = BooleanIsh(!isFalseIsh)
+
+ return nil
+}
diff --git a/internal/wisski/ingredient/barrel/barrel/scripts/user_shell.sh b/internal/wisski/ingredient/barrel/barrel/scripts/user_shell.sh
index 10a738c..9156c8f 100755
--- a/internal/wisski/ingredient/barrel/barrel/scripts/user_shell.sh
+++ b/internal/wisski/ingredient/barrel/barrel/scripts/user_shell.sh
@@ -1,12 +1,15 @@
#!/bin/bash
set -e
-# This script is used to start a user shell inside the docker container.
+# if the user is not www-data, re-invoke self as www-data
+if [ "$USER" != "www-data" ]; then
+ sudo -u www-data /bin/bash /user_shell.sh "$@"
+ exit $?
+fi
+
+# Now start a shell in the proper path
cd "/var/www/data/project"
export "PATH=/var/www/data/project/vendor/bin:$PATH"
-if [ "$USER" = "www-data" ]; then
- /bin/bash "$@"
-else
- sudo -u www-data /bin/bash "$@"
-fi;
\ No newline at end of file
+# Re-invoke the actual command
+/bin/bash "$@"
\ No newline at end of file
diff --git a/internal/wisski/ingredient/barrel/barrel/ssh/keys.sh b/internal/wisski/ingredient/barrel/barrel/wisskiutils/ssh/keys.sh
similarity index 100%
rename from internal/wisski/ingredient/barrel/barrel/ssh/keys.sh
rename to internal/wisski/ingredient/barrel/barrel/wisskiutils/ssh/keys.sh
diff --git a/internal/wisski/ingredient/barrel/barrel/ssh/sshd_config b/internal/wisski/ingredient/barrel/barrel/wisskiutils/ssh/sshd_config
similarity index 100%
rename from internal/wisski/ingredient/barrel/barrel/ssh/sshd_config
rename to internal/wisski/ingredient/barrel/barrel/wisskiutils/ssh/sshd_config
diff --git a/internal/wisski/ingredient/barrel/barrel/ssh/start.sh b/internal/wisski/ingredient/barrel/barrel/wisskiutils/ssh/start.sh
similarity index 100%
rename from internal/wisski/ingredient/barrel/barrel/ssh/start.sh
rename to internal/wisski/ingredient/barrel/barrel/wisskiutils/ssh/start.sh
diff --git a/internal/wisski/ingredient/fetcher.go b/internal/wisski/ingredient/fetcher.go
index 18d0440..d371fa1 100644
--- a/internal/wisski/ingredient/fetcher.go
+++ b/internal/wisski/ingredient/fetcher.go
@@ -38,6 +38,9 @@ type Information struct {
LastUpdate time.Time
LastCron time.Time
+ // Statistics of the wisski (TODO: fix me)
+ Statistics Statistics
+
// List of backups made
Snapshots []models.Export
@@ -49,3 +52,39 @@ type Information struct {
Prefixes []string // list of prefixes
Pathbuilders map[string]string // all the pathbuilders
}
+
+type Statistics struct {
+ Activity struct {
+ MostVisited string `json:"mostVisited"`
+ PageVisits []struct {
+ URL string `json:"url"`
+ Visits int `json:"visits"`
+ } `json:"pageVisits"`
+ TotalEditsLastWeek int `json:"totalEditsLastWeek"`
+ } `json:"activity"`
+ Bundles struct {
+ Bundles []struct {
+ Label string `json:"label"`
+ MachineName string `json:"machineName"`
+
+ Count int `json:"entities"`
+
+ LastEdit int `json:"lastEdit"`
+
+ MainBundle phpx.BooleanIsh `json:"mainBundle"`
+ } `json:"bundleStatistics"`
+ TotalBundles int `json:"totalBundles"`
+ TotalMainBundles int `json:"totalMainBundles"`
+ } `json:"bundles"`
+ Triplestore struct {
+ Graphs []struct {
+ URI string `json:"uri"`
+ Count int `json:"triples"`
+ } `json:"graphStatistics"`
+ Total int `json:"totalTriples"`
+ } `json:"triplestore"`
+ Users struct {
+ LastLogin string `json:"lastLogin"`
+ TotalUsers int `json:"totalUsers"`
+ } `json:"users"`
+}
diff --git a/internal/wisski/ingredient/php/extras/stats.go b/internal/wisski/ingredient/php/extras/stats.go
new file mode 100644
index 0000000..047ac4e
--- /dev/null
+++ b/internal/wisski/ingredient/php/extras/stats.go
@@ -0,0 +1,37 @@
+package extras
+
+import (
+ _ "embed"
+ "log"
+
+ "github.com/FAU-CDI/wisski-distillery/internal/phpx"
+ "github.com/FAU-CDI/wisski-distillery/internal/wisski/ingredient"
+ "github.com/FAU-CDI/wisski-distillery/internal/wisski/ingredient/php"
+)
+
+type Stats struct {
+ ingredient.Base
+
+ PHP *php.PHP
+}
+
+//go:embed stats.php
+var statsPHP string
+
+// Get fetches all statistics from the server
+func (stats *Stats) Get(server *phpx.Server) (data ingredient.Statistics, err error) {
+ err = stats.PHP.ExecScript(server, &data, statsPHP, "export_statistics")
+ if err != nil {
+ log.Println(err)
+ }
+ return
+}
+
+func (stats *Stats) Fetch(flags ingredient.FetchFlags, info *ingredient.Information) (err error) {
+ if flags.Quick {
+ return
+ }
+
+ info.Statistics, _ = stats.Get(flags.Server)
+ return
+}
diff --git a/internal/wisski/ingredient/php/extras/stats.php b/internal/wisski/ingredient/php/extras/stats.php
new file mode 100644
index 0000000..69d7b3d
--- /dev/null
+++ b/internal/wisski/ingredient/php/extras/stats.php
@@ -0,0 +1,8 @@
+update();
+}
diff --git a/internal/wisski/wisski.go b/internal/wisski/wisski.go
index af39a37..65a06e4 100644
--- a/internal/wisski/wisski.go
+++ b/internal/wisski/wisski.go
@@ -99,6 +99,7 @@ func (wisski *WissKI) allIngredients() []initFunc {
auto[*extras.Prefixes],
auto[*extras.Settings],
auto[*extras.Pathbuilder],
+ auto[*extras.Stats],
// info
manual(func(info *info.Info) {
|