Skip to content

Commit 50ec833

Browse files
authored
Merge pull request #47 from BNETDocs/phoenix-packetedit
Implement packet editor
2 parents c18a9f2 + 3e06fb2 commit 50ec833

File tree

11 files changed

+467
-7
lines changed

11 files changed

+467
-7
lines changed

README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -90,5 +90,4 @@ Try accessing this endpoint: [local.bnetdocs.org](https://local.bnetdocs.org)
9090
environment is not your `localhost`.
9191

9292
## Contributing
93-
Please read the [CONTRIBUTING.md]
94-
(https://github.com/BNETDocs/bnetdocs-web/blob/phoenix/CONTRIBUTING.md) file.
93+
Please read the [CONTRIBUTING.md](/CONTRIBUTING.md) file.

src/controllers/Packet/Edit.php

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
<?php
2+
3+
namespace BNETDocs\Controllers\Packet;
4+
5+
use \BNETDocs\Libraries\CSRF;
6+
use \BNETDocs\Libraries\Exceptions\PacketNotFoundException;
7+
use \BNETDocs\Libraries\Logger;
8+
use \BNETDocs\Libraries\Packet;
9+
use \BNETDocs\Libraries\User;
10+
use \BNETDocs\Models\Packet\Edit as PacketEditModel;
11+
use \CarlBennett\MVC\Libraries\Common;
12+
use \CarlBennett\MVC\Libraries\Controller;
13+
use \CarlBennett\MVC\Libraries\DatabaseDriver;
14+
use \CarlBennett\MVC\Libraries\Router;
15+
use \CarlBennett\MVC\Libraries\View;
16+
use \DateTime;
17+
use \DateTimeZone;
18+
use \InvalidArgumentException;
19+
20+
class Edit extends Controller {
21+
22+
public function &run(Router &$router, View &$view, array &$args) {
23+
24+
$data = $router->getRequestQueryArray();
25+
$model = new PacketEditModel();
26+
$model->csrf_id = mt_rand();
27+
$model->csrf_token = CSRF::generate($model->csrf_id, 900); // 15 mins
28+
$model->error = null;
29+
$model->format = null;
30+
$model->id = null;
31+
$model->markdown = null;
32+
$model->name = null;
33+
$model->packet = null;
34+
$model->packet_id = (isset($data["id"]) ? $data["id"] : null);
35+
$model->published = null;
36+
$model->remarks = null;
37+
$model->user = (
38+
isset($_SESSION['user_id']) ? new User($_SESSION['user_id']) : null
39+
);
40+
41+
$model->acl_allowed = ($model->user && $model->user->getAcl(
42+
User::OPTION_ACL_PACKET_MODIFY
43+
));
44+
45+
try { $model->packet = new Packet($model->packet_id); }
46+
catch (PacketNotFoundException $e) { $model->packet = null; }
47+
catch (InvalidArgumentException $e) { $model->packet = null; }
48+
49+
if ($model->packet === null) {
50+
$model->error = "NOT_FOUND";
51+
} else {
52+
$flags = $model->packet->getOptionsBitmask();
53+
54+
$model->id = $model->packet->getPacketId();
55+
$model->name = $model->packet->getPacketName();
56+
$model->format = $model->packet->getPacketFormat();
57+
$model->remarks = $model->packet->getPacketRemarks(false);
58+
$model->markdown = ($flags & Packet::OPTION_MARKDOWN);
59+
$model->published = ($flags & Packet::OPTION_PUBLISHED);
60+
61+
if ($router->getRequestMethod() == "POST") {
62+
$this->handlePost($router, $model);
63+
}
64+
}
65+
66+
$view->render($model);
67+
68+
$model->_responseCode = ($model->acl_allowed ? 200 : 403);
69+
$model->_responseHeaders["Content-Type"] = $view->getMimeType();
70+
$model->_responseTTL = 0;
71+
72+
return $model;
73+
74+
}
75+
76+
protected function handlePost(Router &$router, PacketEditModel &$model) {
77+
if (!$model->acl_allowed) {
78+
$model->error = "ACL_NOT_SET";
79+
return;
80+
}
81+
if (!isset(Common::$database)) {
82+
Common::$database = DatabaseDriver::getDatabaseObject();
83+
}
84+
85+
$data = $router->getRequestBodyArray();
86+
$csrf_id = (isset($data["csrf_id" ]) ? $data["csrf_id" ] : null);
87+
$csrf_token = (isset($data["csrf_token"]) ? $data["csrf_token"] : null);
88+
$csrf_valid = CSRF::validate($csrf_id, $csrf_token);
89+
$id = (isset($data["id" ]) ? $data["id" ] : null);
90+
$name = (isset($data["name" ]) ? $data["name" ] : null);
91+
$format = (isset($data["format" ]) ? $data["format" ] : null);
92+
$remarks = (isset($data["remarks" ]) ? $data["remarks" ] : null);
93+
$markdown = (isset($data["markdown" ]) ? $data["markdown" ] : null);
94+
$content = (isset($data["content" ]) ? $data["content" ] : null);
95+
$publish = (isset($data["publish" ]) ? $data["publish" ] : null);
96+
$save = (isset($data["save" ]) ? $data["save" ] : null);
97+
98+
$model->id = $id;
99+
$model->name = $name;
100+
$model->format = $format;
101+
$model->remarks = $remarks;
102+
$model->markdown = $markdown;
103+
$model->content = $content;
104+
105+
if (!$csrf_valid) {
106+
$model->error = "INVALID_CSRF";
107+
return;
108+
}
109+
CSRF::invalidate($csrf_id);
110+
111+
if (empty($name)) {
112+
$model->error = "EMPTY_NAME";
113+
} else if (empty($format)) {
114+
$model->error = "EMPTY_FORMAT";
115+
} else if (empty($remarks)) {
116+
$model->error = "EMPTY_REMARKS";
117+
}
118+
119+
$user_id = $model->user->getId();
120+
121+
try {
122+
123+
$model->packet->setPacketId($model->id);
124+
$model->packet->setPacketName($model->name);
125+
$model->packet->setPacketFormat($model->format);
126+
$model->packet->setPacketRemarks($model->remarks);
127+
$model->packet->setMarkdown($model->markdown);
128+
$model->packet->setPublished($publish);
129+
130+
$model->packet->setEditedCount(
131+
$model->packet->getEditedCount() + 1
132+
);
133+
$model->packet->setEditedDateTime(
134+
new DateTime("now", new DateTimeZone("UTC"))
135+
);
136+
137+
$success = $model->packet->save();
138+
139+
} catch (QueryException $e) {
140+
141+
// SQL error occurred. We can show a friendly message to the user while
142+
// also notifying this problem to staff.
143+
Logger::logException($e);
144+
145+
$success = false;
146+
147+
}
148+
149+
if (!$success) {
150+
$model->error = "INTERNAL_ERROR";
151+
} else {
152+
$model->error = false;
153+
}
154+
155+
Logger::logEvent(
156+
"packet_edited",
157+
$user_id,
158+
getenv("REMOTE_ADDR"),
159+
json_encode([
160+
"error" => $model->error,
161+
"packet_id" => $model->packet_id,
162+
"options_bitmask" => $model->packet->getOptionsBitmask(),
163+
"name" => $model->packet->getPacketName(),
164+
"format" => $model->packet->getPacketFormat(),
165+
"remarks" => $model->packet->getPacketRemarks(false),
166+
])
167+
);
168+
}
169+
170+
}

src/libraries/Document.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -367,13 +367,13 @@ public function save() {
367367
`id` = :id
368368
LIMIT 1;
369369
");
370-
$stmt->bindParam(":content", $this->content, PDO::PARAM_INT);
370+
$stmt->bindParam(":content", $this->content, PDO::PARAM_STR);
371371
$stmt->bindParam(":created_dt", $this->created_datetime, PDO::PARAM_INT);
372372
$stmt->bindParam(":edited_count", $this->edited_count, PDO::PARAM_INT);
373373
$stmt->bindParam(":edited_dt", $this->edited_datetime, PDO::PARAM_INT);
374374
$stmt->bindParam(":id", $this->id, PDO::PARAM_INT);
375375
$stmt->bindParam(":options", $this->options_bitmask, PDO::PARAM_INT);
376-
$stmt->bindParam(":title", $this->title, PDO::PARAM_INT);
376+
$stmt->bindParam(":title", $this->title, PDO::PARAM_STR);
377377
$stmt->bindParam(":user_id", $this->user_id, PDO::PARAM_INT);
378378
if (!$stmt->execute()) {
379379
throw new QueryException("Cannot save document");

src/libraries/Packet.php

+115
Original file line numberDiff line numberDiff line change
@@ -485,4 +485,119 @@ public function refresh() {
485485
return false;
486486
}
487487

488+
public function save() {
489+
if (!isset(Common::$database)) {
490+
Common::$database = DatabaseDriver::getDatabaseObject();
491+
}
492+
try {
493+
$stmt = Common::$database->prepare("
494+
UPDATE
495+
`packets`
496+
SET
497+
`created_datetime` = :created_dt,
498+
`edited_count` = :edited_count,
499+
`edited_datetime` = :edited_dt,
500+
`options_bitmask` = :options,
501+
`packet_application_layer_id` = :application_layer_id,
502+
`packet_direction_id` = :direction_id,
503+
`packet_format` = :format,
504+
`packet_name` = :name,
505+
`packet_remarks` = :remarks,
506+
`packet_transport_layer_id` = :transport_layer_id,
507+
`user_id` = :user_id
508+
WHERE
509+
`id` = :id
510+
LIMIT 1;
511+
");
512+
$stmt->bindParam(
513+
":application_layer_id", $this->packet_application_layer_id,
514+
PDO::PARAM_INT
515+
);
516+
$stmt->bindParam(":created_dt", $this->created_datetime, PDO::PARAM_INT);
517+
$stmt->bindParam(":edited_count", $this->edited_count, PDO::PARAM_INT);
518+
$stmt->bindParam(":edited_dt", $this->edited_datetime, PDO::PARAM_INT);
519+
$stmt->bindParam(
520+
":direction_id", $this->packet_direction_id, PDO::PARAM_INT
521+
);
522+
$stmt->bindParam(":format", $this->packet_format, PDO::PARAM_STR);
523+
$stmt->bindParam(":id", $this->id, PDO::PARAM_INT);
524+
$stmt->bindParam(":name", $this->packet_name, PDO::PARAM_STR);
525+
$stmt->bindParam(":options", $this->options_bitmask, PDO::PARAM_INT);
526+
$stmt->bindParam(":remarks", $this->packet_remarks, PDO::PARAM_STR);
527+
$stmt->bindParam(
528+
":transport_layer_id", $this->packet_transport_layer_id,
529+
PDO::PARAM_INT
530+
);
531+
$stmt->bindParam(":user_id", $this->user_id, PDO::PARAM_INT);
532+
if (!$stmt->execute()) {
533+
throw new QueryException("Cannot save document");
534+
}
535+
$stmt->closeCursor();
536+
537+
$object = new StdClass();
538+
$object->created_datetime = $this->created_datetime;
539+
$object->edited_count = $this->edited_count;
540+
$object->edited_datetime = $this->edited_datetime;
541+
$object->id = $this->id;
542+
$object->options_bitmask = $this->options_bitmask;
543+
$object->packet_application_layer_id = $this->packet_application_layer_id;
544+
$object->packet_direction_id = $this->packet_direction_id;
545+
$object->packet_format = $this->packet_format;
546+
$object->packet_id = $this->packet_id;
547+
$object->packet_name = $this->packet_name;
548+
$object->packet_remarks = $this->packet_remarks;
549+
$object->packet_transport_layer_id = $this->packet_transport_layer_id;
550+
$object->user_id = $this->user_id;
551+
552+
$cache_key = "bnetdocs-packet-" . $this->id;
553+
Common::$cache->set($cache_key, serialize($object), 300);
554+
Common::$cache->delete("bnetdocs-packets");
555+
556+
return true;
557+
} catch (PDOException $e) {
558+
throw new QueryException("Cannot save packet", $e);
559+
}
560+
return false;
561+
}
562+
563+
public function setEditedCount($value) {
564+
$this->edited_count = $value;
565+
}
566+
567+
public function setEditedDateTime(\DateTime $value) {
568+
$this->edited_datetime = $value->format("Y-m-d H:i:s");
569+
}
570+
571+
public function setMarkdown($value) {
572+
if ($value) {
573+
$this->options_bitmask |= self::OPTION_MARKDOWN;
574+
} else {
575+
$this->options_bitmask &= ~self::OPTION_MARKDOWN;
576+
}
577+
}
578+
579+
public function setPacketFormat($value) {
580+
$this->packet_format = $value;
581+
}
582+
583+
public function setPacketId($value) {
584+
$this->packet_id = $value;
585+
}
586+
587+
public function setPacketName($value) {
588+
$this->packet_name = $value;
589+
}
590+
591+
public function setPacketRemarks($value) {
592+
$this->packet_remarks = $value;
593+
}
594+
595+
public function setPublished($value) {
596+
if ($value) {
597+
$this->options_bitmask |= self::OPTION_PUBLISHED;
598+
} else {
599+
$this->options_bitmask &= ~self::OPTION_PUBLISHED;
600+
}
601+
}
602+
488603
}

src/main.php

+3
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ function main() {
163163
//$router->addRoute( // URL: /packet/create
164164
// "#^/packet/create/?$#", "Packet\\Create", "Packet\\CreateHtml"
165165
//);
166+
$router->addRoute( // URL: /packet/edit
167+
"#^/packet/edit/?$#", "Packet\\Edit", "Packet\\EditHtml"
168+
);
166169
$router->addRoute( // URL: /packet/index.cpp
167170
"#^/packet/index\.cpp/?$#", "Packet\\Index", "Packet\\IndexCpp"
168171
);

src/models/Document/Edit.php

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
class Edit extends Model {
88

99
public $acl_allowed;
10+
public $category;
1011
public $content;
1112
public $csrf_id;
1213
public $csrf_token;

src/models/Packet/Edit.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace BNETDocs\Models\Packet;
4+
5+
use \CarlBennett\MVC\Libraries\Model;
6+
7+
class Edit extends Model {
8+
9+
public $acl_allowed;
10+
public $csrf_id;
11+
public $csrf_token;
12+
public $error;
13+
public $format;
14+
public $id;
15+
public $markdown;
16+
public $name;
17+
public $packet;
18+
public $packet_id;
19+
public $published;
20+
public $remarks;
21+
public $user;
22+
23+
}

src/templates/Document/Edit.phtml

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ switch ($this->getContext()->error) {
1919
$message = "Cannot find document by that id.";
2020
break;
2121
case "INVALID_CSRF":
22-
$message = "The Cross-Site Request Forgery token was invalid. Either the"
23-
. "edit document form expired, or this may have been a malicious attempt"
24-
. "to create a document.";
22+
$message = "The Cross-Site Request Forgery token was invalid. Either the "
23+
. "edit document form expired, or this may have been a malicious "
24+
. "attempt to create a document.";
2525
break;
2626
case "EMPTY_TITLE":
2727
$message = "The title of the document is required.";

0 commit comments

Comments
 (0)