WIP refactoring newsLib - not pretty, but news ar on the testpage

This commit is contained in:
marko
2025-05-11 18:57:34 +02:00
parent 003310623f
commit 107bdf4fdb
6 changed files with 402 additions and 247 deletions

View File

@@ -51,6 +51,7 @@ ampTest: $(ampFiles)
INSTALL_DEPENDENCIES:
npm install csso-cli
npm install --save-dev --save-exact prettier
npm install --save-dev prettier @prettier/plugin-php
build/css/cwsvJudo.css: $(cssFiles)
cat $^ | $(CSSO) -o $@

View File

@@ -0,0 +1,22 @@
<?php
require_once "config.php";
require_once "phpLibs/cwsvJudo/dbConnector.php";
require_once "phpLibs/cwsvJudo/news.php";
$config = json_decode(
json: file_get_contents(filename: $home . "/.local/config.json"),
associative: true
);
$secrets = json_decode(
json: file_get_contents(filename: $home . "/.local/secrets.json"),
associative: true
);
$dbHandle = new \CwsvJudo\Db\Connector(
hostname: $config["cwsvJudo"]["db"]["host"],
dbName: $config["cwsvJudo"]["db"]["name"],
user: $config["cwsvJudo"]["db"]["user"],
password: $secrets["cwsvJudo"]["db"][$config["cwsvJudo"]["db"]["user"]]
);

View File

