How to Use IRootFolder

Hi,

any idea how to use the interface OCP\Files\IRootFolder to get file size? it has a function getUserFolder but how to implement it?

Thanks

IRootFolder is purely used to get a user’s folder. This returns the users folder which you can query for more information (see the php docs)

I tried to query the script FilesService.php which contains the function getFileFromPath following the steps at here
so my scripts looks like

<?php
namespace OCA\TestApp\Actions;

use	OCA\TestApp\Actions\FilesService;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use	OCP\AppFramework\App;
use	OCP\ILogger;
use	OCP\IPreview;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use	OCP\Util;
class Files extends Action {
	
	private $filesService;
	
	public function create(array $params) {
		if ($params['path'] === '/' || $params['path'] === '' || $params['path'] === null) {
			return;
		}
		
		$this->filesService = $this->getContainer()->query(FilesService::class);

but it returned an error, when I wanted to enable the app at the server
which is Error: This app can not be enabled because it makes the server unstable
what went wrong?
Thaks

UPDATE:

<?php
    use OCP\Files\IRootFolder;
    use OCP\Files\Node;

where duplicated, I deleted them with the same code now I got the exception:

{\"Exception\":\"Error\",\"Message\":\"Call to undefined method OCA\\\\TestApp\\\\Actions\\\\Files::getContainer()\",\"Code\":0,

class Files extends Action 

I don’t think you understand what you are doing :slight_smile: You don’t import Action anywhere in your code. Try to step back and tell us what you are trying to do first :wink:

actually yes, I’m mainly a .NET dev, so you might see a common errors like this in my code :slight_smile:

anyways, I already made an app that logs activities, same as admin_audit but my app logs only files activities, such as create, delete rename…etc. and nothing else
the structure is like this,

lib\AppInfo\Application.php
lib\Actions\Action.php
lib\Actions\Files.php
lib\Actions\FilesService.php

Application.php registers logger using ILogger has the web hooks such as

Util::connectHook(
 Filesystem::CLASSNAME,
 Filesystem::signal_post_rename,
 $fileActions,
 'rename');

in Files.php there is files functions such as public function create(array $params) and in action the logger
all that works fine
I only need to get the file size, and send it to logger, I have the file path at $params

so you can see my problem is at $this->filesService = $this->getContainer()->query(FilesService::class);

I need access somehow to this function which is inside FilesService.php

I saw in other example they query (FilesService::class); so they can have access the getFileFromPath
so you can see I’m beginner at PHP, I appreciate any help

Thanks :slight_smile:

we usually set those stuff in the __construct() method. With automatic DI, you just set:

public function __construct(IRootFolder $rootFolder) {
    $this->rootFolder = $rootFolder;
}

you can check the Activity app, or the Fulltextsearch app.

If we need the IRootFolder in a class that is called manually, like from the hooks/events, you go with the query() thing

1 Like

if I wanted to do that manually, (since I already have the path and user id of the file) this constructor should be in Application.php correct?
Application.php extends App

__constructor() is the first method called when creating a new instance of a class:
https://secure.php.net/manual/en/language.oop5.decon.php

So, set the example I gave you before in the service that need to call the IRootFolder, but you really should have a look to existing apps to have a better overview on how an app is integrated to Nextcloud.

You should also upload your work to github to get better support

Sorry guys for I have been a real bother

now my code is like this

<?php

namespace OCA\TestApp\AppInfo;
use	OC\Files\Filesystem;
use	OC\Files\Node\File;
use	OCA\TestApp\Actions\Files;
use	OCA\TestApp\Actions\FilesService;
use	OCP\AppFramework\App;
use	OCP\ILogger;
use	OCP\IPreview;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use	OCP\Util;
use	Symfony\Component\EventDispatcher\GenericEvent;

class Application extends App {

	private $rootFolder;
	
	public function __construct(IRootFolder $rootFolder) {
		$this->rootFolder = $rootFolder;
		parent::__construct('TestApp');
	}
		
	public function register() {
		$this->registerHooks();
	}

in the case the app isn’t getting enabled and gives me this error

{“reqId”:“9kREepbLh2lhjhrDTlcI”,“level”:3,“time”:“2018-01-10T08:33:44+00:00”,“remoteAddr”:“194.165.136.114”,“user”:“admin”,“app”:“no app in context”,“method”:“GET”,“url”:"/index.php/apps/files",“message”:"Exception: {\"Exception\":\"TypeError\",\"Message\":\"Argument 1 passed to OCA\\\\TracerSizeFour\\\\AppInfo\\\\Application::__construct() must implement interface OCP\\\\Files\\\\IRootFolder, none given, called in \\\/var\\\/snap\\\/nextcloud\\\/4371\\\/nextcloud\\\/extra-apps\\\/tracersizefour\\\/appinfo\\\/app.php on line 4\",\"Code\":0,\"Trace\":\"#0 \\\/var\\\/snap\\\/nextcloud\\\/4371\\\/nextcloud\\\/extra-apps\\\/tracersizefour\\\/appinfo\\\/app.php(4): OCA\\\\TracerSizeFour\\\\AppInfo\\\\Application->__construct()\\n#1 \\\/snap\\\/nextcloud\\\/4371\\\/htdocs\\\/lib\\\/private\\\/legacy\\\/app.php(209): require_once('\\\/var\\\/snap\\\/nextc...')\\n#2 \\\/snap\\\/nextcloud\\\/4371\\\/htdocs\\\/lib\\\/private\\\/legacy\\\/app.php(149): OC_App::requireAppFile('tracersizefour')\\n#3 \\\/snap\\\/nextcloud\\\/4371\\\/htdocs\\\/lib\\\/private\\\/legacy\\\/app.php(124): OC_App::loadApp('tracersizefour')\\n#4 \\\/snap\\\/nextcloud\\\/4371\\\/htdocs\\\/lib\\\/base.php(989): OC_App::loadApps()\\n#5 \\\/snap\\\/nextcloud\\\/4371\\\/htdocs\\\/index.php(48): OC::handleRequest()\\n#6 {main}\",\"File\":\"\\\/var\\\/snap\\\/nextcloud\\\/4371\\\/nextcloud\\\/extra-apps\\\/tracersizefour\\\/lib\\\/AppInfo\\\/Application.php\",\"Line\":25}","userAgent":"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/63.0.3239.84 Safari\/537.36","version":"12.0.4.3"}

by the way does the $params that returns from file hooks contains the file size? I know it contains the path and the username

Thanks

Extending App should only be done to customize the dependency injection behavior. Do you know any of the C# DI frameworks like Autofac, Unity or Ninject?

Apart from that I think the app already allows you to write plugins for that.

Also please start with the app-tutorial app https://github.com/nextcloud/app-tutorial

Documentation is currently being worked on here https://github.com/nextcloud/documentation/pull/567

actually I have no prior knowledge of the frameworks that you have mentioned :slightly_frowning_face:, as for extending that “App” in my code I was following structure of the admin_audit app at the NextCloud server, but with modification only to the code, which works, but here parent::__construct('TestApp'); is passing the name of the app so it will appear in the logs. that doesn’t conflict with creating instance of rootFolder, does it?

in most of the apps that uses OPC/Files/IRootFolder, they followed the same pattern which is defining IRootFolder in constructor

Thanks

Thanks both for the help

I took another way of creating IRootFolder to get file size and file time

<?php

namespace OCA\TestApp\AppInfo;

use	OC\Files\Filesystem;
use	OC\Files\Node\File;
use	OCA\TestApp\Actions\Files;
use	OCA\TestApp\Actions\FilesService;
use	OCP\AppFramework\App;
use	OCP\ILogger;
use	OCP\IPreview;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use	OCP\Util;
use	Symfony\Component\EventDispatcher\GenericEvent;

class Application extends App {
	
	private $rootFolder;
	
	public function __construct() {
		
		parent::__construct('TestApp');
	}
		
	public function register() {
		$this->registerHooks();
	}
	
	protected function registerHooks() {
		$logger = $this->getContainer()->getServer()->getLogger();							
		$this->fileHooks($logger);	
	}
	
	protected function fileHooks(ILogger $logger) {
		//NOTICE THE LINE BELOW
		$rootFolder = $this->getContainer()->getServer()->getRootFolder();
 		
              //sending the rootFolder instance to the constructor of the class Files
		$fileActions = new Files($rootFolder, $logger);
		$eventDispatcher = $this->getContainer()->getServer()->getEventDispatcher();
}

and from the rootFolder:

<?php
public function getFileFromPath($userId, $path) {
		return $this->rootFolder->getUserFolder($userId)->get($path);
	}

inside a function

<?php
$node = $this->getFileFromPath($str, $params['path']);
$size = $node->getSize();
$time = $node->getMTime();

That’s not how you should solve it but ok. Go through the tutorial.

its not?:thinking:
but I already can have the size and time for created, and renamed files, what could be the problem?