riclep / laravel-storyblok Goto Github PK
View Code? Open in Web Editor NEWMake Laravel and Storyblok work together beautifully.
Home Page: https://ls.sirric.co.uk/
License: MIT License
Make Laravel and Storyblok work together beautifully.
Home Page: https://ls.sirric.co.uk/
License: MIT License
Hey, again thanks for the nice package!
Storyblok allows to insert components within the RichText field [1]. But from what i understood the provided storyblok/richtext-resolver for PHP does not handle them. Anyways, i needed to render inline components and came up with the following code. Maybe its a common enough use-case to be added to the core of this package.
I found no way to overwrite the existing RichText Field Class, so i added a Custom Field and named it accordingly in Storyblok. Maybe it would be nice if one could also overwrite the built-in fields to apply changes globally based on the field type vs the field name.
<?php
namespace App\Storyblok\Fields;
use Riclep\Storyblok\Fields\RichText as BaseRichText;
use Storyblok\RichtextRender\Resolver;
use Riclep\Storyblok\Block;
class Richtextfield extends BaseRichText
{
/**
* Converts the data to HTML when printed
*
* @return string
*/
public function __toString()
{
$richtextResolver = new Resolver();
$out = "";
// Loop through all nodes from the RichText Field
// Either Render them normally
// Or if type is 'blok' create a block an add the rendered content to ouput
foreach ($this->content['content'] as $node) {
if ($node['type'] == 'blok' && isset($node['attrs']['body']) && is_array($node['attrs']['body'])){
foreach ($node['attrs']['body'] as $blockContent) {
$block = new Block($blockContent, $this->block()->parent());
$out .= $block->render();
}
} else {
$out .= $richtextResolver->render(["content" => [$node]]);
}
}
return $out;
// Original
// return $richtextResolver->render($this->content);
}
}
[1] https://www.storyblok.com/docs/richtext-field#components-inside-the-richtext-field
Hello there 👋 .
We seem to be encountering a bug in one of the recent updates of your package. We upgraded from 2.15.0
to 2.19.2
and parsing of multi-option fields is no longer working.
After doing a bit more research the bug seems to have been introduced in 2.17.0
.
self
{
"story": {
"content": {
"_uid": "1515771c-3ec4-4922-8921-9607eda522e6",
"body": [
{
"_uid": "29914472-2a98-428d-868c-56c30207d608",
"component": "test-component",
"test_field": [
"20",
"10",
"30"
],
}
]
}
}
}
I expect in the component TestComponent
to have access to a field called test_field
that would be an array.
When accessing test_field
, null
is returned.
Hey there 👋 .
This is more of a question than a feature request or bug ticket.
Let's say you have a block that you are going to serialize (via json_encode or the like). This package uses the magic __get()
function to get attributes out of the private $fields
array behind the scenes, so the JSON encoded object only has a few public properties (resolve relations and whatnot).
Is there a native way to get the full class serialized with all of the Storyblok attributes included? If there isn't, would that be something you want this package to handle?
A lot of times we are using Storyblok to render our data, but then there are some frontend manipulations that we want to do as well. To accomplish our goals, sometimes we need to encode the Storyblok object into javascript to be used on the client.
If I use the laravel @json
directive on any component, the output will look similar to this:
{"_autoResolveRelations":false,"_resolveRelations":[],"_filterRelations":true,"_componentPath":["page","page","full-section","button"]}
But if I @dd
that same instance, I get something like this:
App\Storyblok\Blocks\Button {[#1588 ▼]
+_autoResolveRelations: false
+_resolveRelations: []
+_filterRelations: true
+_componentPath: array:4 [[▶]()]
#_casts: []
-_fields: Illuminate\Support\Collection {[#1589 ▼]()
#items: array:15 [[▼]()
"url" => Riclep\Storyblok\Fields\UrlLink {[#1592 ▶]()}
"size" => "normal"
"text" => "Rawr"
]
#escapeWhenCastingToString: false
// other attributes
}
}
Notice that the component has data like size
and text
in it, but it doesn't show up in the serialized instance.
Looks like the latest version broke something in the editor-bridge. I see a function called flatten
was removed, but not seeing any obvious references.
Error
Call to undefined method App\Storyblok\Block::flatten() (View: /.../projectname/vendor/riclep/laravel-storyblok/src/resources/views/editor-bridge.blade.php)
Thanks for the awesome library.
Referring to line: https://github.com/RicLeP/laravel-storyblok/blob/master/src/Folder.php#L165
If we have the following two pages we get the same results back, the second from the cache.
// example.org/some-content?page=1
$requestSomeContent = new Folder();
$requestSomeContent->slug('some-content');
$requestSomeContent->perPage(10);
$requestSomeContent->settings([
'is_startpage' => false,
'filter_query' => [],
]);
// yields cache key:
// folder-some-content-4893ccccb8f122d63a21febbbb000000
// example.org/some-content?page=2
$requestSomeContent = new Folder();
$requestSomeContent->slug('some-content');
$requestSomeContent->perPage(10);
$requestSomeContent->settings([
'is_startpage' => false,
'filter_query' => [],
]);
// yields cache key:
// folder-some-content-4893ccccb8f122d63a21febbbb000000
Note on the second request (page=2), the cache key constructed doesn't account for the current page which gives it the same key, meaning we get the cached data back.
I believe the cache key should include $page
in the cache key if set.
If I disable the cache (STORYBLOK_CACHE=false
) it works as expected.
Looking through telescope I can confirm the cache keys aren't accounting for $page.
Hi @RicLeP, I was wondering how you'd deal with paginating through the StoryBlok API when there's more than 100 articles in a 'collection'.
E.G. my client has a blog with several hundred articles - I couldn't see a process for iterating through all of the blog posts - just the first 100.
A bit of an edge case here, but I've got a StoryBlok instance where we imported thousands of articles into the system, and we have a ton of broken images.
The client's gradually going through and fixing them, but we've gone live anyway - so there's a lot of older pages that just error out when we use $image->transform()
.
My current method of detecting if an image exists or not is to do a check on $story->image->filename
.
However with broken images imported into Storyblok, there's still a filename (which is helping my client to figure out which images need to be added back in).
I could probably do a check on the $image->copyright
or $image->alt
fields - these are null on broken images, and if not utilised are empty.
But I thought it might be a better option to be able to check the transformer for the extension type - which will return null on these images.
As I said, very much an edge case, but I'd be interested to hear your thoughts on a solve.
When generating new components that have no items in the schema, the command errors out.
php artisan ls:block EmptyComponent
I expect a class representation of the component, but with no available attributes listed.
Command errors out with the following stack:
ErrorException
Trying to access array offset on value of type null
at vendor/riclep/laravel-storyblok/src/Console/BlockSyncCommand.php:154
150▕
151▕ $component = $components->firstWhere('name', $name);
152▕
153▕ $fields = [];
➜ 154▕ foreach ($component['schema'] as $name => $data) {
155▕ if ( ! $this->isIgnoredType($data['type'])) {
156▕ $fields[$name] = $this->convertToPhpType($data['type']);
157▕ }
158▕ }
+29 vendor frames
30 artisan:37
Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
Hey there, thanks for the package!
While following the documentation about Blocks i ran into an issue with my blocks not being rendered properly.
php artisan ls:block MyComponent -b
Creates a template in ressources/views/storyblok/components/my-component.blade.php.
This will not be found by the Block Class automatically. It expects the templates to reside in ressources/views/storyblok/blocks/ see
laravel-storyblok/src/Block.php
Line 142 in aa7412b
Once i renamed the folder the template gets used.
It appears that there is an issue when using the console commands that are using the replace
method on files where it will actually update file permissions unnecessarily.
php artisan ls:block <component>
php artisan ls:sync
The new field will show up as a property for that block's class. File permissions should remain 644 (rw, r, r).
The new field will show up as a property for that block's class. File permissions are updated to 755 (rwx, rx, rx).
In a clean Laravel project if I try to install laravel-storyblok
package i receive an error:
Storyblok\BaseClient::setApiKey(): Argument #1 ($apiKey) must be of type string, null given, called in /Users/roberto/Sites/composable-example/vendor/storyblok/php-client/src/Storyblok/BaseClient.php on line 81
I think this issue could be solved by setting the default as an empty string in the config/storyblok.php:
'api_public_key' => env('STORYBLOK_PUBLIC_API_KEY', ''),
Instead of:
'api_public_key' => env('STORYBLOK_PUBLIC_API_KEY'),
https://ls.sirric.co.uk/docs/2.4/folders
seems out of date. e.g. class DefaultFolder does not exist
Hey Richard!
We have a global reference that we want to resolve. Is there a workflow to handle this?
For more information you can read here:
https://www.storyblok.com/tp/global-components-references
Have a nice weekend!
Looks like a recent change to the generator command stub changed the variable in the blade file from $content
to $block
. Now when generating a fresh block with the latest version of the library, you get this error:
Undefined variable: block (View: /projects/www.bankrate.com/resources/views/storyblok/blocks/teaser.blade.php)
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
composer.json
php ^8.1|^8.2|^8.3
barryvdh/reflection-docblock ^2.0
embed/embed ^3.4|^4
illuminate/support ^9.0|^10.0|^11.0
imgix/imgix-php ^3.3|^4.0
ivopetkov/html5-dom-document-php 2.*
league/commonmark ^2.0
spatie/laravel-ignition ^2.8
spatie/schema-org ^3.3
storyblok/php-client ^2.3
storyblok/richtext-resolver ^2.2
mockery/mockery ^1.2
orchestra/testbench ^8.0|^9.0
phpunit/phpunit ^10
.github/workflows/tests.yml
actions/checkout v3
php-actions/composer v6
php-actions/phpunit v3
This is almost certainly down to a lack of experience with Laravel, but I'm having trouble getting started.
I've got a StoryBlok space setup with a ton of content imported into it.
I've got laravel and laravel-storyblok installed, and serving on localhost.
Environment variables are set, and by the errors I'm getting, it's definitely trying to hit the storyblok API. I've got the catch-all router in place.
I've gone back to basics, created the file /resources/views/storyblok/pages/page.blade.php which looks like this:
<main>
<header>
<h1>@{{ $story->title }}</h1>
</header>
<section>
<?php dd($story); ?>
</section>
</main>
I've created a page called 'test' at the root of Storyblok, using the 'page' component, which has two fields defined - title and text.
But the @{{ $story->title }} just displays {{ $story->title}} in the browser.
The dd does give me a result:
App\Storyblok\Page {#1180 ▼
+_componentPath: array:1 [▶]
-block: App\Storyblok\Block {#1090 ▶}
-story: array:22 [▼
"name" => "test"
"created_at" => "2021-11-17T10:41:40.966Z"
"published_at" => "2021-11-17T10:42:25.116Z"
"alternates" => []
"id" => 86019624
"uuid" => "761d11ac-c8bd-4eee-ae1f-6e3dbdc920bf"
"content" => array:4 [▼
"_uid" => "fbb0f60a-3c57-456e-84c3-8b86f02aeae0"
"body" => array:1 [▼
0 => array:4 [▼
"_uid" => "62cd6c66-4d78-4ee5-af0f-e17b231fabda"
"title" => "My big test"
"component" => "text"
"_editable" => "<!--#storyblok#{"name": "text", "space": "127485", "uid": "62cd6c66-4d78-4ee5-af0f-e17b231fabda", "id": "86019624"}-->"
]
]
"component" => "page"
"_editable" => "<!--#storyblok#{"name": "page", "space": "127485", "uid": "fbb0f60a-3c57-456e-84c3-8b86f02aeae0", "id": "86019624"}-->"
]
"slug" => "test"
"full_slug" => "test"
"default_full_slug" => null
"sort_by_date" => null
"position" => -40
"tag_list" => []
"is_startpage" => false
"parent_id" => 0
"meta_data" => null
"group_id" => "c3210eaf-a185-46ea-b7c5-a54424b3fcc9"
"first_published_at" => "2021-11-17T10:42:25.116Z"
"release_id" => null
"lang" => "default"
"path" => null
"translated_slugs" => []
]
+liveContent: []
#_meta: array:5 [▶]
}
Only slugs in Storyblok root produce this kind of result, everything else errors out completely - usually because the API call is using the slug without the 'starts_with'. For example:
Storyblok\ApiException
An HTTP Error has occurred! - An HTTP Error has occurred! - Client error: `GET http://api.storyblok.com/v1/cdn/stories/blog?token=xxxxx&version=draft&cache_version=1637149023` resulted in a `404 Not Found` response: {"stories":["This record could not be found"]}
If I hit the API directly in the browser with a 'starts_with=blog/' parameter, then I get a full API response.
So definitely I'm missing something here, and if the answer is "learn more Laravel", then that's perfectly acceptable answer!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.