Not all mandatory fields in episode creation are marked so?
Describe the bug
Failing to fill new episode title in creation form incorrectly does not show form validation error, instead showing HTTP 50x.
Steps to reproduce
- Go to admin->some podcast->new episode
- Only select audio file (omit title!)
Expected behavior
Form validation fails, telling you to fill the title.
Actual behavior
50x in routing (?).
Relevant logs and/or screenshots
Dump from CI_ENVIRONMENT="development"
run:
CodeIgniter\Router\Exceptions\RouterException
Router.invalidParameterType
SYSTEMPATH/Router/RouteCollection.php at line 1378
1371
1372 // Remove `(:` and `)` when $placeholder is a placeholder.
1373 $placeholderName = substr($placeholder, 2, -1);
1374 // or maybe $placeholder is not a placeholder, but a regex.
1375 $pattern = $this->placeholders[$placeholderName] ?? $placeholder;
1376
1377 if (! preg_match('#^' . $pattern . '$#u', $params[$index])) {
1378 throw RouterException::forInvalidParameterType();
1379 }
1380
1381 // Ensure that the param we're inserting matches
1382 // the expected param type.
1383 $pos = strpos($from, $placeholder);
1384 $from = substr_replace($from, $params[$index], $pos, strlen($placeholder));
1385 }
Backtrace Server Request Response Files Memory
SYSTEMPATH/Router/RouteCollection.php : 1378 — CodeIgniter\Router\Exceptions\RouterException::forInvalidParameterType ()
1371
1372 // Remove `(:` and `)` when $placeholder is a placeholder.
1373 $placeholderName = substr($placeholder, 2, -1);
1374 // or maybe $placeholder is not a placeholder, but a regex.
1375 $pattern = $this->placeholders[$placeholderName] ?? $placeholder;
1376
1377 if (! preg_match('#^' . $pattern . '$#u', $params[$index])) {
1378 throw RouterException::forInvalidParameterType();
1379 }
1380
1381 // Ensure that the param we're inserting matches
1382 // the expected param type.
1383 $pos = strpos($from, $placeholder);
1384 $from = substr_replace($from, $params[$index], $pos, strlen($placeholder));
1385 }
SYSTEMPATH/Router/RouteCollection.php : 1169 — CodeIgniter\Router\RouteCollection->buildReverseRoute ()
1162 // Named routes get higher priority.
1163 foreach ($this->routesNames as $verb => $collection) {
1164 if (array_key_exists($search, $collection)) {
1165 $routeKey = $collection[$search];
1166
1167 $from = $this->routes[$verb][$routeKey]['from'];
1168
1169 return $this->buildReverseRoute($from, $params);
1170 }
1171 }
1172
1173 // Add the default namespace if needed.
1174 $namespace = trim($this->defaultNamespace, '\\') . '\\';
1175 if (
1176 substr($search, 0, 1) !== '\\'
SYSTEMPATH/Common.php : 978 — CodeIgniter\Router\RouteCollection->reverseRoute ()
971 * @param int|string ...$params One or more parameters to be passed to the route.
972 * The last parameter allows you to set the locale.
973 *
974 * @return false|string The route (URI path relative to baseURL) or false if not found.
975 */
976 function route_to(string $method, ...$params)
977 {
978 return Services::routes()->reverseRoute($method, ...$params);
979 }
980 }
981
982 if (! function_exists('session')) {
983 /**
984 * A convenience method for accessing the session instance,
985 * or an item that has been set in the session.
SYSTEMPATH/Helpers/url_helper.php : 482 — route_to()
APPPATH/Entities/Episode.php : 454 — url_to()
APPPATH/Entities/Episode.php : 466 — App\Entities\Episode->getLink ()
459 return $theme
460 ? url_to('embed-theme', esc($this->getPodcast()->handle), esc($this->attributes['slug']), $theme)
461 : url_to('embed', esc($this->getPodcast()->handle), esc($this->attributes['slug']));
462 }
463
464 public function setGuid(?string $guid = null): static
465 {
466 $this->attributes['guid'] = $guid === null ? $this->getLink() : $guid;
467
468 return $this;
469 }
470
471 public function getPodcast(): ?Podcast
472 {
473 return (new PodcastModel())->getPodcastById($this->podcast_id);
SYSTEMPATH/Entity/Entity.php : 485 — App\Entities\Episode->setGuid ()
478 $this->{'_' . $method}($value);
479
480 return;
481 }
482
483 // If a "`set` + $key" method exists, it is also a setter.
484 if (method_exists($this, $method) && $method !== 'setAttributes') {
485 $this->{$method}($value);
486
487 return;
488 }
489
490 // Otherwise, just the value. This allows for creation of new
491 // class properties that are undefined, though they cannot be
492 // saved. Useful for grabbing values through joins, assigning
SYSTEMPATH/Entity/Entity.php : 152 — CodeIgniter\Entity\Entity->__set ()
145 public function fill(?array $data = null)
146 {
147 if (! is_array($data)) {
148 return $this;
149 }
150
151 foreach ($data as $key => $value) {
152 $this->__set($key, $value);
153 }
154
155 return $this;
156 }
157
158 /**
159 * General method that will return all public and protected values
SYSTEMPATH/Entity/Entity.php : 133 — CodeIgniter\Entity\Entity->fill ()
126 /**
127 * Allows filling in Entity parameters during construction.
128 */
129 public function __construct(?array $data = null)
130 {
131 $this->syncOriginal();
132
133 $this->fill($data);
134 }
135
136 /**
137 * Takes an array of key/value pairs and sets them as class
138 * properties, using any `setCamelCasedProperty()` methods
139 * that may or may not exist.
140 *
ROOTPATH/modules/Admin/Controllers/EpisodeController.php : 195 — CodeIgniter\Entity\Entity->__construct ()
188 ->withInput()
189 ->with('error', lang('Episode.messages.sameSlugError'));
190 }
191
192 $db = db_connect();
193 $db->transStart();
194
195 $newEpisode = new Episode([
196 'created_by' => user_id(),
197 'updated_by' => user_id(),
198 'podcast_id' => $this->podcast->id,
199 'title' => $this->request->getPost('title'),
200 'slug' => $this->request->getPost('slug'),
201 'guid' => null,
202 'audio' => $this->request->getFile('audio_file'),
ROOTPATH/modules/Admin/Controllers/EpisodeController.php : 64 — Modules\Admin\Controllers\EpisodeController->attemptCreate ()
57
58 $this->episode = $episode;
59
60 unset($params[1]);
61 unset($params[0]);
62 }
63
64 return $this->{$method}(...$params);
65 }
66
67 public function list(): string
68 {
69 /** @var ?string $query */
70 $query = $this->request->getGet('q');
71
SYSTEMPATH/CodeIgniter.php : 941 — Modules\Admin\Controllers\EpisodeController->_remap ()
934 */
935 protected function runController($class)
936 {
937 // This is a Web request or PHP CLI request
938 $params = $this->router->params();
939
940 $output = method_exists($class, '_remap')
941 ? $class->_remap($this->method, ...$params)
942 : $class->{$this->method}(...$params);
943
944 $this->benchmark->stop('controller');
945
946 return $output;
947 }
948
SYSTEMPATH/CodeIgniter.php : 502 — CodeIgniter\CodeIgniter->runController ()
495 if (! method_exists($controller, '_remap') && ! is_callable([$controller, $this->method], false)) {
496 throw PageNotFoundException::forMethodNotFound($this->method);
497 }
498
499 // Is there a "post_controller_constructor" event?
500 Events::trigger('post_controller_constructor');
501
502 $returned = $this->runController($controller);
503 } else {
504 $this->benchmark->stop('controller_constructor');
505 $this->benchmark->stop('controller');
506 }
507
508 // If $returned is a string, then the controller output something,
509 // probably a view, instead of echoing it directly. Send it along
SYSTEMPATH/CodeIgniter.php : 361 — CodeIgniter\CodeIgniter->handleRequest ()
354
355 $this->getRequestObject();
356 $this->getResponseObject();
357
358 $this->spoofRequestMethod();
359
360 try {
361 $this->response = $this->handleRequest($routes, config(Cache::class), $returnResponse);
362 } catch (ResponsableInterface|DeprecatedRedirectException $e) {
363 $this->outputBufferingEnd();
364 if ($e instanceof DeprecatedRedirectException) {
365 $e = new RedirectException($e->getMessage(), $e->getCode(), $e);
366 }
367
368 $this->response = $e->getResponse();
FCPATH/index.php : 85 — CodeIgniter\CodeIgniter->run ()
78 *---------------------------------------------------------------
79 * LAUNCH THE APPLICATION
80 *---------------------------------------------------------------
81 * Now that everything is set up, it's time to actually fire
82 * up the engines and make this app do its thang.
83 */
84
85 $app->run();
86
87 // Save Config Cache
88 // $factoriesCache->save('config');
89 // ^^^ Uncomment this line if you want to use Config Caching.
90
91 // Exits the application, setting the exit code for CLI-based applications
92 // that might be watching.
Displayed at 19:17:29pm — PHP: 8.2.14 — CodeIgniter: 4.4.3 -- Environment: development
Context
- Castopod: 1.7.3
- OS: Debian 11
- Browser: Firefox 121
- Web server: NGINX
- Yunohost 11.2.8 with Castopod 1.7.3~ynh2
Possible fixes
Works when I fill title field (i.e. missing description properly causes validation error).
Edited by orhtej2