Merge branch 'seeddms-5.1.x' into seeddms-6.0.x

This commit is contained in:
Uwe Steinmann 2025-11-13 14:01:55 +01:00
commit c2ec21ae40
39 changed files with 8423 additions and 7159 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

34
phpcs.xml Normal file
View File

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<ruleset name="SeedDmsStandard" namespace="SeedDMS\PHPCS">
<description>Coding standards for SeedDMS.</description>
<file>inc</file>
<file>out</file>
<file>op</file>
<file>controllers</file>
<exclude-pattern>SeedDMS_Core/[^/]+/oldtests/*</exclude-pattern>
<exclude-pattern>SeedDMS_Core/[^/]+/tests/*</exclude-pattern>
<arg name="extensions" value="php"/>
<arg name="tab-width" value="2"/>
<rule ref="PSR2">
<exclude name="Generic.WhiteSpace.DisallowTabIndent" />
<exclude name="Generic.Files.LineLength"/>
<exclude name="Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine"/>
<exclude name="Squiz.Functions.MultiLineFunctionDeclaration.ContentAfterBrace"/>
<exclude name="Squiz.Classes.ValidClassName.NotPascalCase"/>
<exclude name="Squiz.WhiteSpace.ScopeClosingBrace.ContentBefore"/>
<exclude name="PSR1.Classes.ClassDeclaration.MissingNamespace"/>
<exclude name="PSR1.Classes.ClassDeclaration.MultipleClasses"/>
<exclude name="PSR2.Classes.ClassDeclaration.CloseBraceAfterBody"/>
<exclude name="PSR2.Classes.PropertyDeclaration.Underscore"/>
<exclude name="PSR2.Classes.ClassDeclaration.OpenBraceNewLine"/>
<exclude name="Generic.ControlStructures.InlineControlStructure.NotAllowed"/>
<exclude name="Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase"/>
</rule>
<rule ref="Generic.WhiteSpace.DisallowSpaceIndent" />
<rule ref="Generic.WhiteSpace.ScopeIndent">
<properties>
<property name="indent" value="2"/>
<property name="tabIndent" value="true"/>
</properties>
</rule>
</ruleset>

View File

@ -0,0 +1,280 @@
<?php
namespace Seeddms\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Seeddms\Seeddms\Settings;
use Seeddms\Seeddms\Translator;
use SeedDMS_Extension_Mgr;
use Log_file;
use finfo;
class AdddocumentCommand extends Command
{
protected $settings;
protected $logger;
protected $translator;
protected $extmgr;
public function __construct(Settings $settings, Log_file $logger, Translator $translator, SeedDMS_Extension_Mgr $extmgr)
{
$this->settings = $settings;
$this->logger = $logger;
$this->translator = $translator;
$this->extmgr = $extmgr;
parent::__construct();
}
protected function configure()
{
$this->setName('dms:adddocument')
->setDescription('Create a new document')
->setHelp('Create a new document below the given parent folder')
->addArgument('filename', InputArgument::REQUIRED, 'Name of file to be uploaded.')
->addOption('user', 'u', InputOption::VALUE_REQUIRED, 'Owner of new document.', '')
->addOption('no-notifications', '', InputOption::VALUE_NONE, 'Do not send notifications.')
->addOption('folder', 'F', InputOption::VALUE_REQUIRED, 'Parent folder.', null)
->addOption('document', 'D', InputOption::VALUE_REQUIRED, 'Document to be updated.', null)
->addOption('name', '', InputOption::VALUE_REQUIRED, 'Name of document.', null)
->addOption('comment', 'c', InputOption::VALUE_REQUIRED, 'Comment of document.', '')
->addOption('mimetype', 't', InputOption::VALUE_REQUIRED, 'Mime type of document.', '')
->addOption('sequence', 's', InputOption::VALUE_REQUIRED, 'Sequence of document.', null)
->addOption('keyword', 'k', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Keyword.', null)
->addOption('category', 'K', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Category.', null)
->addOption('attribute', 'a', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Document attribute.', null)
->addOption('version_attribute', 'A', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Document version attribute.', null)
;
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$settings = $this->settings;
$logger = $this->logger;
$translator = $this->translator;
$output->writeln("<comment>Using configuration from '".$settings->_configFilePath."'.</comment>", OutputInterface::VERBOSITY_VERBOSE);
if (!is_writable($settings->_contentDir)) {
$output->writeln(sprintf("<error>The content dir '%s' is not writable by the system user running this script.</error>", $settings->_contentDir));
return Command::FAILURE;
}
$filename = $input->getArgument('filename');
$mymimetype = $input->getOption('mimetype');
/* Check if file is readable {{{ */
if (is_readable($filename)) {
if (filesize($filename)) {
$finfo = new finfo(FILEINFO_MIME_TYPE);
if (!$mymimetype) {
$mymimetype = $finfo->file($filename);
}
$filetype = "." . pathinfo($filename, PATHINFO_EXTENSION);
} else {
$output->writeln(sprintf("<error>File '%s' has zero size</error>", $filename));
return Command::FAILURE;
}
} else {
$output->writeln(sprintf("<error>File '%s' is not readable</error>", $filename));
return Command::FAILURE;
}
/* }}} */
$nonotifications = $input->getOption('no-notifications');
require_once('inc/inc.DBInit.php');
$username = $input->getOption('user');
if ($username) {
if (!($user = $dms->getUserByLogin($username))) {
$output->writeln(sprintf("<error>No such user '%s'</error>", $username));
return Command::FAILURE;
}
} else {
$user = $dms->getUser(1);
}
$dms->setUser($user);
$output->writeln("<comment>Running as user ".$user->getLogin().".</comment>", OutputInterface::VERBOSITY_VERBOSE);
$name = $input->getOption('name');
if (!$name) {
$output->writeln("<error>You need to specify a document name.</error>");
return Command::FAILURE;
}
$comment = $input->getOption('comment');
$folder = $document = null;
if ($folderid = $input->getOption('folder')) {
$folder = $dms->getFolder((int) $folderid);
if (!is_object($folder)) {
$output->writeln("<error>Could not find specified parent folder.</error>");
return Command::FAILURE;
}
if ($folder->getAccessMode($user) < M_READWRITE) {
$output->writeln("<error>Not sufficient access rights.</error>");
return Command::FAILURE;
}
} elseif ($documentid = $input->getOption('document')) {
$document = $dms->getDocument((int) $documentid);
if (!is_object($document)) {
$output->writeln("<error>Could not find specified document.</error>");
return Command::FAILURE;
}
if ($document->getAccessMode($user) < M_READWRITE) {
$output->writeln("<error>Not sufficient access rights.</error>");
return Command::FAILURE;
}
} else {
$output->writeln("<error>You need to specify a parent folder or a document to be updated.</error>");
return Command::FAILURE;
}
$sequence = $input->getOption('sequence');
if (!$sequence) {
$sequence = $this->settings->_defaultFolderPosition;
}
if (!is_numeric($sequence) && $sequence != 'start' && $sequence != 'end') {
$output->writeln("<error>Sequence must be a numeric value, 'start', or 'end'</error>");
return Command::FAILURE;
}
if ($folder) {
$minmax = $folder->getDocumentsMinMax();
if ($sequence == 'start') {
$seq = $minmax['min'] - 1;
} elseif ($sequence == 'end') {
$seq = $minmax['max'] + 1;
} else {
$seq = $sequence;
}
}
/* Parse categories {{{ */
$cats = $input->getOption('category');
if ($cats) {
foreach($cats as $categoryname) {
$cat = $dms->getDocumentCategoryByName($categoryname);
if ($cat) {
$categories[] = $cat;
} else {
$output->writeln(sprintf("<error>Category '%s' not found.</error>", $categoryname));
return Command::FAILURE;
}
}
} /* }}} */
/* Parse document attributes. {{{ */
$document_attributes = array();
$attributes = $input->getOption('attribute');
if ($attributes) {
foreach ($attributes as $thisAttribute) {
$attrKey = strstr($thisAttribute, '=', true);
$attrVal = substr(strstr($thisAttribute, '='), 1);
if (empty($attrKey) || empty($attrVal)) {
$output->writeln(sprintf("<error>Document attribute %s not understood</error>", $thisAttribute));
return Command::FAILURE;
}
$attrdef = $dms->getAttributeDefinitionByName($attrKey);
if (!$attrdef) {
$output->writeln(sprintf("<error>Document attribute '%s' unknown</error>", $attrKey));
return Command::FAILURE;
}
$document_attributes[$attrdef->getID()] = $attrVal;
}
} /* }}} */
/* Parse version attributes. {{{ */
$version_attributes = array();
$attributes = $input->getOption('version_attribute');
if ($attributes) {
foreach ($attributes as $thisAttribute) {
$attrKey = strstr($thisAttribute, '=', true);
$attrVal = substr(strstr($thisAttribute, '='), 1);
if (empty($attrKey) || empty($attrVal)) {
$output->writeln(sprintf("<error>Document attribute %s not understood</error>", $thisAttribute));
return Command::FAILURE;
}
$attrdef = $dms->getAttributeDefinitionByName($attrKey);
if (!$attrdef) {
$output->writeln(sprintf("<error>Document attribute '%s' unknown</error>", $attrKey));
return Command::FAILURE;
}
$version_attributes[$attrdef->getID()] = $attrVal;
}
} /* }}} */
// return Command::FAILURE;
$keywords = implode(' ', $input->getOption('keyword'));
$expires = false;
$reviewers = array();
$approvers = array();
require_once("inc/inc.ClassController.php");
if ($folder) {
$controller = \Controller::factory('AddDocument', array('dms'=>$dms, 'user'=>$user, 'extmgr'=>$this->extmgr, 'settings'=>$this->settings));
$controller->setParam('documentsource', 'script');
$controller->setParam('folder', $folder);
$controller->setParam('fulltextservice', $fulltextservice);
$controller->setParam('name', $name);
$controller->setParam('comment', $comment);
$controller->setParam('expires', $expires);
$controller->setParam('keywords', $keywords);
$controller->setParam('categories', $categories);
$controller->setParam('owner', $user);
$controller->setParam('sequence', $seq);
$controller->setParam('userfiletmp', $filename);
$controller->setParam('userfilename', basename($filename));
$controller->setParam('filetype', $filetype);
$controller->setParam('userfiletype', $mymimetype);
$controller->setParam('reviewers', $reviewers);
$controller->setParam('approvers', $approvers);
$controller->setParam('attributes', array());
$controller->setParam('notificationgroups', array());
$controller->setParam('notificationusers', array());
if (!$document = $controller->run()) {
output->writeln("<error>Could not create document</error>");
return Command::FAILURE;
} else {
// Send notification to subscribers.
if ($notifier && !$nonotifications) {
$output->writeln(sprintf('<comment>Sending notifications ...</comment>'), OutputInterface::VERBOSITY_VERBOSE);
$notifier->sendNewDocumentMail($document, $user);
}
}
$output->writeln(sprintf('<info>New document with id=%d created.</info>', $document->getId()), OutputInterface::VERBOSITY_QUIET);
return Command::SUCCESS;
} elseif ($document) {
$controller = \Controller::factory('UpdateDocument', array('dms'=>$dms, 'user'=>$user));
$controller->setParam('folder', $document->getFolder());
$controller->setParam('document', $document);
$controller->setParam('fulltextservice', $fulltextservice);
$controller->setParam('comment', $comment);
$controller->setParam('userfiletmp', $filename);
$controller->setParam('userfilename', basename($filename));
$controller->setParam('filetype', $filetype);
$controller->setParam('userfiletype', $mymimetype);
$controller->setParam('reviewers', $reviewers);
$controller->setParam('approvers', $approvers);
$controller->setParam('attributes', $version_attributes);
$controller->setParam('workflow', null);
if (!$content = $controller->run()) {
output->writeln("<error>Could not add version to document</error>");
return Command::FAILURE;
} else {
// Send notification to subscribers.
if ($notifier && !$nonotifications) {
$output->writeln(sprintf('<comment>Sending notifications ...</comment>'));
$notifier->sendNewDocumentVersionMail($document, $user);
}
}
$output->writeln(sprintf('<info>New document version %d of document with id=%d created.</info>', $content->getVersion(), $document->getId()), OutputInterface::VERBOSITY_QUIET);
return Command::SUCCESS;
}
}
}
// vim: sw=4 ts=4 expandtab