@@ -1,7 +1,8 @@
<!DOCTYPE html>
<?php
require_once "bootstrap.php";
$directory_paths=[
$directory_paths = [
"wallpapers" => "/ressourcen/graphiken/wallpapers",
];
@@ -9,32 +10,40 @@ $mainNav = [
[
"url" => "training",
"caption" => "Training",
"title" => "Trainingszeiten und -orte der Judoka des Chemnitzer WSV"
]
"title" => "Trainingszeiten und -orte der Judoka des Chemnitzer WSV",
],
];
$sections = [
"Lorem ipsum",
\CwsvJudo\News\newsBoard(
dbHandle: $dbHandle,
options: [
"limit" => 6,
// "dbCharset" => "ISO-8859-1",
"dbCharset" => "UTF-8",
// "outCharset" => "ISO-8859-1",
"outCharset" => "UTF-8",
]
),
"dolor sit amet",
"consectetur adipiscing elit"
"consectetur adipiscing elit",
];
$wallpapers = [
[
"src" => $directory_paths['wallpapers']. "/osae-komi.svg",
"data-src" => $directory_paths['wallpapers']. "/osae-komi.jpg"
"src" => $directory_paths["wallpapers"] . "/osae-komi.svg",
"data-src" => $directory_paths["wallpapers"] . "/osae-komi.jpg",
],
[
"src" => $directory_paths['wallpapers']. "/nage.svg",
"data-src" => $directory_paths['wallpapers']. "/nage.jpg"
"src" => $directory_paths["wallpapers"] . "/nage.svg",
"data-src" => $directory_paths["wallpapers"] . "/nage.jpg",
],
[
"src" => $directory_paths['wallpapers']. "/kata.svg",
"data-src" => $directory_paths['wallpapers']. "/kata.jpg"
"src" => $directory_paths["wallpapers"] . "/kata.svg",
"data-src" => $directory_paths["wallpapers"] . "/kata.jpg",
],
];
// helper functions
// -html output
@@ -43,40 +52,41 @@ $wallpapers = [
* @param mixed $mainNav
* @return void
*/
function mainNavTargets($mainNav){
echo('<ul id="nav-mobile" class="right">');
foreach($mainNav as $nav){
echo('<li>');
echo('<a');
echo(' href="' . $nav['url']. '"');
echo(' title="' . $nav['caption']. '"');
echo('>');
echo('<span>'.$nav['caption'].'</span>');
echo('</a>');
echo('</li>');
function mainNavTargets($mainNav)
{
echo '<ul id="nav-mobile" class="right">';
foreach ($mainNav as $nav) {
echo "<li>";
echo "<a";
echo ' href="' . $nav["url"] . '"';
echo ' title="' . $nav["caption"] . '"';
echo ">";
echo "<span>" . $nav["caption"] . "</span>";
echo "</a>";
echo "</li>";
}
echo('</ul>');
echo "</ul>";
}
function main($sections, $wallpapers){
foreach($sections as $idx => $section){
echo(
'<div class="parallax-container">'
.'<div class="parallax">'
.'<img'
. ' class="lazyload" '
. ' src="'.$wallpapers[$idx]['src'].'" '
. ' data-src="'.$wallpapers[$idx]['data-src'].'" '
.'>'
.'</div>'
.'</div>'
);
echo(
'<div class="section">'.$section.'</div>'
);
function main($sections, $wallpapers)
{
foreach ($sections as $idx => $section) {
echo '<div class="parallax-container">' .
'<div class="parallax">' .
"<img" .
' class="lazyload" ' .
' src="' .
$wallpapers[$idx]["src"] .
'" ' .
' data-src="' .
$wallpapers[$idx]["data-src"] .
'" ' .
">" .
"</div>" .
"</div>";
echo '<div class="section">' . $section . "</div>";
}
}
?>
<html>
@@ -101,7 +111,7 @@ function main($sections, $wallpapers){
<a href="/" class="brand-logo">
<span>cwsvJudo</span>
</a>
<?php mainNavTargets($mainNav);?>
<?php mainNavTargets($mainNav); ?>
</div>
<!-- <div class="nav-content">
$if(subNav)$
@@ -130,7 +140,7 @@ function main($sections, $wallpapers){
</header>
<main>
<?php main($sections, $wallpapers);?>
<?php main($sections, $wallpapers); ?>
</main>
<!--JavaScript at end of body for optimized loading-->
@@ -147,8 +157,16 @@ function main($sections, $wallpapers){
const instances = M.Parallax.init(elems, {
// specify options here
});
})
// const elems = document.querySelectorAll('.carousel');
// const instances = M.Carousel.init(elems, {
// // fullWidth: true,
// // indicators: true,
// // noWrap: true,
// // numVisible: 6,
// });
});
</script>
</body>
</html>
</html>

View File

@@ -21,19 +21,15 @@ $dbHandle = new \CwsvJudo\Db\Connector(
password: $secrets['cwsvJudo']['db'][$config['cwsvJudo']['db']['user']]
);
// try {
// $conn = new PDO(
// dsn: join(separator: ";",array: [
// "mysql:host=".$config['cwsvJudo']['db']['host'],
// "port=3306",
// "dbname=".$config['cwsvJudo']['db']['name']
// ]),
// username: $config['cwsvJudo']['db']['user'],
// password: $secrets['cwsvJudo']['db'][$config['cwsvJudo']['db']['user']]
// );
// // set the PDO error mode to exception
// $conn->setAttribute(attribute: PDO::ATTR_ERRMODE, value: PDO::ERRMODE_EXCEPTION);
// echo "Connected successfully";
// } catch(PDOException $e) {
// echo "Connection failed: " . $e->getMessage();
// }
var_dump(
\CwsvJudo\News\newsBoard(
dbHandle: $dbHandle,
options: [
'limit' => 6,
// "dbCharset" => "ISO-8859-1",
"dbCharset" => "UTF-8",
// "outCharset" => "ISO-8859-1",
"outCharset" => "UTF-8",
],
)
);

View File

@@ -12,9 +12,8 @@ class Connector
string $dbName,
string $user,
string $password,
int $port=3306,
)
{
int $port = 3306
) {
$this->db = self::connectToPdo(
hostname: $hostname,
port: $port,
@@ -23,187 +22,192 @@ class Connector
password: $password
);
}
// public
// - variables (none)
// - functions
public function connect(
// public
// - variables (none)
// - functions
public function connect(
string $hostname,
string $dbName,
string $user,
string $password,
int $port = 3306,
): bool
{
return self::setDbConnection(
int $port = 3306
): bool {
return self::setDbConnection(
dbConnection: self::connectToPdo(
hostname: $hostname,
dbName: $dbName,
user: $user,
password: $password,
password: $password
)
);
}
// private
// - variables
}
// private
// - variables
/**
* pointer to the database connection
* @var
*
* Handle to interact with the database
*/
private ?\PDO $db = null;
// - functions
/** @todo Docu
* Establish a connection to the database
* @param mixed $hostname
* @param mixed $dbName
* @param mixed $user
* @param mixed $password
* @return \PDO|null
*/
private ?\PDO $db = null;
// - functions
/** @todo Docu
* Establish a connection to the database
* @param mixed $hostname
* @param mixed $dbName
* @param mixed $user
* @param mixed $password
* @return \PDO|null
*/
private static function connectToPdo(
string $hostname,
string $dbName,
string $user,
string $password,
int $port = 3306,
): \PDO|null
{
$dbConnection = null;
try {
$dbConnection = new \PDO(
dsn: 'mysql:'.join(
';',
[
'host=' . $hostname,
'port=' . strval($port),
'dbname=' . $dbName
]
),
username: $user,
password: $password
);
} catch(\PDOException $dbError) {
echo('Error whilst getting a dbConnection!: ' . $dbError->getMessage());
}
return $dbConnection;
}
int $port = 3306
): \PDO|null {
$dbConnection = null;
try {
$dbConnection = new \PDO(
dsn: "mysql:" .
join(";", [
"host=" . $hostname,
"port=" . strval($port),
"dbname=" . $dbName,
]),
username: $user,
password: $password
);
} catch (\PDOException $dbError) {
echo "Error whilst getting a dbConnection!: " .
$dbError->getMessage();
}
return $dbConnection;
}
public function getDbConnection() : \PDO|null
{
return $this->db;
}
public function getDbConnection(): \PDO|null
{
return $this->db;
}
/// perform a \PDO-query
///
/// @param $aQueryString
/// @param $aBindArray e.g. array(
/// ':userId' => array('value'=>$anUserId, 'data_type'=>\PDO::PARAM_INT),
/// ':attributeId'=> array('value'=>$anAttributeId, 'data_type'=>\PDO::PARAM_INT) )
/// @param $someOption
public static function query($aQueryString, $aBindArray = [], $someOptions = [])
{
// var_dump($aQueryString, $aBindArray);
// Standardbelegungen
if (empty($someOptions['dbCharset'])) {
$someOptions['dbCharset'] = 'ISO-8859-1';
}
if (empty($someOptions['outCharset'])) {
$someOptions['outCharset'] = 'UTF-8';
}
if (empty($someOptions['dontFetch'])) {
$someOptions['dontFetch'] = false;
}
/// perform a \PDO-query
///
/// @param $aQueryString
/// @param $aBindArray e.g. array(
/// ':userId' => array('value'=>$anUserId, 'data_type'=>\PDO::PARAM_INT),
/// ':attributeId'=> array('value'=>$anAttributeId, 'data_type'=>\PDO::PARAM_INT) )
/// @param $options
public function query(
string $aQueryString,
array $aBindArray = [],
array $options = []
) {
// Standardbelegungen
if (empty($options["dbCharset"])) {
$options["dbCharset"] = "ISO-8859-1";
}
if (empty($options["outCharset"])) {
$options["outCharset"] = "UTF-8";
}
if (empty($options["dontFetch"])) {
$options["dontFetch"] = false;
}
$ignoreErrors = $someOptions['ignoreErrors'] ?? false;
$ignoreErrors = $options["ignoreErrors"] ?? false;
/// @toDo: Bisher wird nur die Rückgabe konvertiert. Eigentlich muss
/// doch auch die Eingabe konvertiert werden. Aber das jetzt
/// umzustellen wird schwer! Die User im Wettkampfplaner sind ja z.B.
/// als UTF8 in latin1(?) gespeichert.
/// @toDo: Die Standardwerte sollten vielleicht aus einer config
/// kommen, nicht hardcoded
/// @toDo: Bisher wird nur die Rückgabe konvertiert. Eigentlich muss
/// doch auch die Eingabe konvertiert werden. Aber das jetzt
/// umzustellen wird schwer! Die User im Wettkampfplaner sind ja z.B.
/// als UTF8 in latin1(?) gespeichert.
/// @toDo: Die Standardwerte sollten vielleicht aus einer config
/// kommen, nicht hardcoded
try {
$PDOStatement = self::$db->prepare($aQueryString);
foreach ($aBindArray as $bindName => $bind) {
if ($bind['data_type'] == \PDO::PARAM_STR) {
$bind['value'] = iconv(
$someOptions['outCharset'],
$someOptions['dbCharset'],
$bind['value']
);
}
$PDOStatement->bindValue(
$bindName,
$bind['value'],
(isset($bind['data_type']) ? $bind['data_type'] : \PDO::PARAM_STR)
);
}
$PDOResult = $PDOStatement->execute();
if (!$ignoreErrors && !$PDOResult) {
echo("Error during dbQuery!\n");
echo("DB-Error:\n");
var_dump(self::$db->errorInfo());
}
if ($someOptions['dontFetch']) {
$ret = null;
} else {
$ret = $PDOStatement->fetchAll(\PDO::FETCH_ASSOC);
}
} catch(\PDOException $db_error) {
print 'Error!: ' . $db_error->getMessage() . '<br/>';
return null;
}
try {
$PDOStatement = $this->getDbConnection()->prepare($aQueryString);
foreach ($aBindArray as $bindName => $bind) {
if ($bind["data_type"] == \PDO::PARAM_STR) {
$bind["value"] = iconv(
$options["outCharset"],
$options["dbCharset"],
$bind["value"]
);
}
$PDOStatement->bindValue(
$bindName,
$bind["value"],
isset($bind["data_type"])
? $bind["data_type"]
: \PDO::PARAM_STR
);
}
$PDOResult = $PDOStatement->execute();
if (!$ignoreErrors && !$PDOResult) {
echo "Error during dbQuery!\n";
echo "DB-Error:\n";
var_dump($this->getDbConnection()->errorInfo());
}
if ($options["dontFetch"]) {
$ret = null;
} else {
$ret = $PDOStatement->fetchAll(\PDO::FETCH_ASSOC);
}
} catch (\PDOException $db_error) {
print "Error!: " . $db_error->getMessage() . "<br/>";
return null;
}
// Zeichensatzkonvertierung
if (is_array($ret)) {
foreach ($ret as &$entry) {
array_walk(
$entry,
function (&$value, $key, $someOptions) {
$value = iconv($someOptions['dbCharset'], $someOptions['outCharset'], $value);
},
$someOptions
);
}
}
return $ret;
}
// Zeichensatzkonvertierung
if (is_array($ret)) {
foreach ($ret as &$entry) {
array_walk(
$entry,
function (&$value, $key, $options) {
$value = iconv(
$options["dbCharset"],
$options["outCharset"],
$value
);
},
$options
);
}
}
return $ret;
}
// @todo docu
public static function getLastInsertId()
{
return self::$db->lastInsertId();
}
// @todo docu
public function getLastInsertId()
{
return $this->getDbConnection()->lastInsertId();
}
// set the dbConnection (just setting, no establishing)
private function setDbConnection($dbConnection): bool
{
$success = false;
if ($dbConnection instanceof \PDO) {
$this->db = $dbConnection;
$success = true;
} else {
$this->db = null;
}
return $success;
}
// set the dbConnection (just setting, no establishing)
private function setDbConnection($dbConnection): bool
{
$success = false;
if ($dbConnection instanceof \PDO) {
self::$db = $dbConnection;
$success = true;
} else {
self::$db = null;
}
return $success;
}
public static function debugEchoQuery($query, $params)
{
foreach ($params as $key => $value) {
switch($value['data_type']) {
case \PDO::PARAM_STR:{
$query = str_replace($key, '\'' . $value['value'] . '\'', $query);
}
default:{
$query = str_replace($key, $value['value'], $query);
}
}
};
echo('query: ' . $query . PHP_EOL);
}
public static function debugEchoQuery($query, $params)
{
foreach ($params as $key => $value) {
switch ($value["data_type"]) {
case \PDO::PARAM_STR:
$query = str_replace(
$key,
'\'' . $value["value"] . '\'',
$query
);
default:
$query = str_replace($key, $value["value"], $query);
}
}
echo "query: " . $query . PHP_EOL;
}
}

View File

@@ -5,59 +5,65 @@ namespace CwsvJudo\News;
use DateTime;
// swap the values of two variables
function swap(mixed &$x, mixed &$y) : void{
$tmp=$x;
$x=$y;
$y=$tmp;
function swap(mixed &$x, mixed &$y): void
{
$tmp = $x;
$x = $y;
$y = $tmp;
}
// input sanitation for integers in a range
function filter_integer_range(mixed $value, ?int $min = null, ?int $max = null) : ?int {
$options = ["options"=>["flags"=> FILTER_NULL_ON_FAILURE]];
function filter_integer_range(
mixed $value,
?int $min = null,
?int $max = null
): ?int {
if (is_null($value)) {
return null;
}
$options = ["options" => ["flags" => FILTER_NULL_ON_FAILURE]];
if (!is_null($min) && !is_null($max)){
if( $min > $max ){
if (!is_null($min) && !is_null($max)) {
if ($min > $max) {
swap($min, $max);
}
}
if(!is_null($min)){
if (!is_null($min)) {
$options["options"]["min_range"] = $min;
}
if(!is_null($max)){
if (!is_null($max)) {
$options["options"]["max_range"] = $max;
}
return filter_var(
$value,
FILTER_VALIDATE_INT,
$options,
);
return filter_var($value, FILTER_VALIDATE_INT, $options);
}
// input sanitation for integers
function filter_integer(mixed $value) : ?int {
function filter_integer(mixed $value): ?int
{
return filter_integer_range($value);
}
// input sanitation for id-s
function filter_id(mixed $value, int $min = 0) : ?int {
function filter_id(mixed $value, int $min = 0): ?int
{
return filter_integer_range($value, $min, null);
}
// input sanitation for URL
function filter_url(mixed $value){
return filter_var(
$value,
FILTER_VALIDATE_URL,
["options" => ["flags" => FILTER_NULL_ON_FAILURE]]
);
function filter_url(mixed $value)
{
return filter_var($value, FILTER_VALIDATE_URL, [
"options" => ["flags" => FILTER_NULL_ON_FAILURE],
]);
}
class PromoImage {
public function __construct(array $data) {
class PromoImage
{
public function __construct(array $data)
{
$this->src = filter_url($data["src"]);
$this->height = filter_integer_range(
value: $data["height"],
@@ -68,16 +74,17 @@ class PromoImage {
$this->data = $data;
}
public function to_json(): string|null{
public function to_json(): string|null
{
$data = json_encode(
value: [
"src" => $this->src,
"width" => $this->width,
"height" => $this->height
"height" => $this->height,
]
);
if($data == false){
if ($data == false) {
return null;
}
@@ -92,10 +99,34 @@ class PromoImage {
}
// a single news entry
class Entry{
class Entry
{
// public
// - functions
function __construct(array $data)
{
$this->id = filter_id($data["nr"]);
$this->date = new \DateTime($data["datum"]);
$this->title = $data["betreff"];
$this->content = $data["nachricht"];
$this->author = $data["autor"];
// $this->promo = new PromoImage(
// json_encode($data["promoImg"]));
}
function as_card(): string
{
return '<div class="col s12 m6 l3"><div class="card">' .
'<div class="card-content">' .
'<span class="card-title">' .
$this->title .
"</span>" .
"<p>" .
$this->content .
"</p>" .
"</div>" .
"</div></div>";
}
// private
// - member variables
private int $id;
@@ -105,3 +136,86 @@ class Entry{
private string $author;
private PromoImage $promo;
}
/// Eine Liste mit News abfragen
///
/// Der Rückgabewert sollte vor Verwendung (und zur Fehlerbeheandlung)
/// auf NULL und/oder leeres Array getestet werden.
/// Der Zeichensatz wird von "ISO-8859-1" auf "UTF-8" gesetzt
///
/// @return Array mit News (die wiederum assoziative arrays sind
function getNews(
\CwsvJudo\Db\Connector $dbHandle,
array $options = [
"dbCharset" => "ISO-8859-1",
"outCharset" => "UTF-8",
"limit" => "1",
]
): array|null {
if (!$dbHandle->getDbConnection()) {
return null;
}
if (empty($options["dbCharset"])) {
$options["dbCharset"] = "ISO-8859-1";
}
if (empty($options["outCharset"])) {
$options["outCharset"] = "UTF-8";
}
$newsId = filter_id($options["newsId"] ?? null);
$limit = filter_id($options["limit"] ?? 1);
$year = filter_id($options["jahr"] ?? null);
$query = "SELECT * FROM nachrichten ";
$bindArray = [
":limit" => ["value" => $limit, "data_type" => \PDO::PARAM_INT],
];
// Falls eine konkrete newsId angegeben wurde, wollen wir ab dieser News haben
if (!is_null($newsId)) {
$query .=
"WHERE nachrichten.datum <= (SELECT nachrichten.datum FROM nachrichten WHERE nachrichten.nr = :newsId ) ORDER BY nachrichten.datum DESC LIMIT :limit OFFSET 0;";
$bindArray[":newsId"] = [
"value" => $newsId,
"data_type" => \PDO::PARAM_INT,
];
}
// Ansonsten die aktuellsten
else {
if (!is_null($year)) {
$query .= " WHERE DATE_FORMAT( datum, '%Y') = :year";
$bindArray["year"] = [
"value" => $year,
"data_type" => \PDO::PARAM_INT,
];
}
$query .= " ORDER BY datum DESC, nr DESC LIMIT :limit;";
}
$ret = $dbHandle->query(
aQueryString: $query,
aBindArray: $bindArray,
options: [
"dbCharset" => $options["dbCharset"],
"outCharset" => $options["outCharset"],
]
);
return $ret;
}
function newsBoard(\CwsvJudo\Db\Connector $dbHandle, array $options): string
{
$boardHtml = '<div class="container"><div class="row">';
$entries = getNews(dbHandle: $dbHandle, options: $options);
if (!is_null($entries)) {
foreach ($entries as $entryData) {
$entry = new \CwsvJudo\News\Entry($entryData);
$boardHtml .= $entry->as_card();
}
}
$boardHtml .= "</div></div>";
return $boardHtml;
}