Jump to content

Brew Digital

Clients
  • Posts

    17
  • Joined

  • Last visited

 Content Type 

Downloads

Release Notes

IPS4 Guides

IPS4 Developer Documentation

Invision Community Blog

Development Blog

Deprecation Tracker

Providers Directory

Forums

Events

Store

Gallery

Everything posted by Brew Digital

  1. Yes, understood. Dev is under a different license on another account.
  2. Yes, that is the setup we are trying to do. There is the current production site which is fine as it is, then the QA environment requires an update to the URL as it has been replaced. This is the part where I cannot reset via the client portal or enter the {license}-TESTINSTALL as it says the URL has already been assigned. This results in one live environment, one test one as per the license. The request is to simply swap staging.xxx.org to xxx-test.co.uk.
  3. How can we then update the Test URL to the location of the new staging environment? We have three environments: Dev QA Production With QA and Production wanting to exist on the same license, one being the test URL. Essentially the staging.xxx.org instance no longer exists, we are trying to update it to: www.xxx-test.co.uk. Applying the license key reports back that there is an active test instance.
  4. Hello, We are doing some housekeeping and are looking to change the naming scheme used for our Production and Q/A environments, unfortunately, when trying to reset the license URLs to update them, this message occurs: Any help here is greatly appreciated. Thank you.
  5. We have upgraded from version 4.5.4.2 at that point all of this functionality still worked. So the API connection is setup through this class (slightly amended to remove some comments etc.) <?php namespace IPS\pslshare; class InvisionAPI { private $db; private $apiUrl; private $apiKey; private $curl; private $endpointUrl; public function __construct($apiUrl, $apiKey) { $this->db = \IPS\Db::i(); $this->apiUrl = $apiUrl; $this->apiKey = $apiKey; $this->curl = null; $this->endpointUrl = ''; } public function __destruct() { $this->closeCurl(); } public function getEndpointUrl() { return $this->endpointUrl; } /** * @param $endpoint * @param string $params * @throws \Exception */ private function initCurl($endpoint, $params = '') { $queryString = (!empty($params)) ? '?' . $params : ''; $this->endpointUrl = $this->apiUrl . $endpoint . $queryString; $this->curl = curl_init($this->endpointUrl); if (!$this->curl) { throw new \Exception('Failed to initialise cURL'); } curl_setopt_array( $this->curl, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPAUTH => CURLAUTH_BASIC, CURLOPT_USERPWD => "{$this->apiKey}:" ] ); } private function convertArrayToString(array $array) { return http_build_query($array); } private function setupPost(array $fields) { curl_setopt_array( $this->curl, [ CURLOPT_POST => count($fields), CURLOPT_POSTFIELDS => $this->convertArrayToString($fields) ] ); } private function closeCurl() { if (isset($this->curl)) { curl_close($this->curl); } } /** * @return bool|string * @throws \Exception */ private function processRequest() { $response = curl_exec($this->curl); if ($response === false) { throw new \Exception(curl_error($this->curl), curl_errno($this->curl)); } return $response; } private function requestPost($endpoint, $fields) { try { $this->initCurl($endpoint); $this->setupPost($fields); return $this->processRequest(); } catch (\Exception $e) { trigger_error(sprintf('Curl failed with error #%d: %s', $e->getCode(), $e->getMessage()), E_USER_ERROR); } } private function generateRandomString($length) { $keyspace = '0123456789bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ'; $str = ''; $max = \mb_strlen($keyspace, '8bit') - 1; for ($i = 0; $i < $length; ++$i) { $str .= $keyspace[\random_int(0, $max)]; } return $str; } private function generateUniqueReference($databaseID, $length = 15) { do { $ref = $this->generateRandomString($length); $count = $this->db->select( 'COUNT(*) as count', 'cms_custom_database_' . $databaseID, ['field_33 = ?', $ref] )->first(); } while ($count >= 1); return $ref; } public function createDatabasePage($databaseID, $categoryID, $authorID, $fields, $tags, $hidden = 1, $anonymous) { $fields[33] = $this->generateUniqueReference($databaseID); if (empty($fields[2])) { $fields[2] = ' '; } if (!empty($fields[7])) { $fields[7] = \strtotime($fields[7]); } if (!empty($fields[29])) { $fields[29] = \strtotime($fields[29]); } if (!empty($fields[30])) { $fields[30] = \strtotime($fields[30]); } if (!empty($fields[31])) { $fields[31] = \strtotime($fields[31]); } if (!empty($fields[36])) { $fields[36] = \strtotime($fields[36]); } $anonymousBool = $anonymous; $fields = [ 'category' => $categoryID, 'author' => $authorID, 'fields' => $fields, 'tags' => $tags, 'hidden' => $hidden, 'ip_address' => $_SERVER['REMOTE_ADDR'], 'anonymous' => $anonymousBool ]; return $this->requestPost('cms/records/' . $databaseID, $fields); } } The $anonymousBool in there is the only recent addition to obviously give the ability for the post to be anonymous, everything else is legacy. The class is called through this (also removed a chunk of this for legibility and brevity sake, anything outside of this that you think would be useful let me know. protected function post() { $member = \IPS\Member::loggedIn(); $api = new InvisionAPI($this->baseURL . '/api/', $apiKey); $submission = _handleFormFields(); $response = $api->createDatabasePage( $databaseID, $submission['category'], $authorID, $submission['fields'], $submission['tags'], $requiresModerating, $submission['anonymous'], ); exit(); } function _handleFormFields() { $category = null; $tags = null; $authorVisibility = null; $customFields = []; foreach ($_POST as $key => $value) { switch ($key) { case 'article-type' : $customFields[3] = $value; break; case 'content-type' : $customFields[4] = $value; break; case 'category' : $category = \intval($value); break; case 'tags' : $tags = $value; break; case 'author-visibility' : $authorVisibility = $value === 'anonymous' ? 1 : 0; break; default : if (\mb_strpos($key, 'field_') !== false) { if (\is_array($value)) { $value = \implode(',', $value); } $customFields[_removePrefix($key, 'field_')] = $value; } } } return [ 'category' => $category, 'tags' => $tags, 'author-visibility' => $authorVisibility, 'anonymous' => $authorVisibility, 'fields' => $customFields ]; } Massive thanks for any assistance given on this front.
  6. Yes it worked on an older version of Invision and as I'm trying to update it, it's why I am now running into problems.
  7. I can try and share a little more about the code, but my knowledge is limited by the fact that I have inherited this and didn't originally build it, so if it has been gone about the wrong way, please do let me know. The app itself was requested by the client to be a more bespoke way of handling the whole process of creating a topic, they have a lot of custom category and tag information that wanted to display in a very specific way. So one of my predecessors has written the application as a multi-step form with various methods for managing the interactions back with the custom database instance, done via the REST API as you have discovered, 99% of it works perfectly fine, just having issues with this handling of the standalone 'attachments' field (yes I know they could be using the attachments in the content fields as well). So the method that handles the attachments did look like this: function _handleFormUploads($customFields, $maxFileSize, $allowedFileTypes) { $attachments = []; foreach ($_FILES as $key => $file) { if (\mb_strpos($key, 'field_') !== false) { // First ensure file key is named as expected before handling it if (!empty($file['name']) && \is_array($file['name'])) { // Multiple file upload $file = _parseMultiUpload($file); foreach ($file as $f) { $attachments[_removePrefix($key, 'field_')][] = $f; } } else { // Single file upload $attachments[_removePrefix($key, 'field_')][] = $file; } } } foreach ($attachments as $fieldID => $files) { foreach ($files as $file) { \IPS\File::validateUpload($file, $allowedFileTypes, $maxFileSize); $file = \IPS\File::create('core_Attachment', $file['name'], null, null, false, $file['tmp_name'], true); if ($file instanceof \IPS\File) { // Store the resultant file path via the API request if (array_key_exists($fieldID, $customFields)) { $customFields[$fieldID] .= ',' . $file->container . '/' . $file->filename; } else { $customFields[$fieldID] = $file->container . '/' . $file->filename; } } } } return $customFields; } I've tried hacking around that as mentioned above to get the upload data to save into the db but with no joy. As I say if this is definitely NOT the way to go about doing this sort of thing then do tell me, but if there is a way that it can be made to work I would be very interested. Like I say I am still learning Invision, so apologies if I am making terrible schoolboy errors.
  8. Yep, sorry I should have been clearer with that. A little context, the custom app posts various fields of information and has a standalone 'uploads' field that is causing the problem here, when it's left blank all is good. Anyway the error code I'm getting back currently is this: { "status": false, "message": "Submission failed", "data": { "error": { "errorCode": "1S306/E", "errorMessage": "UPLOAD_FIELD_NOT_OBJECT" } } } Not sure where else I can go to get anything better, can't see anything in the logs from when I've just replicated that error on my local setup. I'm reasonably new to the Invision development world (not to dev) so still getting familiar with the code that I have inherited. If you know of anything else I can provide to possibly help debug the situation that would be really helpful.
  9. Hi all, I've got an application that has an upload field that is giving me the "UPLOAD_FIELD_NOT_OBJECT" error, it's an app that we have had for several years and has worked on older versions of Invision. I understand why it's giving me the error and everything, but the attachments that I am using are actually being put in the uploads folder, it's just failing at the point of inserting the data into the custom database. Traditionally we have always just stored a reference to the file and it's folder and that has been fine. My main question on it is can I carry on with just storing the file reference rather than storing the upload object? So the code I have currently gets all of the attached files from the PHP $_FILES global and then sorts through the attachments and constructs strings to be inserted on the field in the database like this foreach ($attachments as $fieldID => $files) { foreach ($files as $file) { \IPS\File::validateUpload($file, $allowedFileTypes, $maxFileSize); $file = \IPS\File::create('core_Attachment', $file['name'], null, null, false, $file['tmp_name'], true); if ($file instanceof \IPS\File) { if (array_key_exists($fieldID, $customFields)) { $customFields[$fieldID] .= ',' . $file->container . '/' . $file->filename; } else { $customFields[$fieldID] = $file->container . '/' . $file->filename; } } } } I've tried doing things like: $customFields[$fieldID][$file->filename] = (string) $file; as I've seen people talking about using the file object in that sort of way. If all of that looks completely wrong let me know, any help or just thoughts as to another approach would greatly appreciated
  10. Thanks for the reply, I have actually sorted this one, turned out my code was perfectly fine and it was the anonymous posting abilities of the users on the categories that was the issue.
  11. Hi, not sure if I need follow on from this question or not, we have an old app that still works fine, running against the /cms/records API endpoint, but were hoping to add 'anonymous' onto the postfields, they were initially in the same urlencode format that Simon had above, so I've changed the fields to be in the array format suggested and added anonymous in, something like this CURLOPT_POSTFIELDS => [ 'author' => 2, 'category' => 4, 'fields[1]' => 'title', ... 'anonymous' => 1 ] This doesn't seem to post correctly at all, in fact I get the weird single character issue mentioned above. I've tried adding the anonymous into the URL encoded string as well, that still posts the data fine but doesn't do anything with the anonymous value (ie it remains at 0 in the custom table). Apologies if this is the wrong place to ask the question, but any help, or just just any thoughts about it at all, would be greatly appreciated.
  12. We are currently using ‘getItemsWithPermission’ to pull topics into a sidebar, we aren’t sure if that should be filtering the posts according to users who can ‘read’ the posts or not. We have a private forum whose posts are showing in that initial list so have been using ‘$topic->canView()’ wrapped around the content which seems to do what we require. So is that the right way to do this? Or should we be able to filter to users that can view a post with only ‘getItemsWithPermission’?
×
×
  • Create New...