Gabriyel Goede 1 month ago
parent
commit
2a18d3490b

+ 1 - 1
composer.json

@@ -10,7 +10,7 @@
 		"n2n/n2n-context" : "^7.5",
 		"n2n/n2n-impl-persistence-meta" : "^7.5",
 		"n2n/n2n-impl-persistence-orm" : "^7.5",
-		"n2n/rocket" : "^3.0",
+		"n2n/rocket" : "^4.1",
 		"lcobucci/jwt" : "4.0.4",
 		"n2n/n2n-bind": "^7.5"
     },

+ 32 - 28
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "daf0a259f2427c028366d53e401ff745",
+    "content-hash": "01d4ab84eee26086359928384faf044d",
     "packages": [
         {
             "name": "lcobucci/clock",
@@ -1631,32 +1631,36 @@
         },
         {
             "name": "n2n/rocket",
-            "version": "3.0.x-dev",
+            "version": "4.1.x-dev",
             "source": {
                 "type": "git",
                 "url": "https://github.com/n2n/rocket.git",
-                "reference": "e4830150f8e448f7bc2c8ca65d3c837b569fa55c"
+                "reference": "c74f12e5c540e9d3859e461e8e54497a4334b2ff"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/n2n/rocket/zipball/e4830150f8e448f7bc2c8ca65d3c837b569fa55c",
-                "reference": "e4830150f8e448f7bc2c8ca65d3c837b569fa55c",
+                "url": "https://api.github.com/repos/n2n/rocket/zipball/c74f12e5c540e9d3859e461e8e54497a4334b2ff",
+                "reference": "c74f12e5c540e9d3859e461e8e54497a4334b2ff",
                 "shasum": ""
             },
             "require": {
-                "n2n/n2n": "^7.3",
-                "n2n/n2n-batch": "^7.3",
-                "n2n/n2n-composer-module-installer": "^7.1.3",
-                "n2n/n2n-context": "^7.3",
-                "n2n/n2n-impl-persistence-meta": "^7.3",
-                "n2n/n2n-impl-persistence-orm": "^7.3",
-                "n2n/n2n-impl-web-dispatch": "^7.3",
-                "n2n/n2n-impl-web-ui": "^7.3",
-                "n2n/n2n-validation": "^7.3",
-                "php": ">=8.0"
+                "ext-mbstring": "*",
+                "ext-xml": "*",
+                "n2n/n2n": "^7.5",
+                "n2n/n2n-bind": "^7.5",
+                "n2n/n2n-composer-module-installer": "^7.1.6",
+                "n2n/n2n-impl-persistence-meta": "^7.5",
+                "n2n/n2n-impl-persistence-orm": "^7.5",
+                "n2n/n2n-impl-web-dispatch": "^7.5",
+                "n2n/n2n-impl-web-ui": "^7.5",
+                "n2n/n2n-persistence": "^7.5",
+                "n2n/n2n-reflection": "^7.5",
+                "n2n/n2n-util": "^7.5",
+                "n2n/n2n-validation": "^7.5"
             },
             "require-dev": {
-                "phpunit/phpunit": "^9.5"
+                "n2n/n2n-test": "~7.4.0",
+                "phpunit/phpunit": "^9.6.29"
             },
             "type": "n2n-module",
             "autoload": {
@@ -1695,9 +1699,9 @@
             ],
             "support": {
                 "issues": "https://github.com/n2n/rocket/issues",
-                "source": "https://github.com/n2n/rocket/tree/3.0.x"
+                "source": "https://github.com/n2n/rocket/tree/4.1.x"
             },
-            "time": "2025-08-18T08:56:07+00:00"
+            "time": "2026-09-03T06:13:13+00:00"
         },
         {
             "name": "psr/cache",
@@ -2461,12 +2465,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/nikic/PHP-Parser.git",
-                "reference": "5d907dc3c30e379b9168436286e9a2c2f699a2dd"
+                "reference": "93411bf09b25bff03a555cbe64cd25cd20e4b966"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/5d907dc3c30e379b9168436286e9a2c2f699a2dd",
-                "reference": "5d907dc3c30e379b9168436286e9a2c2f699a2dd",
+                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/93411bf09b25bff03a555cbe64cd25cd20e4b966",
+                "reference": "93411bf09b25bff03a555cbe64cd25cd20e4b966",
                 "shasum": ""
             },
             "require": {
@@ -2511,7 +2515,7 @@
                 "issues": "https://github.com/nikic/PHP-Parser/issues",
                 "source": "https://github.com/nikic/PHP-Parser/tree/master"
             },
-            "time": "2026-09-14T18:33:13+00:00"
+            "time": "2026-09-28T19:31:45+00:00"
         },
         {
             "name": "phar-io/manifest",
@@ -2953,16 +2957,16 @@
         },
         {
             "name": "phpunit/phpunit",
-            "version": "9.6.36",
+            "version": "9.6.37",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "abab27ed286d3e1246fbbfe6b56bfd732d945ec9"
+                "reference": "aceaa623912caf8e80bffea22fc4103a0a01565f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/abab27ed286d3e1246fbbfe6b56bfd732d945ec9",
-                "reference": "abab27ed286d3e1246fbbfe6b56bfd732d945ec9",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/aceaa623912caf8e80bffea22fc4103a0a01565f",
+                "reference": "aceaa623912caf8e80bffea22fc4103a0a01565f",
                 "shasum": ""
             },
             "require": {
@@ -3036,7 +3040,7 @@
             "support": {
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
                 "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
-                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.36"
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.37"
             },
             "funding": [
                 {
@@ -3044,7 +3048,7 @@
                     "type": "other"
                 }
             ],
-            "time": "2026-08-11T06:25:15+00:00"
+            "time": "2026-09-23T09:59:59+00:00"
         },
         {
             "name": "sebastian/cli-parser",

File diff suppressed because it is too large
+ 0 - 0
src-php/.phpunit.result.cache


+ 67 - 5
src-php/app/internship/controller/ArticleApiController.php

@@ -7,6 +7,7 @@ use n2n\context\attribute\Inject;
 use n2n\web\http\controller\ParamBody;
 use internship\bo\Article;
 use n2n\validation\plan\ErrorMap;
+use n2n\web\http\BadRequestException;
 use n2n\web\http\PageNotFoundException;
 
 /**
@@ -50,6 +51,13 @@ class ArticleApiController extends ControllerAdapter {
 	 */
 	function getDoArticle(int $articleId): void {
 		$article = $this->articleDao->getArticleById($articleId);
+		if($article === null) {
+			throw new PageNotFoundException('Article not found with ID:' . $articleId);
+		}
+		if($article->getId() === 2) {
+			throw new PageNotFoundException('Article is Secret:' . $articleId);
+		}
+
 		$this->sendJson($article);
 	}
 
@@ -75,9 +83,16 @@ class ArticleApiController extends ControllerAdapter {
 	function getDoArticles(?string $categoryName = null): void {
 		if($categoryName === null) {
 			$articles = $this->articleDao->getArticles();
+			if($articles === []) {
+				throw new PageNotFoundException('No articles found');
+			}
 		} else { 
 			$articles = $this->articleDao->getArticlesByCategoryName($categoryName);
-		} 
+			if($articles === []) {
+				throw new PageNotFoundException('Category ' . $categoryName . ' not found');
+			}
+		}
+
 		$this->sendJson($articles);
 	}
 
@@ -97,12 +112,35 @@ class ArticleApiController extends ControllerAdapter {
 	 * 	 </li>
 	 * </ul>
 	 *
-	 * Nenne die Methode {@see saveArticle(Article $article)}
+	 * Nenne die Methode {@see saveArticle(Aŋ@rticle $article)}
 	 *
 	 * @return void
 	 */
 	function postDoArticle(ParamBody $body): void {
-		$body->parseJson();
+		if(!$body === null) {
+		$zwivar1 = $body->parseJson();
+		} else {
+			throw new BadRequestException('Body cant be empty');
+		}
+		$this->beginTransaction();
+			if(!in_array($zwivar1['categoryName'],['sport','international','national'])) {
+				throw new BadRequestException('The Category must be international, national or sport');
+			}
+			if(!isset($zwivar1['title'])) {
+				throw new BadRequestException('Title must be set');
+			}
+			if(!isset($zwivar1['text'])) {
+				throw new BadRequestException('Article must contain a text');
+			}
+			
+		$article = new Article();
+		$article->setTitle($zwivar1['title']);
+		$article->setText($zwivar1['text']);
+		$article->setCategoryName($zwivar1['categoryName']);
+		$this->articleDao->saveArticle($article);
+ 
+    	$this->commit();
+		$this->sendJson($article);
 	}
 
 	/**
@@ -124,7 +162,29 @@ class ArticleApiController extends ControllerAdapter {
 	 * @return void
 	 */
 	function putDoArticle(int $articleId, ParamBody $body): void {
-
+		$this->beginTransaction();
+		$article = $this->articleDao->getArticleById($articleId);
+		if($article === null) {
+			throw new PageNotFoundException('Article not found');
+		}
+		$zwivar1 = $body->parseJson();
+		if(isset($zwivar1['categoryName'])) {
+			if(!in_array($zwivar1['categoryName'],['sport','international','national'])) {
+				throw new BadRequestException('The Category must be international, national or sport');
+			}
+			
+		
+			$article->setCategoryName($zwivar1['categoryName']);
+		}
+		if(isset($zwivar1['text'])) {
+			$article->setText($zwivar1['text']);
+		}
+		if(isset($zwivar1['title'])) {
+			$article->setTitle($zwivar1['title']);
+		}
+		$this->articleDao->saveArticle($article);
+		$this->commit();
+		$this->sendJson($article);
 	}
 
 	/**
@@ -137,6 +197,8 @@ class ArticleApiController extends ControllerAdapter {
 	 * @return void
 	 */
 	function deleteDoArticle(int $articleId): void {
-
+		$this->beginTransaction();
+		$this->articleDao->removeArticle($articleId);
+		$this->commit();
 	}
 }

+ 10 - 3
src-php/app/internship/model/ArticleDao.php

@@ -27,7 +27,7 @@ class ArticleDao {
 	 * @return Article[]
 	 */
 	function getArticles(): array {
-		$criteria = $this->em->createSimpleCriteria(Article::getClass());
+		$criteria = $this->em->createSimpleCriteria(Article::getClass(), order: ['id' => 'DESC']);
 		return $criteria->toQuery()->fetchArray();
 
 	}
@@ -38,7 +38,7 @@ class ArticleDao {
 	 * @return array
 	 */
 	function getArticlesByCategoryName(string $categoryName): array {
-		$criteria = $this->em->createSimpleCriteria(Article::getClass(), ['categoryName' => $categoryName ]);
+		$criteria = $this->em->createSimpleCriteria(Article::getClass(), ['categoryName' => $categoryName ], order: ['id' => 'DESC']);
 		return $criteria->toQuery()->fetchArray();
 	}
 
@@ -53,9 +53,16 @@ class ArticleDao {
 
 		$criteria = $this->em->createSimpleCriteria(Article::getClass(),['id'=> $id]);
 		return $criteria->toQuery()->fetchSingle();
-
+	}
+	
+	function saveArticle(Article $article) {
+		$this->em->persist($article);
 	}
 
+	function removeArticle(int $id ) {
+		$article = $this->em->find(Article::getClass(), $id);
+		$this->em->remove($article);
+	}
 	//function getArticleRowById(int $id): array {
 	//	$this->pdo->prepare('SELECT...'),
 	//}

+ 10 - 0
src-php/huii.sql

@@ -0,0 +1,10 @@
+-- Mysql Backup of internship-playground
+-- Date 2023-05-01T12:38:25+02:00
+-- Backup by nikolai
+DROP TABLE IF EXISTS `article`;
+CREATE TABLE `article` (
+        `id` INTEGER PRIMARY KEY AUTOINCREMENT,
+        `category_name` VARCHAR(255) NOT NULL ,
+        `title` VARCHAR(255) NOT NULL ,
+        `text` TEXT NOT NULL
+) ;

+ 2 - 1
src-php/test/bootstrap.php

@@ -3,6 +3,7 @@ use n2n\core\N2N;
 use n2n\core\FileN2nCache;
 use n2n\io\IoUtils;
 use n2n\core\TypeLoader;
+use n2n\persistence\ext\PdoPool;
 
 ini_set('display_errors', 1);
 error_reporting(E_ALL);
@@ -40,4 +41,4 @@ $sql = preg_replace("/[\r\n]+/", "\n", $sql);
 $sql = str_replace('UNSIGNED ', '', $sql);
 file_put_contents('huii.sql', $sql);
 
-N2N::getPdoPool()->getPdo()->exec($sql);
+N2N::getN2nContext()->lookup(PdoPool::class)->getPdo()->exec($sql);

+ 199 - 8
src-php/test/internship/controller/ArticleControllerTest.php

@@ -6,7 +6,9 @@ use PHPUnit\Framework\TestCase;
 use n2n\test\TestEnv;
 use internship\test\ArticleTestEnv;
 use util\GeneralTestEnv;
-
+use n2n\web\http\PageNotFoundException;
+use internship\bo\Article;
+use n2n\web\http\BadRequestException;
 
 class ArticleControllerTest extends TestCase {
 
@@ -18,8 +20,8 @@ class ArticleControllerTest extends TestCase {
 		GeneralTestEnv::tearDown();
 
 		$tx = TestEnv::createTransaction();
-		$article1 = ArticleTestEnv::setUpArticle('Title 1', 'Loren ipsum 1', 'teaser');
-		$article2 = ArticleTestEnv::setUpArticle('Title 2', 'Loren ipsum 2', 'news');
+		$article1 = ArticleTestEnv::setUpArticle('Title 1', 'Loren ipsum 1', 'news');
+		$article2 = ArticleTestEnv::setUpArticle('Title 2', 'Loren ipsum 2', 'teaser');
 		$article3 = ArticleTestEnv::setUpArticle('Title 3', 'Loren ipsum 3', 'news');
 		$tx->commit();
 
@@ -33,12 +35,201 @@ class ArticleControllerTest extends TestCase {
 				->get(['api', 'articles'])
 				->exec();
 
-		$articleStructs = $response->parseJson();
-		$this->assertCount(3, $articleStructs);
+		$articleStruct = $response->parseJson();
+		$this->assertCount(3, $articleStruct);
+
+		$this->assertEquals('Title 3', $articleStruct[0]['title']);
+		$this->assertEquals('Title 2', $articleStruct[1]['title']);
+		$this->assertEquals('Title 1', $articleStruct[2]['title']);
+	}
+
+	function testGetDoArticlesWithCategory() {
+		$response = TestEnv::http()->newRequest()
+				->get(['api', 'articles', 'teaser'])
+				->exec();
+
+		$articleStruct = $response->parseJson();
+		$this->assertCount(1, $articleStruct);
+
+		$this->assertEquals('Title 2', $articleStruct[0]['title']);
+	}
+
+	function testGetDoArticlesWithCategory2() {
+		$response = TestEnv::http()->newRequest()
+				->get(['api', 'articles', 'news'])
+				->exec();
+
+		$articleStruct = $response->parseJson();
+		$this->assertCount(2, $articleStruct);
+
+		$this->assertEquals('Title 3', $articleStruct[0]['title']);
+		$this->assertEquals('Title 1', $articleStruct[1]['title']);
+	}
+
+	function testGetDoArticlesExpectExceptionBecauseCategoryNotFound() {
+		$this->expectException(PageNotFoundException::class);
+		$this->expectExceptionMessage('Category abc not found');
+		TestEnv::http()->newRequest()
+				->get(['api', 'articles', 'abc'])
+				->exec();
+
+	}
+	
+	function testGetDoArticle() {
+		$response = TestEnv::http()->newRequest()
+				->get(['api', 'article', $this->article1Id])
+				->exec();
+
+		$articleStruct = $response->parseJson();
+		$this->assertCount(4, $articleStruct);
 
-		$this->assertEquals('Title 3', $articleStructs[0]['title']);
-		$this->assertEquals('Title 2', $articleStructs[1]['title']);
-		$this->assertEquals('Title 1', $articleStructs[2]['title']);
+		$this->assertEquals('Title 1', $articleStruct['title']);
+		$this->assertEquals('Loren ipsum 1', $articleStruct['text']);
+		$this->assertEquals('news', $articleStruct['categoryName']);
+
+	}
+
+	function testGetDoArticleExpectExceptionBecauseArticleNotFound() {
+		$this->expectException(PageNotFoundException::class);
+		$this->expectExceptionMessage('Article not found with ID:25436857');
+		TestEnv::http()->newRequest()
+				->get(['api', 'article', 25436857])
+				->exec();
+
+
+
+
+	}
+
+	function testPostDoArticle() {
+		$response = TestEnv::http()->newRequest()
+				->post(['api', 'article'])
+				->bodyJson([
+            		'title' => 'title1',
+            		'categoryName' => 'sport',
+            		'text' => 'text1'
+       			])
+				->exec();
+		$articleStruct = $response->parseJson();
+		$this->assertEquals(4,TestEnv::emUtil()->count(Article::class));
+		$this->assertCount(4, $articleStruct);
+
+		$this->assertEquals('title1', $articleStruct['title']);
+		$this->assertEquals('text1', $articleStruct['text']);
+		$this->assertEquals('sport', $articleStruct['categoryName']);
+	}
+
+	function testPostDoArticleExpectExceptionBecauseCategoryNotFound() {
+		$this->expectException(BadRequestException::class);
+		$this->expectExceptionMessage('The Category must be international, national or sport');
+		TestEnv::http()->newRequest()
+				->post(['api', 'article'])
+				->bodyJson([
+            		'title' => 'title1',
+            		'categoryName' => 'abc',
+            		'text' => 'text1'
+       			])
+				->exec();
+	}
+
+	function testPutDoArticle() {
+		$response = TestEnv::http()->newRequest()
+				->put(['api', 'article',$this->article1Id])
+				->bodyJson([
+            		'title' => 'title1',
+            		'categoryName' => 'sport',
+            		'text' => 'text1'
+       			])
+				->exec();
+		$articleStruct = $response->parseJson();
+		$this->assertCount(4, $articleStruct);
+		$this->assertEquals('title1', $articleStruct['title']);
+		$this->assertEquals('text1', $articleStruct['text']);
+		$this->assertEquals('sport', $articleStruct['categoryName']);
+	}
+	
+	function testPutDoArticle1() {
+		$response = TestEnv::http()->newRequest()
+				->put(['api', 'article',$this->article1Id])
+				->bodyJson([
+            		'title' => 'title1',
+       			])
+				->exec();
+		$articleStruct = $response->parseJson();
+		$this->assertCount(4, $articleStruct);
+		$this->assertEquals('title1', $articleStruct['title']);
+		$this->assertEquals('Loren ipsum 1', $articleStruct['text']);
+		$this->assertEquals('news', $articleStruct['categoryName']);
+
+	}
+
+	function testPutDoArticle2() {
+		$response = TestEnv::http()->newRequest()
+				->put(['api', 'article',$this->article1Id])
+				->bodyJson([
+            		'categoryName' => 'sport',
+       			])
+				->exec();
+		$articleStruct = $response->parseJson();
+		$this->assertCount(4, $articleStruct);
+		$this->assertEquals('Title 1', $articleStruct['title']);
+		$this->assertEquals('Loren ipsum 1', $articleStruct['text']);
+		$this->assertEquals('sport', $articleStruct['categoryName']);
+
+	}
+
+	function testPutDoArticle3() {
+		$response = TestEnv::http()->newRequest()
+				->put(['api', 'article',$this->article1Id])
+				->bodyJson([
+            		'text' => 'text1',
+       			])
+				->exec();
+		$articleStruct = $response->parseJson();
+		$this->assertCount(4, $articleStruct);
+		$this->assertEquals('Title 1', $articleStruct['title']);
+		$this->assertEquals('text1', $articleStruct['text']);
+		$this->assertEquals('news', $articleStruct['categoryName']);
+
+	}
+
+	function testPutDoArticleExpectExceptionBecauseCategoryNotFound() {
+		$this->expectException(BadRequestException::class);
+		$this->expectExceptionMessage('The Category must be international, national or sport');
+		TestEnv::http()->newRequest()
+				->put(['api', 'article',$this->article1Id])
+				->bodyJson([
+            		'title' => 'title1',
+            		'categoryName' => 'abc',
+            		'text' => 'text1'
+       			])
+				->exec();
+	}	
+	
+	function testPutDoArticleExpectExceptionBecauseArticleNotFound() {
+		$this->expectException(PageNotFoundException::class);
+		$this->expectExceptionMessage('Article not found');
+		TestEnv::http()->newRequest()
+				->put(['api', 'article', 25436857])
+				->bodyJson([
+            		'title' => 'title1',
+            		'categoryName' => 'abc',
+            		'text' => 'text1'
+       			])
+				->exec();
+
+
+
+
+	}
+
+	function testDeleteDoArticle() {
+		$response = TestEnv::http()->newRequest()
+			->delete(['api', 'article',$this->article1Id])
+			->exec();
+			$tx = TestEnv::createTransaction();
+			$this->assertEquals(2,TestEnv::temUtil()->count(Article::class));
+			$tx->commit();
 	}
 
 }

Some files were not shown because too many files changed in this diff