agentejo / cockpit

Add content management functionality to any site - plug & play / headless / api-first CMS
http://getcockpit.com
MIT License
5.4k stars 523 forks source link

How can i get full image paths? #816

Open jesperlandberg opened 6 years ago

jesperlandberg commented 6 years ago

Is there any good way of getting the full path to images (rest api)? I'm not hosting cockpit on the same server as the front-end.

nisdec commented 6 years ago

I have the same question.

michabbb commented 6 years ago

your application, which is doing the rest call, already needs infos like

so whatΒ΄s the deal adding a:

to your existing config ? πŸ€”

jesperlandberg commented 6 years ago

@michabbb Not sure I follow.

michabbb commented 6 years ago

@jesperlandberg ah, you mean path on the server, not url to open that image in the browser, right ? 😏

jesperlandberg commented 6 years ago

@michabbb correct=)

michabbb commented 6 years ago

@jesperlandberg pardon, misunderstanding πŸ™ˆ 😏

nisdec commented 6 years ago

Since this cms is mainly used as a "headless" cms, it would just make sense to serve absolute image paths, because more often than not is this cms hosted on a different domain than the frontend. Even if this would be an opt-in option.

@michabbb Your suggestion might be okay in a "smaller" frontend environment, but it becomes a pain when you have to deal with a ton of components, services and maybe even multiple apps, which all get their data from this cms. To feed a "image_url"-variable through everything is just a unnecessary pain.

michabbb commented 6 years ago

@nisdec i am just evaluating this cms at the moment, thats why i am interested in some issues here. as i said, sorry - misunderstanding here 😏 beside the fact that there exists NULL docu about "howto write an addon", i really like what i see, so far. and yes, i understand you.

gryphonmyers commented 6 years ago

It's an oft-requested feature https://github.com/agentejo/cockpit/issues/695 and one we've argued with @aheinze about before https://github.com/agentejo/cockpit/issues/470

raffaelj commented 6 years ago

Create a file /config/bootstrap.php with this content:

<?php

/*
  copy this code to `/config/bootstrap.php`

  When you save an asset, absolute_path and real_path are added automatically.

*/

$app->on('cockpit.assets.save', function(&$assets) use ($app) {

    foreach ($assets as &$asset) {

        // add paths
        $asset['absolute_path'] = $app['site_url'] . $app['base_url'] . '/storage/uploads' . $asset['path'];

        $asset['real_path'] = COCKPIT_DIR . '/storage/uploads' . $asset['path'];

    }

});