View File

@ -0,0 +1,155 @@
<?php
namespace Seeddms\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Seeddms\Seeddms\Settings;
use Seeddms\Seeddms\Translator;
use Log_file;
class AddfolderCommand extends Command
{
protected $settings;
protected $logger;
protected $translator;
public function __construct(Settings $settings, Log_file $logger, Translator $translator)
{
$this->settings = $settings;
$this->logger = $logger;
$this->translator = $translator;
parent::__construct();
}
protected function configure()
{
$this->setName('dms:addfolder')
->setDescription('Create a new folder')
->setHelp('Create a new folder below the given parent folder')
->addOption('user', 'u', InputOption::VALUE_REQUIRED, 'Owner of new folder.', '')
->addOption('parent', 'F', InputOption::VALUE_REQUIRED, 'Parent folder.', null)
->addOption('name', '', InputOption::VALUE_REQUIRED, 'Name of folder.', null)
->addOption('comment', 'c', InputOption::VALUE_REQUIRED, 'Comment of folder.', '')
->addOption('sequence', 's', InputOption::VALUE_REQUIRED, 'Sequence of folder.', null);
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$settings = $this->settings;
$logger = $this->logger;
$translator = $this->translator;
$output->writeln("<comment>Using configuration from '".$settings->_configFilePath."'.</comment>", OutputInterface::VERBOSITY_VERBOSE);
if (!is_writable($settings->_contentDir)) {
$output->writeln(sprintf("<error>The content dir '%s' is not writable by the system user running this script.</error>", $settings->_contentDir));
return Command::FAILURE;
}
require_once('inc/inc.DBInit.php');
$username = $input->getOption('user');
if ($username) {
if (!($user = $dms->getUserByLogin($username))) {
$output->writeln(sprintf("<error>No such user '%s'</error>", $username));
return Command::FAILURE;
}
} else {
$user = $dms->getUser(1);
}
$dms->setUser($user);
$output->writeln("<comment>Running as user ".$user->getLogin().".</comment>", OutputInterface::VERBOSITY_VERBOSE);
$name = $input->getOption('name');
if(!$name) {
$output->writeln("<error>You need to specify a folder name.</error>");
return Command::FAILURE;
}
$comment = $input->getOption('comment');
if($folderid = $input->getOption('parent')) {
$folder = $dms->getFolder((int) $folderid);
if (!is_object($folder)) {
$output->writeln("<error>Could not find specified parent folder.</error>");
return Command::FAILURE;
}
} else {
$output->writeln("<error>You need to specify a parent folder.</error>");
return Command::FAILURE;
}
if ($folder->getAccessMode($user) < M_READWRITE) {
$output->writeln("<error>Not sufficient access rights.</error>");
return Command::FAILURE;
}
$sequence = $input->getOption('sequence');
if(!$sequence) {
$sequence = $this->settings->_defaultFolderPosition;
}
if (!is_numeric($sequence) && $sequence != 'start' && $sequence != 'end') {
$output->writeln("<error>Sequence must be a numeric value, 'start', or 'end'</error>");
return Command::FAILURE;
}
$minmax = $folder->getFoldersMinMax();
if($sequence == 'start') {
$seq = $minmax['min'] - 1;
} elseif ($sequence == 'end') {
$seq = $minmax['max'] + 1;
} else {
$seq = $sequence;
}
require_once('inc/inc.DBInit.php');
require_once('inc/inc.Extension.php');
require_once("inc/inc.ClassController.php");
$controller = \Controller::factory('AddSubFolder', array('dms'=>$dms, 'user'=>$user, 'extmgr'=>$extmgr, 'settings'=>$this->settings));
$controller->setParam('folder', $folder);
$controller->setParam('name', $name);
$controller->setParam('comment', $comment);
$controller->setParam('sequence', $seq);
$controller->setParam('attributes', array());
$controller->setParam('notificationgroups', array());
$controller->setParam('notificationusers', array());
if (!$subFolder = $controller->run()) {
output->writeln("<error>Could not create folder</error>");
return Command::FAILURE;
} else {
// Send notification to subscribers.
if ($notifier) {
$output->writeln(sprintf('<comment>Sending notifications ...</comment>'), OutputInterface::VERBOSITY_VERBOSE);
$fnl = $folder->getNotifyList();
$snl = $subFolder->getNotifyList();
$nl = array(
'users'=>array_unique(array_merge($snl['users'], $fnl['users']), SORT_REGULAR),
'groups'=>array_unique(array_merge($snl['groups'], $fnl['groups']), SORT_REGULAR)
);
$subject = "new_subfolder_email_subject";
$message = "new_subfolder_email_body";
$params = array();
$params['name'] = $subFolder->getName();
$params['folder_name'] = $folder->getName();
$params['folder_path'] = $folder->getFolderPathPlain();
$params['username'] = $user->getFullName();
$params['comment'] = $comment;
$params['url'] = $settings->getBaseUrlWithRoot()."out/out.ViewFolder.php?folderid=".$subFolder->getID();
$params['sitename'] = $settings->_siteName;
$params['http_root'] = $settings->_httpRoot;
$notifier->toList($user, $nl["users"], $subject, $message, $params);
foreach ($nl["groups"] as $grp) {
$notifier->toGroup($user, $grp, $subject, $message, $params);
}
}
}
$output->writeln(sprintf('<info>New folder with id=%d created.</info>', $subFolder->getId()), OutputInterface::VERBOSITY_QUIET);
return Command::SUCCESS;
}
}
// vim: sw=4 ts=4 expandtab

