Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"require": {
"ext-curl": "*",
"ext-json": "*",
"neuron-php/mvc": "^0.9.5",
"neuron-php/mvc": "0.9.*",
"neuron-php/data": "0.9.*",
"neuron-php/cli": "0.8.*",
"neuron-php/jobs": "0.2.*",
"neuron-php/orm": "0.1.*",
Expand All @@ -21,7 +22,8 @@
},
"require-dev": {
"phpunit/phpunit": "9.*",
"mikey179/vfsstream": "^1.6"
"mikey179/vfsstream": "^1.6",
"neuron-php/scaffolding": "0.8.*"
},
"autoload": {
"psr-4": {
Expand All @@ -38,10 +40,5 @@
"psr-4": {
"Tests\\": "tests/"
}
},
"extra": {
"neuron": {
"cli-provider": "Neuron\\Cms\\Cli\\Provider"
}
}
}
2 changes: 1 addition & 1 deletion resources/app/Initializers/AuthInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function run( array $argv = [] ): mixed
// Get Settings from Registry
$settings = Registry::getInstance()->get( 'Settings' );

if( !$settings || !$settings instanceof \Neuron\Data\Setting\SettingManager )
if( !$settings || !$settings instanceof \Neuron\Data\Settings\SettingManager )
{
Log::error( "Settings not found in Registry, skipping auth initialization" );
return null;
Expand Down
2 changes: 1 addition & 1 deletion resources/app/Initializers/MaintenanceInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function run( array $argv = [] ): mixed
$config = null;
$settings = Registry::getInstance()->get( 'Settings' );

if( $settings && $settings instanceof \Neuron\Data\Setting\SettingManager )
if( $settings && $settings instanceof \Neuron\Data\Settings\SettingManager )
{
try
{
Expand Down
2 changes: 1 addition & 1 deletion resources/app/Initializers/PasswordResetInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use Neuron\Cms\Services\Auth\PasswordResetter;
use Neuron\Cms\Repositories\DatabasePasswordResetTokenRepository;
use Neuron\Cms\Repositories\DatabaseUserRepository;
use Neuron\Data\Setting\SettingManager;
use Neuron\Data\Settings\SettingManager;
use Neuron\Log\Log;
use Neuron\Patterns\Registry;
use Neuron\Patterns\IRunnable;
Expand Down
2 changes: 1 addition & 1 deletion resources/app/Initializers/RegistrationInitializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function run( array $argv = [] ): mixed
// Get Settings from Registry
$settings = Registry::getInstance()->get( 'Settings' );

if( !$settings || !$settings instanceof \Neuron\Data\Setting\SettingManager )
if( !$settings || !$settings instanceof \Neuron\Data\Settings\SettingManager )
{
Log::error( "Settings not found in Registry, skipping registration initialization" );
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

use Phinx\Migration\AbstractMigration;

/**
* Add content_raw column to posts table for Editor.js JSON storage
*/
class AddContentRawToPosts extends AbstractMigration
{
/**
* Add content_raw column
*/
public function change()
{
$table = $this->table( 'posts' );

$table->addColumn( 'content_raw', 'text', [
'null' => false,
'default' => '{"blocks":[]}',
'after' => 'body',
'comment' => 'Editor.js JSON content'
] )->update();
}
}
82 changes: 78 additions & 4 deletions resources/views/admin/posts/create.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<div class="card">
<div class="card-body">
<form method="POST" action="<?= route_path('admin_posts_store') ?>">
<form method="POST" action="<?= route_path('admin_posts_store') ?>" id="post-form">
<?= csrf_field() ?>

<div class="mb-3">
Expand All @@ -21,9 +21,12 @@
</div>

<div class="mb-3">
<label for="content" class="form-label">Content</label>
<textarea class="form-control" id="content" name="content" rows="15" required></textarea>
<small class="form-text text-muted">Markdown supported</small>
<label class="form-label">Content</label>
<div id="editorjs" style="border: 1px solid #ddd; border-radius: 0.25rem; padding: 20px; min-height: 400px; background: #fff;"></div>
<input type="hidden" name="content" id="content-json">
<small class="form-text text-muted">
Use shortcodes for dynamic content: <code>[latest-posts limit="5"]</code>
</small>
</div>

<div class="mb-3">
Expand Down Expand Up @@ -67,3 +70,74 @@
</div>
</div>
</div>

<!-- Load Editor.js -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/code@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/raw@latest"></script>
Comment on lines +75 to +82
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Pin CDN script versions instead of using @latest.

Using @latest for CDN dependencies can lead to breaking changes being introduced automatically when new versions are released, potentially causing production issues without warning.

Replace the @latest tags with specific version numbers:

-<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
-<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script>
-<script src="https://cdn.jsdelivr.net/npm/@editorjs/list@latest"></script>
-<script src="https://cdn.jsdelivr.net/npm/@editorjs/image@latest"></script>
-<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote@latest"></script>
-<script src="https://cdn.jsdelivr.net/npm/@editorjs/code@latest"></script>
-<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter@latest"></script>
-<script src="https://cdn.jsdelivr.net/npm/@editorjs/raw@latest"></script>
+<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@2.28.0"></script>
+<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@2.7.0"></script>
+<script src="https://cdn.jsdelivr.net/npm/@editorjs/list@1.8.0"></script>
+<script src="https://cdn.jsdelivr.net/npm/@editorjs/image@2.8.1"></script>
+<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote@2.5.0"></script>
+<script src="https://cdn.jsdelivr.net/npm/@editorjs/code@2.8.0"></script>
+<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter@1.3.0"></script>
+<script src="https://cdn.jsdelivr.net/npm/@editorjs/raw@2.4.0"></script>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/code@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/raw@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@2.28.0"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@2.7.0"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list@1.8.0"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image@2.8.1"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote@2.5.0"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/code@2.8.0"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter@1.3.0"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/raw@2.4.0"></script>
🤖 Prompt for AI Agents
In resources/views/admin/posts/create.php around lines 75 to 82, the CDN script
tags use @latest which risks unplanned breaking changes; replace each @latest
with a specific, tested semantic version (e.g., exact x.y.z values) for
Editor.js and its plugins, update any README or asset notes to record chosen
versions, and consider adding subresource integrity or locking via a package
manager/build tool so future updates are explicit and audited.


<script>
const editor = new EditorJS({
holder: 'editorjs',

placeholder: 'Start writing your post content...',

tools: {
header: {
class: Header,
config: {
levels: [2, 3, 4],
defaultLevel: 2
}
},
list: {
class: List,
inlineToolbar: true
},
image: {
class: ImageTool,
config: {
endpoints: {
byFile: '/admin/upload/image'
}
}
},
quote: {
class: Quote,
inlineToolbar: true
},
code: CodeTool,
delimiter: Delimiter,
raw: {
class: RawTool,
config: {
placeholder: 'Enter HTML or shortcodes like [latest-posts limit="5"]'
}
}
},

onChange: async () => {
const savedData = await editor.save();
document.getElementById('content-json').value = JSON.stringify(savedData);
}
});

// Save content before submit
document.getElementById('post-form').addEventListener('submit', async (e) => {
e.preventDefault();

try {
const savedData = await editor.save();
document.getElementById('content-json').value = JSON.stringify(savedData);
e.target.submit();
} catch (error) {
console.error('Error saving editor content:', error);
alert('Error preparing content. Please try again.');
}
});
</script>
95 changes: 91 additions & 4 deletions resources/views/admin/posts/edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<div class="card">
<div class="card-body">
<form method="POST" action="<?= route_path('admin_posts_update', ['id' => $post->getId()]) ?>">
<form method="POST" action="<?= route_path('admin_posts_update', ['id' => $post->getId()]) ?>" id="post-form">
<input type="hidden" name="_method" value="PUT">
<?= csrf_field() ?>

Expand All @@ -22,9 +22,12 @@
</div>

<div class="mb-3">
<label for="content" class="form-label">Content</label>
<textarea class="form-control" id="content" name="content" rows="15" required><?= htmlspecialchars( $post->getBody() ) ?></textarea>
<small class="form-text text-muted">Markdown supported</small>
<label class="form-label">Content</label>
<div id="editorjs" style="border: 1px solid #ddd; border-radius: 0.25rem; padding: 20px; min-height: 400px; background: #fff;"></div>
<input type="hidden" name="content" id="content-json">
<small class="form-text text-muted">
Use shortcodes for dynamic content: <code>[latest-posts limit="5"]</code>
</small>
</div>

<div class="mb-3">
Expand Down Expand Up @@ -75,3 +78,87 @@
</div>
</div>
</div>

<!-- Load Editor.js -->
<script src="https://cdn.jsdelivr.net/npm/@editorjs/editorjs@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/header@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/list@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/image@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/quote@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/code@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/delimiter@latest"></script>
<script src="https://cdn.jsdelivr.net/npm/@editorjs/raw@latest"></script>

<script>
// Load existing content safely
const existingContentJson = <?= json_encode($post->getContentRaw(), JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;

let existingContent;
try {
existingContent = JSON.parse(existingContentJson);
} catch (error) {
console.error('Failed to parse existing content:', error);
existingContent = { blocks: [] };
}

const editor = new EditorJS({
holder: 'editorjs',

data: existingContent,

placeholder: 'Start writing your post content...',

tools: {
header: {
class: Header,
config: {
levels: [2, 3, 4],
defaultLevel: 2
}
},
list: {
class: List,
inlineToolbar: true
},
image: {
class: ImageTool,
config: {
endpoints: {
byFile: '/admin/upload/image'
}
}
},
quote: {
class: Quote,
inlineToolbar: true
},
code: CodeTool,
delimiter: Delimiter,
raw: {
class: RawTool,
config: {
placeholder: 'Enter HTML or shortcodes like [latest-posts limit="5"]'
}
}
},

onChange: async () => {
const savedData = await editor.save();
document.getElementById('content-json').value = JSON.stringify(savedData);
}
});

// Save content before submit
document.getElementById('post-form').addEventListener('submit', async (e) => {
e.preventDefault();

try {
const savedData = await editor.save();
document.getElementById('content-json').value = JSON.stringify(savedData);
e.target.submit();
} catch (error) {
console.error('Error saving editor content:', error);
alert('Error preparing content. Please try again.');
}
});
</script>
Loading