public function sendMessage($payload, $recipients, $from) { $defaultValues = ['response_to' => null]; $payload = array_merge($defaultValues, $payload); $insert = new Insert($this->getTable()); $insert->columns(['from', 'subject', 'message'])->values(['from' => $from, 'subject' => $payload['subject'], 'message' => $payload['message'], 'datetime' => DateUtils::now(), 'response_to' => $payload['response_to']]); $rows = $this->insertWith($insert); $messageId = $this->lastInsertValue; // Insert recipients $values = []; foreach ($recipients as $recipient) { $read = 0; if ((int) $recipient == (int) $from) { $read = 1; } $values[] = '(' . $messageId . ', ' . $recipient . ', ' . $read . ')'; } $valuesString = implode(',', $values); //@todo sanitize and implement ACL $sql = 'INSERT INTO directus_messages_recipients (`message_id`, `recipient`, `read`) VALUES ' . $valuesString; $result = $this->adapter->query($sql, Adapter::QUERY_MODE_EXECUTE); return $messageId; }
public function preSaveDataHook(array $rowData, $rowExistsInDatabase = false) { $log = Bootstrap::get('log'); if (isset($rowData['id'])) { $logger = Bootstrap::get('log'); $TableGateway = new AclAwareTableGateway($this->acl, $this->table, $this->sql->getAdapter()); $dbRecord = $TableGateway->find($rowData['id']); if (false === $dbRecord) { // @todo is it better to throw an exception here? $rowExistsInDatabase = false; } } // User is updating themselves. // Corresponds to a ping indicating their last activity. // Updated their "last_access" value. if (AuthProvider::loggedIn()) { $currentUser = AuthProvider::getUserInfo(); if (isset($rowData['id']) && $rowData['id'] == $currentUser['id']) { $rowData['last_access'] = DateUtils::now(); } } return $rowData; }
public function manageRecordUpdate($tableName, $recordData, $activityEntryMode = self::ACTIVITY_ENTRY_MODE_PARENT, &$childLogEntries = null, &$parentCollectionRelationshipsChanged = false, $parentData = []) { $TableGateway = $this; if ($tableName !== $this->table) { $TableGateway = new RelationalTableGateway($this->acl, $tableName, $this->adapter); } $recordIsNew = !array_key_exists($TableGateway->primaryKeyFieldName, $recordData); $schemaArray = TableSchema::getSchemaArray($tableName); $currentUser = AuthProvider::getUserRecord(); // Upload file if necessary $TableGateway->copyFiles($tableName, $recordData); // Delete file if necessary $TableGateway->deleteFiles($tableName, $recordData); //Dont do for directus users since id is pk if ($recordIsNew && $tableName != 'directus_users') { $cmsOwnerColumnName = $this->acl->getCmsOwnerColumnByTable($tableName); if ($cmsOwnerColumnName) { $recordData[$cmsOwnerColumnName] = $currentUser['id']; } } //Dont let non-admins make admins if ($tableName == 'directus_users' && $currentUser['group'] != 1) { if (isset($recordData['group']) && $recordData['group']['id'] == 1) { unset($recordData['group']); } } $thisIsNested = $activityEntryMode == self::ACTIVITY_ENTRY_MODE_CHILD; // Recursive functions will change this value (by reference) as necessary // $nestedCollectionRelationshipsChanged = $thisIsNested ? $parentCollectionRelationshipsChanged : false; $nestedCollectionRelationshipsChanged = false; if ($thisIsNested) { $nestedCollectionRelationshipsChanged =& $parentCollectionRelationshipsChanged; } // Recursive functions will append to this array by reference // $nestedLogEntries = $thisIsNested ? $childLogEntries : []; $nestedLogEntries = []; if ($thisIsNested) { $nestedLogEntries =& $childLogEntries; } // Update and/or Add Many-to-One Associations $parentRecordWithForeignKeys = $TableGateway->addOrUpdateManyToOneRelationships($schemaArray, $recordData, $nestedLogEntries, $nestedCollectionRelationshipsChanged); // Merge the M21 foreign keys into the recordData array $recordData = array_merge($recordData, $parentRecordWithForeignKeys); // If more than the record ID is present. $newRecordObject = null; $parentRecordChanged = $this->recordDataContainsNonPrimaryKeyData($parentRecordWithForeignKeys); // || $recordIsNew; if ($parentRecordChanged) { // Update the parent row, w/ any new association fields replaced by their IDs $newRecordObject = $TableGateway->addOrUpdateRecordByArray($parentRecordWithForeignKeys); if (!$newRecordObject) { return []; } if ($newRecordObject) { $newRecordObject = $newRecordObject->toArray(); } } // Do it this way, because & byref for outcome of ternary operator spells trouble $draftRecord =& $parentRecordWithForeignKeys; if ($recordIsNew) { $draftRecord =& $newRecordObject; } // Restore X2M relationship / alias fields to the record representation & process these relationships. $collectionColumns = TableSchema::getAllAliasTableColumns($tableName); foreach ($collectionColumns as $collectionColumn) { $colName = $collectionColumn['id']; if (isset($recordData[$colName])) { $draftRecord[$colName] = $recordData[$colName]; } } // parent if ($activityEntryMode === self::ACTIVITY_ENTRY_MODE_PARENT) { $parentData = ['id' => array_key_exists($this->primaryKeyFieldName, $recordData) ? $recordData[$this->primaryKeyFieldName] : null, 'table_name' => $tableName]; } $draftRecord = $TableGateway->addOrUpdateToManyRelationships($schemaArray, $draftRecord, $nestedLogEntries, $nestedCollectionRelationshipsChanged, $parentData); $rowId = $draftRecord[$this->primaryKeyFieldName]; $columnNames = TableSchema::getAllNonAliasTableColumnNames($tableName); $TemporaryTableGateway = new TableGateway($tableName, $this->adapter); $fullRecordData = $TemporaryTableGateway->select(function ($select) use($rowId, $columnNames) { $select->where->equalTo($this->primaryKeyFieldName, $rowId); $select->limit(1)->columns($columnNames); })->current(); if (!$fullRecordData) { $recordType = $recordIsNew ? 'new' : 'pre-existing'; throw new \RuntimeException('Attempted to load ' . $recordType . ' record post-insert with empty result. Lookup via row id: ' . print_r($rowId, true)); } $fullRecordData = (array) $fullRecordData; $deltaRecordData = $recordIsNew ? [] : array_intersect_key((array) $parentRecordWithForeignKeys, (array) $fullRecordData); switch ($activityEntryMode) { // Activity logging is enabled, and I am a nested action case self::ACTIVITY_ENTRY_MODE_CHILD: $logEntryAction = $recordIsNew ? DirectusActivityTableGateway::ACTION_ADD : DirectusActivityTableGateway::ACTION_UPDATE; $childLogEntries[] = ['type' => DirectusActivityTableGateway::makeLogTypeFromTableName($this->table), 'table_name' => $tableName, 'action' => $logEntryAction, 'user' => $currentUser['id'], 'datetime' => DateUtils::now(), 'parent_id' => isset($parentData['id']) ? $parentData['id'] : null, 'parent_table' => isset($parentData['table_name']) ? $parentData['table_name'] : null, 'data' => json_encode($fullRecordData), 'delta' => json_encode($deltaRecordData), 'parent_changed' => (int) $parentRecordChanged, 'row_id' => $rowId, 'identifier' => $this->findRecordIdentifier($schemaArray, $fullRecordData), 'logged_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '', 'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '']; if ($recordIsNew) { /** * This is a nested call, creating a new record w/in a foreign collection. * Indicate by reference that the top-level record's relationships have changed. */ $parentCollectionRelationshipsChanged = true; } break; case self::ACTIVITY_ENTRY_MODE_PARENT: // Does this act deserve a log? $parentRecordNeedsLog = $nestedCollectionRelationshipsChanged || $parentRecordChanged; /** * NESTED QUESTIONS! * @todo what do we do if the foreign record OF a foreign record changes? * is that activity entry also directed towards this parent activity entry? * @todo how should nested activity entries relate to the revision histories of foreign items? * @todo one day: treat children as parents if this top-level record was not modified. */ $recordIdentifier = $this->findRecordIdentifier($schemaArray, $fullRecordData); // Produce log if something changed. if ($parentRecordChanged || $nestedCollectionRelationshipsChanged) { $logEntryAction = $recordIsNew ? DirectusActivityTableGateway::ACTION_ADD : DirectusActivityTableGateway::ACTION_UPDATE; //If we are updating and active is being set to 0 then we are deleting if (!$recordIsNew && array_key_exists(STATUS_COLUMN_NAME, $deltaRecordData)) { if ($deltaRecordData[STATUS_COLUMN_NAME] == STATUS_DELETED_NUM) { $logEntryAction = DirectusActivityTableGateway::ACTION_DELETE; } } // Save parent log entry $parentLogEntry = AclAwareRowGateway::makeRowGatewayFromTableName($this->acl, 'directus_activity', $this->adapter); $logData = ['type' => DirectusActivityTableGateway::makeLogTypeFromTableName($this->table), 'table_name' => $tableName, 'action' => $logEntryAction, 'user' => $currentUser['id'], 'datetime' => DateUtils::now(), 'parent_id' => null, 'data' => json_encode($fullRecordData), 'delta' => json_encode($deltaRecordData), 'parent_changed' => (int) $parentRecordChanged, 'identifier' => $recordIdentifier, 'row_id' => $rowId, 'logged_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '', 'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '']; $parentLogEntry->populate($logData, false); $parentLogEntry->save(); // Update & insert nested activity entries $ActivityGateway = new DirectusActivityTableGateway($this->acl, $this->adapter); foreach ($nestedLogEntries as $entry) { $entry['parent_id'] = $rowId; // @todo ought to insert these in one batch $ActivityGateway->insert($entry); } } break; } // Yield record object $recordGateway = new AclAwareRowGateway($this->acl, $TableGateway->primaryKeyFieldName, $tableName, $this->adapter); $recordGateway->populate($fullRecordData, true); return $recordGateway; }
public static function getTable($tbl_name) { $acl = Bootstrap::get('acl'); $zendDb = Bootstrap::get('ZendDb'); // TODO: getTable should return an empty object // or and empty array instead of false // in any given situation that the table // can be find or used. if (!self::canGroupViewTable($tbl_name)) { return false; } $info = SchemaManager::getTable($tbl_name); if (!$info) { return false; } if ($info) { $info['count'] = (int) $info['count']; $info['date_created'] = DateUtils::convertToISOFormat($info['date_created'], 'UTC', get_user_timezone()); $info['hidden'] = (bool) $info['hidden']; $info['single'] = (bool) $info['single']; $info['footer'] = (bool) $info['footer']; } $relationalTableGateway = new RelationalTableGateway($acl, $tbl_name, $zendDb); $info = array_merge($info, $relationalTableGateway->countActiveOld()); $info['columns'] = self::getSchemaArray($tbl_name); $directusPreferencesTableGateway = new DirectusPreferencesTableGateway($acl, $zendDb); $currentUser = Auth::getUserInfo(); $info['preferences'] = $directusPreferencesTableGateway->fetchByUserAndTable($currentUser['id'], $tbl_name); return $info; }
$i++; } foreach ($userRecipients as $recipient) { $usersTableGateway = new DirectusUsersTableGateway($acl, $ZendDb); $user = $usersTableGateway->findOneBy('id', $recipient); if (isset($user) && $user['email_messages'] == 1) { $data = ['message' => $requestPayload['message']]; $view = 'mail/notification.twig.html'; Mail::send($view, $data, function ($message) use($user, $requestPayload) { $message->setSubject($requestPayload['subject']); $message->setTo($user['email']); }); } } } $requestPayload['datetime'] = DateUtils::now(); $newRecord = $TableGateway->manageRecordUpdate('directus_messages', $requestPayload, TableGateway::ACTIVITY_ENTRY_MODE_DISABLED); $params['id'] = $newRecord['id']; // GET all table entries $entries = $TableGateway->getEntries($params); JsonView::render($entries); }); /** * EXCEPTION LOG */ //$app->post("/$v/exception/?", function () use ($params, $requestPayload, $app, $acl, $ZendDb) { // print_r($requestPayload);die(); // $data = array( // 'server_addr' =>$_SERVER['SERVER_ADDR'], // 'server_port' =>$_SERVER['SERVER_PORT'], // 'user_agent' =>$_SERVER['HTTP_USER_AGENT'],
/** * Creates a new file for Directus Media * * @param string $filePath * @param string $targetName * * @return Array file info */ private function processUpload($filePath, $targetName) { // set true as $filePath it's outside adapter path // $filePath is on a temporary php directory $fileData = $this->getFileInfo($filePath, true); $mediaPath = $this->filesystem->getPath(); $fileData['title'] = Formatting::fileNameToFileTitle($targetName); $targetName = $this->getFileName($targetName); $finalPath = rtrim($mediaPath, '/') . '/' . $targetName; $data = file_get_contents($filePath); $this->emitter->run('files.saving', ['name' => $targetName, 'size' => strlen($data)]); $this->filesystem->getAdapter()->write($targetName, $data); $this->emitter->run('files.saving:after', ['name' => $targetName, 'size' => strlen($data)]); $fileData['name'] = basename($finalPath); $fileData['date_uploaded'] = DateUtils::now(); $fileData['storage_adapter'] = $this->config['adapter']; return $fileData; }
public function recordMessage($data, $userId) { if (isset($data['response_to']) && $data['response_to'] > 0) { $action = 'REPLY'; } else { $action = 'ADD'; } $logData = ['type' => self::TYPE_MESSAGE, 'table_name' => 'directus_messages', 'action' => $action, 'user' => $userId, 'datetime' => DateUtils::now(), 'parent_id' => null, 'data' => json_encode($data), 'delta' => '[]', 'identifier' => $data['subject'], 'row_id' => $data['id'], 'logged_ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '', 'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '']; $insert = new Insert($this->getTable()); $insert->values($logData); $this->insertWith($insert); }
public function convertDates(array $records, array $schemaArray, $tableName = null) { $tableName = $tableName === null ? $this->table : $tableName; if (!SchemaManager::isDirectusTable($tableName)) { return $records; } // ========================================================================== // hotfix: records sometimes are no set as an array of rows. // NOTE: this code is duplicate @see: AbstractSchema::parseRecordValuesByType // ========================================================================== $singleRecord = false; if (!is_numeric_keys_array($records)) { $records = [$records]; $singleRecord = true; } foreach ($records as $index => $row) { foreach ($schemaArray as $column) { if (in_array(strtolower($column['type']), ['timestamp', 'datetime'])) { $columnName = $column['id']; if (array_key_exists($columnName, $row)) { $records[$index][$columnName] = DateUtils::convertToISOFormat($row[$columnName], 'UTC', get_user_timezone()); } } } } return $singleRecord ? reset($records) : $records; }
public function testPassed() { $datetime = new DateTime('now'); $datetime->modify('-1 days'); $this->assertTrue(DateUtils::hasPassed($datetime)); $datetime->modify('2 days'); $this->assertFalse(DateUtils::hasPassed($datetime)); $datetime->modify('-3 days'); $this->assertTrue(DateUtils::hasPassed($datetime->format('Y-m-d H:i:s'))); $datetime->modify('4 days'); $this->assertFalse(DateUtils::hasPassed($datetime->format('Y-m-d H:i:s'))); }