or $app->on('collections.save.before', function(... for all collections.

Now all assets have absolute_path and real_path, when they are saved.

The trigger collections.find.before doesn't allow to modify data, so it's necessary to create the path when saving the entry.


edit: replaced code with a much better solution

nisdec commented 6 years ago

@raffaelj Thank you for your solution!

Unfortunately I get the following error when I try your solution: Warning: Parameter 1 to LimeExtra\App::{closure}() expected to be a reference, value given in /cms/lib/Lime/App.php on line 592

Any idea?

raffaelj commented 6 years ago

@nisdec I can't reproduce it. Can you explain, what you did before? Did you use the assets manager or image-field or asset-field or the api...? Maybe you have a typo...

Do you use the (latest) next branch or master? Is your PHP version > 7.0?

nisdec commented 6 years ago

@raffaelj Okay I managed to solve the error simply by updating Cockpit, sorry. I was on PHP 7.2 with Cockpit 0.6.0 or 0.6.1. Now I'm on PHP 7.2 with Cockpit 0.8.0.

It actually works now when I use an asset-field! Is there also a way to do the same for an image-field?

Thank you so much.

raffaelj commented 6 years ago

@nisdec

Is there also a way to do the same for an image-field?

I'm not sure. After skimming the code, I don't think so. Image uploads are handled different than assets. It looks like they are just simple files without any database entries.

You could create a custom api endpoint:

<?php
/*
  copy this code to `/config/api/imagepath.php`

  call it with `/api/imagepath?token=xxtokenxx`
  json body: {"src":"imageid","h":"100"}

*/

$thumb_url = $this->invoke('\\Cockpit\\Controller\\RestApi', 'image');

$relative_path = str_replace($this['site_url'].$this['base_route'], '', $thumb_url);

$real_path = COCKPIT_DIR . $relative_path;

return [
    'thumb_url' => $thumb_url,
    'relative_path' => $relative_path,
    'real_path' => $real_path
];
annda commented 5 years ago

I have a site that consumes Cockpit content via API and I would like to insert images in HTML fields, using uploaded assets. The WYSIWYG editor truncates the image paths and outputs relative links, like '/storage/...'.

In a headless CMS I would expect full paths in HTML, like 'http(s)/:.mysite.domain/storage....'

Is there a way to configure the editor to prepend the site path to src in image tags?

I found this option in the TinyMCE docs https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_base_path but I don't know how, or whether, it is possible to configure Cockpit to use it.

The alternative would be to parse all HTML client-side and replace the image links, which I would rather avoid.

pauloamgomes commented 5 years ago

I have a site that consumes Cockpit content via API and I would like to insert images in HTML fields, using uploaded assets. The WYSIWYG editor truncates the image paths and outputs relative links, like '/storage/...'.

In a headless CMS I would expect full paths in HTML, like 'http(s)/:.mysite.domain/storage....'

Is there a way to configure the editor to prepend the site path to src in image tags?

I found this option in the TinyMCE docs https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_base_path but I don't know how, or whether, it is possible to configure Cockpit to use it.

The alternative would be to parse all HTML client-side and replace the image links, which I would rather avoid.

I still think is the best option, contents are saved in Cockpit as collections, so its good to have all paths relative to the storage they are configured, if you switch servers, change domain or migrate, it would be a bit of nightmare to update again all paths, right?

Dealing with that in the frontend is not so complicated, usually in React (or any node app) I defined an .env file (e.g. .env.local, .env.production, etc..):

COCKPIT_STORAGE_ASSETS_URL=https://mycockpit-url/

and replace it on asset fields, etc..

if I'm using a WYSIWYG editor I can also transform the markup, for that I use the handy htmr library (https://github.com/pveyes/htmr) and can do something like:

// (...other imports)
import convert from "htmr";

// my transform callback, can handle any html tag like img
const transform = {
  img: node => <img src={`${process.env.COCKPIT_STORAGE_ASSETS_URL}/${node.src}`} {...node} />,
};

const MyComponent = props => {
  return <div>{convert(props.markup, { transform })}</div>;
}

export default MyComponent;

keep in mind that above is a very draft example, you may need to deal with external images, etc..

annda commented 5 years ago

I absolutely agree that storing full paths in the database is nonsense and would cause more harm than good.

But I am not sure what is wrong with the API itself prepending the URL on database output. Cockpit already uses site_url in configuration, and the paths to assets, uploads, etc. are also separately defined and can be overridden on a per-system basis.

Basically, my wish for the future is that the Cockpit API would process the storage paths internally and output the URLs in links. That way the files could even be stored on another system. And the clients would only call the API and remain agnostic of which assets are stored where. But that is probably a whole new feature request.

In the meantime, I will stick to a simple regex replacement in the client.

jasonday commented 5 years ago

But I am not sure what is wrong with the API itself prepending the URL on database output. Cockpit already uses site_url in configuration, and the paths to assets, uploads, etc. are also separately defined and can be overridden on a per-system basis.

I agree. Additionally, Cockpit is even more aggressive in that if you put in a fully qualified url, cockpit will rewrite it to a relative url - which is a huge pain - https://github.com/agentejo/cockpit/issues/1102

darkylmnx commented 5 years ago

There should be an option for absolute URL's as this is really annoying on JAMstack or SPA apps. On these kind of apps, the CMS is always (98% of the time) on a different domain so the absolute path would be the most accurate solution.