diff --git a/app/psalm-baseline.xml b/app/psalm-baseline.xml
index ef9f86578..0b801c727 100644
--- a/app/psalm-baseline.xml
+++ b/app/psalm-baseline.xml
@@ -11,32 +11,6 @@
password]]>
-
-
- action]]>
- action]]>
- audioEmbed]]>
- audioEmbed]]>
- audioHref]]>
- audioHref]]>
- date]]>
- date]]>
- description]]>
- description]]>
- href]]>
- href]]>
- sourceHref]]>
- sourceHref]]>
- sourceName]]>
- sourceName]]>
- title]]>
- title]]>
- videoEmbed]]>
- videoEmbed]]>
- videoHref]]>
- videoHref]]>
-
-
lead === '' ? null : $values->lead]]>
@@ -61,52 +35,6 @@
site->new->url]]>
-
-
- action]]>
- action]]>
- date]]>
- date]]>
- description]]>
- description]]>
- event]]>
- event]]>
- eventHref]]>
- eventHref]]>
- favorite]]>
- favorite]]>
- filenamesTalk]]>
- filenamesTalk]]>
- href]]>
- href]]>
- locale]]>
- locale]]>
- ogImage]]>
- ogImage]]>
- publishSlides]]>
- publishSlides]]>
- slidesEmbed]]>
- slidesEmbed]]>
- slidesHref]]>
- slidesHref]]>
- slidesNote]]>
- slidesNote]]>
- slidesTalk]]>
- slidesTalk]]>
- supersededBy]]>
- supersededBy]]>
- title]]>
- title]]>
- transcript]]>
- transcript]]>
- translationGroup]]>
- translationGroup]]>
- videoEmbed]]>
- videoEmbed]]>
- videoHref]]>
- videoHref]]>
-
-
@@ -210,12 +138,6 @@
-
-
- videoThumbnail]]>
- videoThumbnailAlternative]]>
-
-
diff --git a/app/src/Form/InterviewFormFactory.php b/app/src/Form/InterviewFormFactory.php
index 370895ac9..80eb5e00c 100644
--- a/app/src/Form/InterviewFormFactory.php
+++ b/app/src/Form/InterviewFormFactory.php
@@ -9,6 +9,7 @@
use MichalSpacekCz\Media\VideoThumbnails;
use Nette\Forms\Controls\SubmitButton;
use Nette\Forms\Form;
+use Nette\Http\FileUpload;
readonly class InterviewFormFactory
{
@@ -71,8 +72,21 @@ public function create(callable $onSuccess, ?Interview $interview = null): UiFor
$form->onSuccess[] = function (UiForm $form) use ($interview, $onSuccess, $videoThumbnailFormFields): void {
$values = $form->getFormValues();
- $videoThumbnailBasename = $this->videoThumbnails->getUploadedMainFileBasename($values);
- $videoThumbnailBasenameAlternative = $this->videoThumbnails->getUploadedAlternativeFileBasename($values);
+ assert($values->videoThumbnail instanceof FileUpload);
+ assert($values->videoThumbnailAlternative instanceof FileUpload);
+ assert(is_string($values->action));
+ assert(is_string($values->title));
+ assert(is_string($values->description));
+ assert(is_string($values->date));
+ assert(is_string($values->href));
+ assert(is_string($values->audioHref));
+ assert(is_string($values->audioEmbed));
+ assert(is_string($values->videoHref));
+ assert(is_string($values->videoEmbed));
+ assert(is_string($values->sourceName));
+ assert(is_string($values->sourceHref));
+ $videoThumbnailBasename = $this->videoThumbnails->getUploadedMainFileBasename($values->videoThumbnail);
+ $videoThumbnailBasenameAlternative = $this->videoThumbnails->getUploadedAlternativeFileBasename($values->videoThumbnailAlternative);
if ($interview) {
$removeVideoThumbnail = $videoThumbnailFormFields->hasVideoThumbnail() && $values->removeVideoThumbnail;
$removeVideoThumbnailAlternative = $videoThumbnailFormFields->hasAlternativeVideoThumbnail() && $values->removeVideoThumbnailAlternative;
@@ -94,7 +108,7 @@ public function create(callable $onSuccess, ?Interview $interview = null): UiFor
$values->sourceName,
$values->sourceHref,
);
- $this->videoThumbnails->saveVideoThumbnailFiles($interview->getId(), $values);
+ $this->videoThumbnails->saveVideoThumbnailFiles($interview->getId(), $values->videoThumbnail, $values->videoThumbnailAlternative);
if ($removeVideoThumbnail && $thumbnailFilename !== null) {
$this->videoThumbnails->deleteFile($interview->getId(), $thumbnailFilename);
}
@@ -117,7 +131,7 @@ public function create(callable $onSuccess, ?Interview $interview = null): UiFor
$values->sourceName,
$values->sourceHref,
);
- $this->videoThumbnails->saveVideoThumbnailFiles($interviewId, $values);
+ $this->videoThumbnails->saveVideoThumbnailFiles($interviewId, $values->videoThumbnail, $values->videoThumbnailAlternative);
}
$onSuccess();
};
diff --git a/app/src/Form/SignInHoneypotFormFactory.php b/app/src/Form/SignInHoneypotFormFactory.php
index e0d38a8d8..766ee20ea 100644
--- a/app/src/Form/SignInHoneypotFormFactory.php
+++ b/app/src/Form/SignInHoneypotFormFactory.php
@@ -26,6 +26,8 @@ public function create(): UiForm
$this->controlsFactory->addSignIn($form);
$form->onSuccess[] = function (UiForm $form): void {
$values = $form->getFormValues();
+ assert(is_string($values->username));
+ assert(is_string($values->password));
Debugger::log("Sign-in attempt: {$values->username}, {$values->password}, {$this->httpRequest->getRemoteAddress()}", 'honeypot');
$creds = $values->username . ':' . $values->password;
if (Regex::isMatch('~\slimit\s~i', $creds)) {
diff --git a/app/src/Form/TalkFormFactory.php b/app/src/Form/TalkFormFactory.php
index e1cfd53ba..f7cf45dea 100644
--- a/app/src/Form/TalkFormFactory.php
+++ b/app/src/Form/TalkFormFactory.php
@@ -11,6 +11,7 @@
use MichalSpacekCz\Talks\Talks;
use Nette\Forms\Controls\SubmitButton;
use Nette\Forms\Form;
+use Nette\Http\FileUpload;
use Nette\Utils\Html;
use Nette\Utils\Strings;
@@ -107,8 +108,32 @@ public function create(callable $onSuccess, ?Talk $talk = null): UiForm
$form->onSuccess[] = function (UiForm $form) use ($talk, $onSuccess, $videoThumbnailFormFields): void {
$values = $form->getFormValues();
- $videoThumbnailBasename = $this->videoThumbnails->getUploadedMainFileBasename($values);
- $videoThumbnailBasenameAlternative = $this->videoThumbnails->getUploadedAlternativeFileBasename($values);
+ assert($values->videoThumbnail instanceof FileUpload);
+ assert($values->videoThumbnailAlternative instanceof FileUpload);
+ assert(is_int($values->locale));
+ assert(is_int($values->translationGroup) || $values->translationGroup === null);
+ assert(is_string($values->action));
+ assert(is_string($values->title));
+ assert(is_string($values->description));
+ assert(is_string($values->date));
+ assert(is_string($values->duration));
+ assert(is_string($values->href));
+ assert(is_int($values->slidesTalk) || $values->slidesTalk === null);
+ assert(is_int($values->filenamesTalk) || $values->filenamesTalk === null);
+ assert(is_string($values->slidesHref));
+ assert(is_string($values->slidesEmbed));
+ assert(is_string($values->slidesNote));
+ assert(is_string($values->videoHref));
+ assert(is_string($values->videoEmbed));
+ assert(is_string($values->event));
+ assert(is_string($values->eventHref));
+ assert(is_string($values->ogImage));
+ assert(is_string($values->transcript));
+ assert(is_string($values->favorite));
+ assert(is_int($values->supersededBy) || $values->supersededBy === null);
+ assert(is_bool($values->publishSlides));
+ $videoThumbnailBasename = $this->videoThumbnails->getUploadedMainFileBasename($values->videoThumbnail);
+ $videoThumbnailBasenameAlternative = $this->videoThumbnails->getUploadedAlternativeFileBasename($values->videoThumbnailAlternative);
if ($talk) {
$removeVideoThumbnail = $videoThumbnailFormFields->hasVideoThumbnail() && $values->removeVideoThumbnail;
$removeVideoThumbnailAlternative = $videoThumbnailFormFields->hasAlternativeVideoThumbnail() && $values->removeVideoThumbnailAlternative;
@@ -141,7 +166,7 @@ public function create(callable $onSuccess, ?Talk $talk = null): UiForm
$values->supersededBy,
$values->publishSlides,
);
- $this->videoThumbnails->saveVideoThumbnailFiles($talk->getId(), $values);
+ $this->videoThumbnails->saveVideoThumbnailFiles($talk->getId(), $values->videoThumbnail, $values->videoThumbnailAlternative);
if ($removeVideoThumbnail && $thumbnailFilename !== null) {
$this->videoThumbnails->deleteFile($talk->getId(), $thumbnailFilename);
}
@@ -176,7 +201,7 @@ public function create(callable $onSuccess, ?Talk $talk = null): UiForm
$values->supersededBy,
$values->publishSlides,
);
- $this->videoThumbnails->saveVideoThumbnailFiles($talkId, $values);
+ $this->videoThumbnails->saveVideoThumbnailFiles($talkId, $values->videoThumbnail, $values->videoThumbnailAlternative);
$message = Html::el()->setText('Přednáška přidána ');
}
$message->addHtml(Html::el('a')->href($this->linkGenerator->link('Www:Talks:talk', [$values->action]))->setText('Zobrazit'));
diff --git a/app/src/Form/TalkSlidesFormFactory.php b/app/src/Form/TalkSlidesFormFactory.php
index 12bb0e9d7..865075b36 100644
--- a/app/src/Form/TalkSlidesFormFactory.php
+++ b/app/src/Form/TalkSlidesFormFactory.php
@@ -65,7 +65,7 @@ public function create(callable $onSuccess, int $talkId, TalkSlideCollection $sl
assert($values->slides instanceof ArrayHash);
assert($values->new instanceof ArrayHash);
assert(is_bool($values->deleteReplaced));
- $this->talkSlides->saveSlides($talkId, $slides, (array)$values->slides, array_values((array)$values->new), $values->deleteReplaced);
+ $this->talkSlides->saveSlides($talkId, $slides, $values->slides, $values->new, $values->deleteReplaced);
$message = $this->texyFormatter->translate('messages.talks.admin.slideadded');
$type = 'info';
} catch (DuplicatedSlideException $e) {
diff --git a/app/src/Media/VideoThumbnails.php b/app/src/Media/VideoThumbnails.php
index c01237e1d..a11f8bf22 100644
--- a/app/src/Media/VideoThumbnails.php
+++ b/app/src/Media/VideoThumbnails.php
@@ -13,7 +13,6 @@
use Nette\Http\FileUpload;
use Nette\Utils\Callback;
use Nette\Utils\ImageException;
-use stdClass;
readonly class VideoThumbnails
{
@@ -114,18 +113,18 @@ public function deleteFile(int $id, string $basename): void
/**
* @throws ContentTypeException
*/
- public function getUploadedMainFileBasename(stdClass $values): ?string
+ public function getUploadedMainFileBasename(FileUpload $thumbnail): ?string
{
- return $this->getUploadedFileBasename($values->videoThumbnail, $this->supportedImageFileFormats->getMainExtensionByContentType(...));
+ return $this->getUploadedFileBasename($thumbnail, $this->supportedImageFileFormats->getMainExtensionByContentType(...));
}
/**
* @throws ContentTypeException
*/
- public function getUploadedAlternativeFileBasename(stdClass $values): ?string
+ public function getUploadedAlternativeFileBasename(FileUpload $thumbnail): ?string
{
- return $this->getUploadedFileBasename($values->videoThumbnailAlternative, $this->supportedImageFileFormats->getAlternativeExtensionByContentType(...));
+ return $this->getUploadedFileBasename($thumbnail, $this->supportedImageFileFormats->getAlternativeExtensionByContentType(...));
}
@@ -149,15 +148,15 @@ private function getUploadedFileBasename(FileUpload $thumbnail, callable $getExt
/**
* @throws ContentTypeException
*/
- public function saveVideoThumbnailFiles(int $id, stdClass $values): void
+ public function saveVideoThumbnailFiles(int $id, FileUpload $videoThumbnail, FileUpload $videoThumbnailAlternative): void
{
- $basename = $this->getUploadedMainFileBasename($values);
+ $basename = $this->getUploadedMainFileBasename($videoThumbnail);
if ($basename !== null) {
- $values->videoThumbnail->move($this->mediaResources->getImageFilename($id, $basename));
+ $videoThumbnail->move($this->mediaResources->getImageFilename($id, $basename));
}
- $basename = $this->getUploadedAlternativeFileBasename($values);
+ $basename = $this->getUploadedAlternativeFileBasename($videoThumbnailAlternative);
if ($basename !== null) {
- $values->videoThumbnailAlternative->move($this->mediaResources->getImageFilename($id, $basename));
+ $videoThumbnailAlternative->move($this->mediaResources->getImageFilename($id, $basename));
}
}
diff --git a/app/src/Talks/Slides/TalkSlides.php b/app/src/Talks/Slides/TalkSlides.php
index 5d90d4f6d..1c5dea6fe 100644
--- a/app/src/Talks/Slides/TalkSlides.php
+++ b/app/src/Talks/Slides/TalkSlides.php
@@ -204,19 +204,16 @@ private function replaceSlideImage(int $talkId, FileUpload $replace, callable $g
/**
- * Insert slides.
- *
- * @param int $talkId
- * @param list> $slides
* @throws DuplicatedSlideException
* @throws ContentTypeException
* @throws SlideImageUploadFailedException
*/
- private function addSlides(int $talkId, array $slides): void
+ private function addSlides(int $talkId, ArrayHash $slides): void
{
$lastNumber = 0;
try {
foreach ($slides as $slide) {
+ assert($slide instanceof ArrayHash);
assert($slide->replace instanceof FileUpload);
assert($slide->replaceAlternative instanceof FileUpload);
assert(is_int($slide->number));
@@ -245,16 +242,13 @@ private function addSlides(int $talkId, array $slides): void
/**
- * Update slides.
- *
- * @param array> $slides
* @param bool $removeFiles Remove old files?
* @throws DuplicatedSlideException
* @throws ContentTypeException
* @throws SlideImageUploadFailedException
* @throws TalkSlideDoesNotExistException
*/
- private function updateSlides(int $talkId, TalkSlideCollection $originalSlides, array $slides, bool $removeFiles): void
+ private function updateSlides(int $talkId, TalkSlideCollection $originalSlides, ArrayHash $slides, bool $removeFiles): void
{
foreach ($originalSlides as $slide) {
foreach ($slide->getAllFilenames() as $filename) {
@@ -262,6 +256,7 @@ private function updateSlides(int $talkId, TalkSlideCollection $originalSlides,
}
}
foreach ($slides as $id => $slide) {
+ assert($slide instanceof ArrayHash);
assert($slide->replace instanceof FileUpload || $slide->replace === null);
assert($slide->replaceAlternative instanceof FileUpload || $slide->replaceAlternative === null);
assert(is_string($slide->alias));
@@ -318,14 +313,12 @@ private function updateSlidesRow(int $talkId, string $alias, int $slideNumber, s
/**
- * @param array> $updateSlides
- * @param list> $newSlides
* @throws ContentTypeException
* @throws DuplicatedSlideException
* @throws SlideImageUploadFailedException
* @throws TalkSlideDoesNotExistException
*/
- public function saveSlides(int $talkId, TalkSlideCollection $originalSlides, array $updateSlides, array $newSlides, bool $deleteReplaced): void
+ public function saveSlides(int $talkId, TalkSlideCollection $originalSlides, ArrayHash $updateSlides, ArrayHash $newSlides, bool $deleteReplaced): void
{
$this->otherSlides = [];
$this->database->beginTransaction();
diff --git a/app/tests/Form/InterviewFormFactoryTest.phpt b/app/tests/Form/InterviewFormFactoryTest.phpt
new file mode 100644
index 000000000..9e8e2c430
--- /dev/null
+++ b/app/tests/Form/InterviewFormFactoryTest.phpt
@@ -0,0 +1,67 @@
+formFactory->create(
+ function (): void {
+ $this->result = true;
+ },
+ null,
+ );
+ $form->setDefaults([
+ 'action' => 'foo',
+ 'date' => '3210-09-08 10:20:30',
+ ]);
+ $this->applicationPresenter->anchorForm($form);
+ Arrays::invoke($form->onSuccess, $form);
+ Assert::true($this->result);
+ Assert::same([
+ [
+ 'action' => 'foo',
+ 'title' => '',
+ 'description' => null,
+ 'date' => '3210-09-08 10:20:30',
+ 'href' => '',
+ 'audio_href' => null,
+ 'audio_embed' => null,
+ 'video_href' => null,
+ 'video_thumbnail' => null,
+ 'video_thumbnail_alternative' => null,
+ 'video_embed' => null,
+ 'source_name' => '',
+ 'source_href' => '',
+ ],
+ ], $this->database->getParamsArrayForQuery('INSERT INTO interviews'));
+ }
+
+}
+
+TestCaseRunner::run(InterviewFormFactoryTest::class);
diff --git a/app/tests/Form/TalkFormFactoryTest.phpt b/app/tests/Form/TalkFormFactoryTest.phpt
new file mode 100644
index 000000000..142b00384
--- /dev/null
+++ b/app/tests/Form/TalkFormFactoryTest.phpt
@@ -0,0 +1,98 @@
+database->addFetchPairsResult([
+ 123 => 'cs_CZ',
+ 321 => 'en_US',
+ ]);
+ }
+
+
+ #[Override]
+ protected function tearDown(): void
+ {
+ $this->database->reset();
+ }
+
+
+ public function testCreateOnSuccessAdd(): void
+ {
+ $form = $this->formFactory->create(
+ function (Html $message): void {
+ $this->message = $message;
+ },
+ null,
+ );
+ $form->setDefaults([
+ 'locale' => 123,
+ 'action' => 'foo',
+ 'date' => '3210-09-08 10:20:30',
+ ]);
+ $this->applicationPresenter->anchorForm($form);
+ Arrays::invoke($form->onSuccess, $form);
+ Assert::same('Přednáška přidána Zobrazit', $this->message?->toHtml());
+ Assert::same([
+ [
+ 'key_locale' => 123,
+ 'key_translation_group' => null,
+ 'action' => 'foo',
+ 'title' => '',
+ 'description' => null,
+ 'date' => '3210-09-08 10:20:30',
+ 'duration' => null,
+ 'href' => null,
+ 'key_talk_slides' => null,
+ 'key_talk_filenames' => null,
+ 'slides_href' => null,
+ 'slides_embed' => null,
+ 'slides_note' => null,
+ 'video_href' => null,
+ 'video_thumbnail' => null,
+ 'video_thumbnail_alternative' => null,
+ 'video_embed' => null,
+ 'event' => '',
+ 'event_href' => null,
+ 'og_image' => null,
+ 'transcript' => null,
+ 'favorite' => null,
+ 'key_superseded_by' => null,
+ 'publish_slides' => false,
+ ],
+ ], $this->database->getParamsArrayForQuery('INSERT INTO talks'));
+ }
+
+}
+
+TestCaseRunner::run(TalkFormFactoryTest::class);
diff --git a/app/tests/Media/VideoThumbnailsTest.phpt b/app/tests/Media/VideoThumbnailsTest.phpt
new file mode 100644
index 000000000..434b69159
--- /dev/null
+++ b/app/tests/Media/VideoThumbnailsTest.phpt
@@ -0,0 +1,73 @@
+videoThumbnails = new VideoThumbnails($mediaResources, $supportedImageFormats);
+ }
+
+
+ public function testGetUploadedMainFileBasename(): void
+ {
+ $upload = $this->getFileUpload('foo', UPLOAD_ERR_EXTENSION);
+ Assert::null($this->videoThumbnails->getUploadedMainFileBasename($upload));
+
+ $upload = $this->getFileUpload(__DIR__ . '/thumbnail-not-pic', UPLOAD_ERR_OK);
+ Assert::exception(function () use ($upload): void {
+ $this->videoThumbnails->getUploadedMainFileBasename($upload);
+ }, UnsupportedContentTypeException::class, 'Unsupported content type \'text/plain\', available types are {"image/gif":"gif","image/png":"png","image/jpeg":"jpg"}');
+
+ $upload = $this->getFileUpload(__DIR__ . '/thumbnail-gif-no-ext', UPLOAD_ERR_OK);
+ Assert::same('video-thumbnail.gif', $this->videoThumbnails->getUploadedMainFileBasename($upload));
+ }
+
+
+ public function testGetUploadedAlternativeFileBasename(): void
+ {
+ $upload = $this->getFileUpload('foo', UPLOAD_ERR_EXTENSION);
+ Assert::null($this->videoThumbnails->getUploadedAlternativeFileBasename($upload));
+
+ $upload = $this->getFileUpload(__DIR__ . '/thumbnail-not-pic', UPLOAD_ERR_OK);
+ Assert::exception(function () use ($upload): void {
+ $this->videoThumbnails->getUploadedAlternativeFileBasename($upload);
+ }, UnsupportedContentTypeException::class, 'Unsupported content type \'text/plain\', available types are {"image/webp":"webp"}');
+
+ $upload = $this->getFileUpload(__DIR__ . '/thumbnail-webp-no-ext', UPLOAD_ERR_OK);
+ Assert::same('video-thumbnail.webp', $this->videoThumbnails->getUploadedAlternativeFileBasename($upload));
+ }
+
+
+ private function getFileUpload(string $tmpName, int $error): FileUpload
+ {
+ return new FileUpload([
+ 'name' => 'test',
+ 'size' => 123,
+ 'tmp_name' => $tmpName,
+ 'error' => $error,
+ ]);
+ }
+
+}
+
+TestCaseRunner::run(VideoThumbnailsTest::class);
diff --git a/app/tests/Media/thumbnail-gif-no-ext b/app/tests/Media/thumbnail-gif-no-ext
new file mode 100644
index 000000000..edaf2b97a
Binary files /dev/null and b/app/tests/Media/thumbnail-gif-no-ext differ
diff --git a/app/tests/Media/thumbnail-not-pic b/app/tests/Media/thumbnail-not-pic
new file mode 100644
index 000000000..db0c8bc57
--- /dev/null
+++ b/app/tests/Media/thumbnail-not-pic
@@ -0,0 +1 @@
+This thumbnail is not a picture, which makes it not a thumbnail at all. Wait, what?
diff --git a/app/tests/Media/thumbnail-webp-no-ext b/app/tests/Media/thumbnail-webp-no-ext
new file mode 100644
index 000000000..2f8bf8fa1
Binary files /dev/null and b/app/tests/Media/thumbnail-webp-no-ext differ
diff --git a/app/tests/Talks/Slides/TalkSlidesTest.phpt b/app/tests/Talks/Slides/TalkSlidesTest.phpt
index 4608cb1f2..149219aba 100644
--- a/app/tests/Talks/Slides/TalkSlidesTest.phpt
+++ b/app/tests/Talks/Slides/TalkSlidesTest.phpt
@@ -52,14 +52,12 @@ class TalkSlidesTest extends TestCase
$slides = new TalkSlideCollection(303);
$slides->add(new TalkSlide(1, 'slide1', 1, 'slide1.jpg', 'slide-alt.jpg', null, 'Title 1', Html::fromText('Notes 1'), 'Notes 1', null, null, null));
$slides->add(new TalkSlide(2, 'slide2', 2, 'slide2.jpg', 'slide-alt.jpg', null, 'Title 2', Html::fromText('Notes 2'), 'Notes 2', null, null, null));
- $updateSlides = [
- 1 => $this->buildSlideArrayHash(1, 'foo1', 'Title 1', 'Speaker notes 1', 'slide1.jpg', null, 'slide-alt1.jpg', null),
- 2 => $this->buildSlideArrayHash(2, 'foo2', 'Title 2', 'Speaker notes 2', 'slide2.jpg', null, 'slide-alt2.jpg', null),
- ];
- $newSlides = [
- $this->buildSlideArrayHash(3, 'new1', 'New 1', 'New notes 1', null, new FileUpload(null), null, new FileUpload(null)),
- $this->buildSlideArrayHash(4, 'new2', 'New 2', 'New notes 2', null, new FileUpload(null), null, new FileUpload(null)),
- ];
+ $updateSlides = new ArrayHash();
+ $updateSlides[1] = $this->buildSlideArrayHash(1, 'foo1', 'Title 1', 'Speaker notes 1', 'slide1.jpg', null, 'slide-alt1.jpg', null);
+ $updateSlides[2] = $this->buildSlideArrayHash(2, 'foo2', 'Title 2', 'Speaker notes 2', 'slide2.jpg', null, 'slide-alt2.jpg', null);
+ $newSlides = new ArrayHash();
+ $newSlides[0] = $this->buildSlideArrayHash(3, 'new1', 'New 1', 'New notes 1', null, new FileUpload(null), null, new FileUpload(null));
+ $newSlides[1] = $this->buildSlideArrayHash(4, 'new2', 'New 2', 'New notes 2', null, new FileUpload(null), null, new FileUpload(null));
$this->talkSlides->saveSlides(303, $slides, $updateSlides, $newSlides, false);
Assert::same(['slide1.jpg' => 0, 'slide-alt.jpg' => 1, 'slide2.jpg' => 0], PrivateProperty::getValue($this->talkSlides, 'otherSlides'));
$paramsUpdate = $this->database->getParamsArrayForQuery('UPDATE talk_slides SET ? WHERE id_slide = ?');