How to get the name of the directory where the app is installed?

I’m developing an app. I know that it can be installed in the default ‘apps’ directory located in the Nextcloud root directory, or in a custom apps directory, named for example ‘special_apps’, created in the Nextcloud root directory.

My question is: How can I get the name of the directory where my app is located ? Since some users may install it in the default ‘apps’ directory, while others may install it in the ‘special_apps’ directory. Is there a method that I can use to get the name of that directory ? Is there something like getAppDirectory("app_id") that would return ‘apps’ if the app was installed inside ‘apps’, and ‘special_apps’ if the app was installed inside ‘special_apps’ ?

Not that I am aware of. Why do you need this?

I guess, the point is routing and accessing static files in the app folder. There, you can use the JS library @nextcloud/router. For example, the generateFilePath function might be what you are looking for.

@christianlupus Thank you for your answer. generateFilePath gives me the generateFilePath is not a function error in Firefox’s console, on the page where I need to use it.

The generateFilePath is only available from within the web frontend of an NC app and only, if you included and imported @nextcloud/router appropriately. Obviously, this is not working in your use case.

So, to sum up your use case: you want to access a static file that is part of an NC app. This access should be made from a foreign web app (or whatever). What you could do is to create a regular route to your NC app. In this app, you can use a public page that will return the correct path to parse.

As this can be done in the NC backend, you can calculate the correct path there and return this as a 301 redirect for example. Alternatively, you can transmit the path using a JSON document.

Does this help you?

@christianlupus Thank you very much for your replies. I really appreciate your help.

While looking at this Nextcloud class I found the function getAppWebPath() with the mention:

@deprecated 18.0.0 use \OC::$server->getAppManager()->getAppWebPath()

So, I took the function:

\OC::$server->getAppManager()->getAppWebPath("app_id");

included it in another function which I included in the file /lib/Controller/MyappnameController.php and it correctly returned the custom apps directory where my app was located. ( app_id is the official id of the app, like calendar, circles, files_external, etc. ). So, If my app was installed in the apps directory the function returned /apps/my_app_id and if the app was installed in the special_apps directory, the function returned /special_apps/my_app_id.

Of course, when installed inside the special_apps directory, I had to add the following lines to the config/config.php file:

"apps_paths" => [
    [
            "path"     => OC::$SERVERROOT . "/apps",
            "url"      => "/apps",
            "writable" => false,
    ],
    [
            "path"     => OC::$SERVERROOT . "/special_apps",
            "url"      => "/special_apps",
            "writable" => true,
    ],
],

Thanks again!

Hello.

This is not a good solution! Never use any classes from the OC namespace directly. You can only use the interfaces from OCP (own cloud public). Otherwise, your app might break anytime.

The feature you are looking for is provided by the IUrlGenerator. You can use that as it is more stable than the private methods and classes.

Christian

I’ve just tried again the methods of IURLGenerator and nothing works. I can only get https://cloud.domain.com/. Yet, I’m interested to get something like /special_apps/my_app_id. That part I can only get with:

\OC::$server->getAppManager()->getAppWebPath("app_id");

What file (relative to the app folder) are you looking for?

I checked the implementation of the URL generator and it should do, what you are looking for.

Ideally you could share your code or at least some contiguous snippets.

Christian

I learned that even if an app is installed in special_apps instead of apps, the URL of the app when opening it remains https://cloud.domain.com/apps/my_app_id. So, even if my app gets installed into a directory different from the default apps, the URLs of the app that need to be accessed from outside Nextcloud remain the same, containing the word apps and not special_apps. This is good, but I still have to replace apps with the name of the custom apps directory in all the image paths that I use in my JavaScript files. I tried to use image paths relative to the JavaScript files, but it didn’t work, so, I still need to get the name of the current apps directory.

@christianlupus you were right. I was able to use the linkTo() method of the URLGenerator class mentioned above to get the name of the directory where my app was located. I used:

$appPath = $this->urlGenerator->linkTo('my_app_id', 'somefile.txt');

to get special_apps/my_app_id/somefile.txt and from there I extracted the name of the custom apps directory, special_apps in this example. Then I added that name in my JavaScript files to the paths of my images, so as to have them displayed correctly irrespective of where the app is installed.

I noticed that the linkTo() method makes use of the getAppWebPath() method that I used earlier and it worked. Is there an advantage of using:

$appPath = $this->urlGenerator->linkTo('my_app_id', 'somefile.txt');

instead of using

\OC::$server->getAppManager()->getAppWebPath("my_app_id");

directly ? The latter seems pretty stable to me.

Why not directly pass the correct file name of the image you are requesting? Then you would not need the special file, avoid the parsing and make the API more robust BTW.

If the problem is the number of files, you could add a path parameter to the route that identifies the file something like https://cloud.example.com/apps/my-app-name/getImage?filename=img/foo0123.jpg. Then, you can define a single route in the app that will return a http 301 or 302 with tge correct location. This should allow you to directly import the link…

The benefit of the way over the URL generator is that it is more stable. Maybe the devs decide one day that the internal variable $server should be dropped. This will break your code in nasty ways immediately. The URL generator can only change with major NC versions and only with prior deprecation. This gives you time to adopt.

Christian

The images that I mentioned don’t need to be accessed from the exterior. They are just included on the app’s pages using JavaScript files, and in these files I have to specify the paths to them in src='/path/to/image.svg' of all <img> elements. The only paths that work are of this type: src='/special_apps/my_app_id/img/someimage.svg', so, the name of the custom apps directory, here special_apps, has to be included in the paths.

Anyway, now everything works. All the images are displayed correctly and the URLs accessed from the exterrior work as well. I’m using the linkTo() method of the URLGenerator class, as adviced. Thank you.

OK, so your JS is part of the NC app. Are you using the webpack builder as done by default when creating an app skeleton? If yes, you can install the package @nextcloud/router (as already mentioned multiple times) in order to resolve the paths to your local app. You do not have to manage this yourself.

Apart from that, if it works, I will not complain. Just wanted to ofer the best service.

Christian