View File

@ -0,0 +1,68 @@
<?php
namespace Seeddms\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Seeddms\Seeddms\Settings;
use Seeddms\Seeddms\Translator;
use SeedDMS_View_Common;
use SeedDMS_Controller_Common;
use Controller;
use Log_file;
class ClearcacheCommand extends Command
{
protected $settings;
protected $logger;
protected $translator;
public function __construct(Settings $settings, Log_file $logger, Translator $translator)
{
$this->settings = $settings;
$this->logger = $logger;
$this->translator = $translator;
parent::__construct();
}
protected function configure()
{
$this->setName('cache:clear')
->setDescription('Clears the cache')
->setHelp('Clears all cache or those specified.')
->addOption('cache', '', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Remove files from cache.', null)
;
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$app = $this->getApplication();
$settings = $this->settings;
$logger = $this->logger;
$translator = $this->translator;
$output->writeln("<comment>Using configuration from '".$settings->_configFilePath."'.</comment>");
if (!is_writable($settings->_cacheDir)) {
$output->writeln(sprintf("<error>The cache dir '%s' is not writable for the system user running this script.</error>", $settings->_cacheDir));
return Command::FAILURE;
}
require_once('inc/inc.DBInit.php');
$post = array_flip($input->getOption('cache'));
array_walk($post, function (&$v, $k) {$v=1;});
$controller = Controller::factory('ClearCache', array('settings'=>$settings));
$controller->setParam('post', $post);
if(!$ret = $controller->run()) {
}
return Command::SUCCESS;
}
}
// vim: ts=4 sw=4 expandtab

View File

@ -0,0 +1,93 @@
<?php
namespace Seeddms\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Seeddms\Seeddms\Settings;
use Seeddms\Seeddms\Translator;
use SeedDMS_Core_File;
use SeedDMS_View_Common;
use SeedDMS_Extension_Mgr;
use Log_file;
class ConfigureextensionCommand extends Command
{
protected $settings;
protected $logger;
protected $translator;
protected $extmgr;
public function __construct(Settings $settings, Log_file $logger, Translator $translator, SeedDMS_Extension_Mgr $extmgr)
{
$this->settings = $settings;
$this->logger = $logger;
$this->translator = $translator;
$this->extmgr = $extmgr;
parent::__construct();
}
protected function configure()
{
$this->setName('ext:configure')
->setDescription('Configure extension')
->setHelp('Enables and disables an extensions.')
->addOption('name', '', InputOption::VALUE_REQUIRED, 'Name of extension.', null)
->addOption('enable', '', InputOption::VALUE_NONE, 'Enable extension.')
->addOption('disable', '', InputOption::VALUE_NONE, 'Disable extension.')
;
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$settings = $this->settings;
$logger = $this->logger;
$translator = $this->translator;
$extmgr = $this->extmgr;
$output->writeln("<comment>Using configuration from '".$settings->_configFilePath."'.</comment>", OutputInterface::VERBOSITY_VERBOSE);
if (!is_writable($settings->_configFilePath)) {
$output->writeln(sprintf("<error>The configuration file '%s' is not writable by the system user running this script.</error>", $settings->_configFilePath));
return Command::FAILURE;
}
$extconf = $extmgr->getExtensionConfiguration();
$extname = $input->getOption('name');
if (!isset($extconf[$extname])) {
$output->writeln(sprintf("<error>No such extension '%s'</error>", $extname));
return Command::FAILURE;
}
if ($input->getOption('enable')) {
if ($settings->extensionIsDisabled($extname)) {
$settings->enableExtension($extname);
} else {
$output->writeln(sprintf("<info>Extension already enabled.</info>"));
return Command::SUCCESS;
}
} elseif ($input->getOption('disable')) {
if (!$settings->extensionIsDisabled($extname)) {
$settings->disableExtension($extname);
} else {
$output->writeln(sprintf("<info>Extension already disabled.</info>"));
return Command::SUCCESS;
}
} else {
$output->writeln(sprintf("<error>Missing option --enable or --disable</error>"));
return Command::FAILURE;
}
$settings->save();
return Command::SUCCESS;
}
}
// vim: ts=4 sw=4 expandtab

View File

@ -0,0 +1,128 @@
<?php
namespace Seeddms\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Seeddms\Seeddms\Settings;
use Seeddms\Seeddms\Translator;
use Log_file;
class DeleteCommand extends Command
{
protected $settings;
protected $logger;
protected $translator;
public function __construct(Settings $settings, Log_file $logger, Translator $translator)
{
$this->settings = $settings;
$this->logger = $logger;
$this->translator = $translator;
parent::__construct();
}
protected function configure()
{
$this->setName('dms:delete')
->setDescription('Delete a folder or document')
->setHelp('Folders can also be emptied.')
->addOption('user', 'u', InputOption::VALUE_REQUIRED, 'Run in behalf of this user.', '')
->addOption('folder', '', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Delete this folder.', null)
->addOption('document', '', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Delete this document.', null)
->addOption('empty', '', InputOption::VALUE_REQUIRED, 'Do not delete but empty the given folder.', null);
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$app = $this->getApplication();
$settings = $this->settings;
$logger = $this->logger;
$translator = $this->translator;
$output->writeln("<comment>Using configuration from '".$settings->_configFilePath."'.</comment>");
if (!is_writable($settings->_contentDir)) {
$output->writeln(sprintf("<error>The content dir '%s' is not writable for the system user running this script.</error>", $settings->_contentDir));
return Command::FAILURE;
}
require_once('inc/inc.DBInit.php');
$username = $input->getOption('user');
if ($username) {
if (!($user = $dms->getUserByLogin($username))) {
$output->writeln(sprintf("<error>No such user '%s'</error>", $username));
return Command::FAILURE;
}
} else {
$output->writeln("<error>You must specify a user.</error>");
return Command::FAILURE;
}
$dms->setUser($user);
$output->writeln("<comment>Running as user ".$user->getLogin().".</comment>");
$folderids = $input->getOption('folder');
$documentids = $input->getOption('document');
$empty = $input->getOption('empty');
if(!$documentids && !$folderids) {
$output->writeln("<error>You need to specify a folder or document.</error>");
return Command::FAILURE;
}
foreach($folderids as $folderid) {
$folder = $dms->getFolder((int) $folderid);
if (!is_object($folder)) {
$output->writeln("<error>Could not find specified folder.</error>");
return Command::FAILURE;
}
if ($folder->getAccessMode($user) < M_ALL) {
$output->writeln("<error>Insufficient access rights to remove folder with id=".$folderid."</error>");
return Command::FAILURE;
} else {
if($empty)
$controller = Controller::factory('EmptyFolder', array('dms'=>$dms, 'user'=>$user));
else
$controller = Controller::factory('RemoveFolder', array('dms'=>$dms, 'user'=>$user));
$controller->setParam('folder', $folder);
$controller->setParam('fulltextservice', $fulltextservice);
if(!$folder = $controller->run()) {
$output->writeln("<error>Could not ".($empty ? 'empty' : 'remove')." folder with id=".$folderid."</error>");
return Command::FAILURE;
} else {
$output->writeln("<info>Folder with id=".$folderid." ".($empty ? 'emptied' : 'removed').".</info>");
}
}
}
foreach($documentids as $documentid) {
$document = $dms->getDocument((int) $documentid);
if (!is_object($document)) {
$output->writeln("<error>Could not find specified document.</error>");
return Command::FAILURE;
}
if ($document->getAccessMode($user) < M_ALL) {
$output->writeln("<error>Insufficient access rights to remove document with id=".$documentid."</error>");
return Command::FAILURE;
} else {
$controller = Controller::factory('RemoveDocument', array('dms'=>$dms, 'user'=>$user));
$controller->setParam('document', $document);
$controller->setParam('fulltextservice', $fulltextservice);
if(!$document = $controller->run()) {
$output->writeln("<error>Could not remove document with id=".$documentid."</error>");
return Command::FAILURE;
} else {
$output->writeln("<info>Document with id=".$documentid." removed.</info>");
}
}
}
return Command::SUCCESS;
}
}
// vim: ts=4 sw=4 expandtab

View File

@ -0,0 +1,101 @@
<?php
namespace Seeddms\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Seeddms\Seeddms\Settings;
use Seeddms\Seeddms\Translator;
use SeedDMS_Core_File;
use SeedDMS_View_Common;
use Log_file;
use FilesystemIterator;
class ListcacheCommand extends Command
{
protected $settings;
protected $logger;
protected $translator;
public function __construct(Settings $settings, Log_file $logger, Translator $translator)
{
$this->settings = $settings;
$this->logger = $logger;
$this->translator = $translator;
parent::__construct();
}
protected function configure()
{
$this->setName('cache:list')
->setDescription('List caches')
->setHelp('Lists all caches including size.')
;
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$app = $this->getApplication();
$settings = $this->settings;
$logger = $this->logger;
$translator = $this->translator;
$outformat = '%-20s %-40s %15s %7d';
require_once('inc/inc.DBInit.php');
$cachedir = $settings->_cacheDir;
$totalc = 0;
$totalspace = 0;
// Preview for png, pdf, and txt */
foreach(['png', 'pdf', 'txt'] as $t) {
$path = addDirSep($cachedir).$t;
if(file_exists($path)) {
$space = dskspace($path);
$fi = new FilesystemIterator($path, FilesystemIterator::SKIP_DOTS);
$c = iterator_count($fi);
} else {
$space = $c = 0;
}
$totalc += $c;
$totalspace += $space;
$output->writeln(sprintf($outformat, 'preview'.$t, $translator->translate('preview_'.$t), SeedDMS_Core_File::format_filesize($space), $c));
}
/* Javascript */
$path = addDirSep($cachedir).'js';
if(file_exists($path)) {
$space = dskspace($path);
$fi = new FilesystemIterator($path, FilesystemIterator::SKIP_DOTS);
$c = iterator_count($fi);
} else {
$space = $c = 0;
}
$totalc += $c;
$totalspace += $space;
$output->writeln(sprintf($outformat, 'js', $translator->translate('temp_jscode'), SeedDMS_Core_File::format_filesize($space), $c));
$caches = [];
/* Create a dummy view for passing it to additionalCache() */
$view = new SeedDMS_View_Common(['settings'=>$settings]);
if (isset($GLOBALS['SEEDDMS_HOOKS']['view']['clearCache'])) {
foreach ($GLOBALS['SEEDDMS_HOOKS']['view']['clearCache'] as $hookObj) {
if (method_exists($hookObj, 'additionalCache')) {
$caches += $hookObj->additionalCache($view);
}
}
}
foreach($caches as $cache) {
$output->writeln(sprintf($outformat, $cache[0], $cache[1], SeedDMS_Core_File::format_filesize($cache[2]), $cache[3]));
}
// print_r($caches);
return Command::SUCCESS;
}
}
// vim: ts=4 sw=4 expandtab

View File

@ -0,0 +1,92 @@
<?php
namespace Seeddms\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Seeddms\Seeddms\Settings;
use Seeddms\Seeddms\Translator;
use SeedDMS_Core_File;
use SeedDMS_View_Common;
use SeedDMS_Extension_Mgr;
use Log_file;
class ListextensionCommand extends Command
{
protected $settings;
protected $logger;
protected $translator;
protected $extmgr;
public function __construct(Settings $settings, Log_file $logger, Translator $translator, SeedDMS_Extension_Mgr $extmgr)
{
$this->settings = $settings;
$this->logger = $logger;
$this->translator = $translator;
$this->extmgr = $extmgr;
parent::__construct();
}
protected function configure()
{
$this->setName('ext:list')
->setDescription('List extensions')
->setHelp('Lists all enable and disable extensions.')
;
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$settings = $this->settings;
$logger = $this->logger;
$translator = $this->translator;
$extmgr = $this->extmgr;
$outformat = '%s %-55s %-8s %-10s';
$descformat = '%-55s';
$extStyle = new OutputFormatterStyle('green', '', ['bold']);
$output->getFormatter()->setStyle('ext', $extStyle);
$descStyle = new OutputFormatterStyle('gray');
$output->getFormatter()->setStyle('desc', $descStyle);
$enabled = 0;
$disabled = 0;
$haserror = 0;
$extconf = $extmgr->getExtensionConfiguration();
foreach ($extconf as $extname=>$extconf) {
if (!$settings->extensionIsDisabled($extname)) {
$enabled++;
$output->writeln(sprintf('<ext>'.$outformat.'</ext>', '*', $extname, $extconf['version'], $extconf['releasedate']));
} else {
$disabled++;
$output->writeln(sprintf('<comment>'.$outformat.'</comment>', '-', $extname, $extconf['version'], $extconf['releasedate']));
}
$output->writeln(sprintf(' <desc>'.$descformat.'</desc>', $extconf['title']));
$lines = explode('|', wordwrap($extconf['description'], 55, '|'));
foreach($lines as $desc)
$output->writeln(sprintf(' <desc>'.$descformat.'</desc>', trim($desc)));
$output->writeln(sprintf(' <desc>'.$descformat.'</desc>', 'Author: '.$extconf['author']['name'].(!empty($extconf['author']['company']) ? ' ('.$extconf['author']['company'].')' : '')));
$check = $extmgr->checkExtensionByDir($extname);
$errmsgs = $extmgr->getErrorMsgs();
if($errmsgs) {
$haserror++;
foreach($errmsgs as $errmsg) {
$output->writeln(sprintf(' <error>'.$descformat.'</error>', trim($errmsg)));
}
}
}
$output->writeln('');
$output->writeln(sprintf('%d extensions, %d enabled, %d disabled, %d has errors', $enabled+$disabled, $enabled, $disabled, $haserror));
return Command::SUCCESS;
}
}
// vim: ts=4 sw=4 expandtab

View File

@ -0,0 +1,79 @@
<?php
namespace Seeddms\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Seeddms\Seeddms\Settings;
use Seeddms\Seeddms\Translator;
use SeedDMS_Core_File;
use SeedDMS_View_Common;
use SeedDMS_Extension_Mgr;
use Log_file;
class PackageextensionCommand extends Command
{
protected $settings;
protected $logger;
protected $translator;
protected $extmgr;
public function __construct(Settings $settings, Log_file $logger, Translator $translator, SeedDMS_Extension_Mgr $extmgr)
{
$this->settings = $settings;
$this->logger = $logger;
$this->translator = $translator;
$this->extmgr = $extmgr;
parent::__construct();
}
protected function configure()
{
$this->setName('ext:package')
->setDescription('Package extension as a zip file. If --output-dir is given, the zip file will be placed into this directory otherwise it will be saved in the current directory. The name of the zip file will be <extname>-<version>.zip. If such a file already exists, it will be deleted and recreated.')
->setHelp('Creates a zip file of an extension, which can be uploaded into SeedDMS.')
->addOption('name', '', InputOption::VALUE_REQUIRED, 'Name of extension.', null)
->addOption('output-dir', '', InputOption::VALUE_REQUIRED, 'Name of directory where the zip file is saved.', null)
;
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$settings = $this->settings;
$logger = $this->logger;
$translator = $this->translator;
$extmgr = $this->extmgr;
$output->writeln("<comment>Using configuration from '".$settings->_configFilePath."'.</comment>", OutputInterface::VERBOSITY_VERBOSE);
$extconf = $extmgr->getExtensionConfiguration();
$extname = $input->getOption('name');
if (!isset($extconf[$extname])) {
$output->writeln(sprintf("<error>No such extension '%s'</error>", $extname));
return Command::FAILURE;
}
$outputdir = $input->getOption('output-dir');
if(!$outputdir)
$outputdir = '.';
/* If the $outputdir is not passed to createArchive(), the cache
* dir of SeedDMS will be used, which requires to run this script
* with sufficient access rights on that directory.
*/
$filename = $extmgr->createArchive($extname, $extmgr->getExtensionConfiguration()[$extname]['version'], $outputdir);
$output->writeln(sprintf("Extension saved as '%s'", $filename));
return Command::SUCCESS;
}
}
// vim: ts=4 sw=4 expandtab

View File

@ -0,0 +1,68 @@
<?php
namespace Seeddms\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Seeddms\Seeddms\Settings;
use Seeddms\Seeddms\Translator;
use SeedDMS_Core_File;
use SeedDMS_View_Common;
use SeedDMS_Extension_Mgr;
use Log_file;
class ReloadextensionCommand extends Command
{
protected $settings;
protected $logger;
protected $translator;
protected $extmgr;
public function __construct(Settings $settings, Log_file $logger, Translator $translator, SeedDMS_Extension_Mgr $extmgr)
{
$this->settings = $settings;
$this->logger = $logger;
$this->translator = $translator;
$this->extmgr = $extmgr;
parent::__construct();
}
protected function configure()
{
$this->setName('ext:reload')
->setDescription('Reload extensions')
->setHelp('Recreates the cached extension list.')
;
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$settings = $this->settings;
$logger = $this->logger;
$translator = $this->translator;
$extmgr = $this->extmgr;
$output->writeln("<comment>Using configuration from '".$settings->_configFilePath."'.</comment>", OutputInterface::VERBOSITY_VERBOSE);
if (!is_writable($settings->_cacheDir)) {
$output->writeln(sprintf("<error>The cache directory '%s' is not writable by the system user running this script.</error>", $settings->_cacheDir));
return Command::FAILURE;
}
if($extmgr->createExtensionConf()) {
return Command::SUCCESS;
} else {
$output->writeln(sprintf("<error>Failed to recreate the extension list.'</error>"));
return Command::FAILURE;
}
}
}
// vim: ts=4 sw=4 expandtab

View File

@ -0,0 +1,83 @@
<?php
namespace Seeddms\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Seeddms\Seeddms\Settings;
use Seeddms\Seeddms\Translator;
use Log_file;
class StatsCommand extends Command
{
protected $settings;
protected $logger;
protected $translator;
public function __construct(Settings $settings, Log_file $logger, Translator $translator)
{
$this->settings = $settings;
$this->logger = $logger;
$this->translator = $translator;
parent::__construct();
}
protected function configure()
{
$this->setName('dms:stats')
->setDescription('Prints Statistics')
->setHelp('Demonstration of custom commands created by Symfony Console component.')
->addOption('json', '', InputOption::VALUE_NONE, 'Export data as json')
;
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$app = $this->getApplication();
$settings = $this->settings;
$logger = $this->logger;
$translator = $this->translator;
require_once('inc/inc.DBInit.php');
foreach (array('docstotal'=>'documents', 'folderstotal'=>'folders', 'userstotal'=>'users', 'groupstotal'=>'groups', 'categoriestotal'=>'categories') as $type=>$name) {
$stats[$type] = $dms->getStatisticalData($type);
}
foreach (array('docsperuser'=>'documents', 'foldersperuser'=>'folders','sizeperuser'=>'size') as $type=>$name) {
$stats[$type] = $dms->getStatisticalData($type);
}
if ($input->getOption('json')) {
$output->writeln(json_encode($stats));
} else {
$outformat = '%-30s %-10d';
$output->writeln(sprintf($outformat, 'Documents', $stats['docstotal']));
$output->writeln(sprintf($outformat, 'Folders', $stats['folderstotal']));
$output->writeln(sprintf($outformat, 'Users', $stats['userstotal']));
$output->writeln(sprintf($outformat, 'Groups', $stats['groupstotal']));
$output->writeln(sprintf($outformat, 'Categories', $stats['categoriestotal']));
$output->writeln('');
$output->writeln('Documents per user:');
foreach($stats['docsperuser'] as $d) {
$output->writeln(sprintf($outformat, $d['key'], $d['total']));
}
$output->writeln('');
$output->writeln('Folders per user:');
foreach($stats['foldersperuser'] as $d) {
$output->writeln(sprintf($outformat, $d['key'], $d['total']));
}
$output->writeln('');
$output->writeln('Size per user:');
foreach($stats['sizeperuser'] as $d) {
$output->writeln(sprintf($outformat, $d['key'], $d['total']));
}
}
return Command::SUCCESS;
}
}
// vim: ts=4 sw=4 expandtab

56
utils/console Executable file
View File

@ -0,0 +1,56 @@
#!/usr/bin/env php
<?php
// application.php
require __DIR__.'/../vendor/autoload.php';
require_once('Log.php');
require_once('inc/inc.Utils.php');
use Symfony\Component\Console\Application;
use Seeddms\Console\Commands\StatsCommand;
use Seeddms\Console\Commands\AddfolderCommand;
use Seeddms\Console\Commands\AdddocumentCommand;
use Seeddms\Console\Commands\DeleteCommand;
use Seeddms\Console\Commands\ClearcacheCommand;
use Seeddms\Console\Commands\ListcacheCommand;
use Seeddms\Console\Commands\ListextensionCommand;
use Seeddms\Console\Commands\ConfigureextensionCommand;
use Seeddms\Console\Commands\PackageextensionCommand;
use Seeddms\Console\Commands\ReloadextensionCommand;
use Seeddms\Seeddms\Settings;
use Seeddms\Seeddms\Translator;
$settings = new Settings();
/* For now includce inc.Language.php, because it defines the old
* translation functions (e.g. getMLText()), which is still used
* by many extensions.
*/
require_once('inc/inc.Language.php');
//$translator = new Translator($settings);
//$translator->init();
$logger = getLogger($settings, 'console-');
require_once('inc/inc.Extension.php');
$application = new Application();
$application->add(new StatsCommand($settings, $logger, $translator));
$application->add(new AddfolderCommand($settings, $logger, $translator));
$application->add(new AdddocumentCommand($settings, $logger, $translator, $extmgr));
$application->add(new DeleteCommand($settings, $logger, $translator));
$application->add(new ClearcacheCommand($settings, $logger, $translator));
$application->add(new ListcacheCommand($settings, $logger, $translator));
$application->add(new ListextensionCommand($settings, $logger, $translator, $extmgr));
$application->add(new ConfigureextensionCommand($settings, $logger, $translator, $extmgr));
$application->add(new PackageextensionCommand($settings, $logger, $translator, $extmgr));
$application->add(new ReloadextensionCommand($settings, $logger, $translator, $extmgr));
if(isset($GLOBALS['SEEDDMS_HOOKS']['console'])) {
foreach($GLOBALS['SEEDDMS_HOOKS']['console'] as $hookObj) {
if (method_exists($hookObj, 'addCommand')) {
$hookObj->addCommand($application, ['settings'=>$settings, 'logger'=>$logger, 'translator'=>$translator, 'extmgr'=>$extmgr]);
}
}
}
$application->run();