diff --git a/src/admin/pages/lists/items-page.vue b/src/admin/pages/lists/items-page.vue index 7a7cf1740..e5f32b108 100644 --- a/src/admin/pages/lists/items-page.vue +++ b/src/admin/pages/lists/items-page.vue @@ -6,6 +6,7 @@ + +
@@ -569,7 +578,58 @@ !openAdvancedSearch"/>
- + +
+ @@ -604,7 +664,8 @@ advancedSearchResults: false, isDoSearch: false, searchControlHeight: 0, - sortingMetadata: [] + sortingMetadata: [], + isFilterModalActive: false } }, props: { @@ -1300,6 +1361,7 @@ } + diff --git a/src/admin/scss/theme-basics.sass b/src/admin/scss/theme-basics.sass index 66fc44491..a7f2953f1 100644 --- a/src/admin/scss/theme-basics.sass +++ b/src/admin/scss/theme-basics.sass @@ -7,3 +7,4 @@ @import "../../../node_modules/bulma/sass/components/tabs.sass" @import "../../../node_modules/bulma/sass/elements/button.sass" @import "../../../node_modules/bulma/sass/grid/columns.sass" +@import "../../../node_modules/bulma/sass/components/modal.sass" diff --git a/src/admin/theme-items-list.vue b/src/admin/theme-items-list.vue index a8d5a59f4..ec967a562 100644 --- a/src/admin/theme-items-list.vue +++ b/src/admin/theme-items-list.vue @@ -24,16 +24,17 @@ export default { // Buefy imports @import "../../node_modules/buefy/src/scss/components/_datepicker.scss"; - $speed-slow: 0.5s; - @import "../../node_modules/buefy/src/scss/utils/_functions.scss"; + @import "../../node_modules/buefy/src/scss/utils/_all.scss"; @import "../../node_modules/buefy/src/scss/components/_checkbox.scss"; @import "../../node_modules/buefy/src/scss/components/_radio.scss"; @import "../../node_modules/buefy/src/scss/components/_tag.scss"; @import "../../node_modules/buefy/src/scss/components/_loading.scss"; @import "../../node_modules/buefy/src/scss/components/_dropdown.scss"; + @import "../../node_modules/buefy/src/scss/components/_modal.scss"; // Tainacan imports @import "../admin/scss/_tables.scss"; + @import "../admin/scss/_modals.scss"; @import "../admin/scss/_pagination.scss"; @import "../admin/scss/_tags.scss"; @import "../admin/scss/_selects.scss"; @@ -269,5 +270,33 @@ export default { } } + .filters-mobile-modal { + // top: 95px; + + .modal-close { + right: calc(8.3333333% + 20px); + background-color: $gray1; + + &:hover { + background-color: $gray1; + } + &::before, &::after { + background-color: $secondary; + } + } + .modal-content { + margin: 0 8.3333333% 0 0; + padding: 24px $page-side-padding; + border-radius: 0; + height: 100%; + max-height: 100%; + overflow-y: auto; + + h3 { + font-size: 100%; + } + } + } + } diff --git a/src/classes/class-tainacan-background-process.php b/src/classes/class-tainacan-background-process.php index c362bf0f5..81af266e5 100644 --- a/src/classes/class-tainacan-background-process.php +++ b/src/classes/class-tainacan-background-process.php @@ -254,33 +254,35 @@ abstract class Background_Process extends \WP_Background_Process { // while we are debugging performance $newRequest = true; - - do { - $batch = $this->get_batch(); + $batch = $this->get_batch(); - if ($newRequest) { - $this->write_log($batch->key, ['New Request']); - $newRequest = false; - } - - // TODO: find a way to catch and log PHP errors as + if ($newRequest) { + $this->write_log($batch->key, ['New Request']); + $newRequest = false; + } + + // TODO: find a way to catch and log PHP errors as + + $task = $batch; + + do { try { - $task = $this->task( $batch ); + $task = $this->task( $task ); } catch (\Exception $e) { // TODO: Add Stacktrace $this->write_error_log($batch->key, ['Fatal Error: ' . $e->getMessage()]); $this->write_error_log($batch->key, ['Process aborted']); $task = false; } - + } while ( false !== $task && ! $this->time_exceeded() && ! $this->memory_exceeded() ); - // Update or close current batch. - if ( false !== $task ) { - $this->update( $batch->key, $task ); - } else { - $this->close( $batch->key ); - } - } while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() ); + + + if ( false !== $task ) { + $this->update( $batch->key, $task ); + } else { + $this->close( $batch->key ); + } $this->unlock_process(); @@ -389,5 +391,5 @@ abstract class Background_Process extends \WP_Background_Process { return $return; } - + } diff --git a/src/classes/libs/wp-background-process.php b/src/classes/libs/wp-background-process.php index 03e3a3e1d..942d4ca5b 100644 --- a/src/classes/libs/wp-background-process.php +++ b/src/classes/libs/wp-background-process.php @@ -59,9 +59,15 @@ if ( ! class_exists( 'WP_Background_Process' ) ) { $this->cron_hook_identifier = $this->identifier . '_cron'; $this->cron_interval_identifier = $this->identifier . '_cron_interval'; + $this->cron_hook_check_identifier = $this->identifier . '_cron_check'; add_action( $this->cron_hook_identifier, array( $this, 'handle_cron_healthcheck' ) ); + add_action( $this->cron_hook_check_identifier, array( $this, 'handle_cron_healthcheck_check' ) ); add_filter( 'cron_schedules', array( $this, 'schedule_cron_healthcheck' ) ); + + if ( ! wp_next_scheduled( $this->cron_hook_check_identifier ) ) { + wp_schedule_event( time(), $this->cron_interval_identifier, $this->cron_hook_check_identifier ); + } } /** @@ -451,6 +457,28 @@ if ( ! class_exists( 'WP_Background_Process' ) ) { exit; } + /** + * Checks the healthcheck + * + * If there is an open process, not running, and not scheduled. schedule it. + * + */ + public function handle_cron_healthcheck_check() { + if ( $this->is_process_running() ) { + // Background process already running. + exit; + } + + if ( $this->is_queue_empty() ) { + // No data to process. + $this->clear_scheduled_event(); + exit; + } + + $this->schedule_event(); + + } + /** * Schedule event */ diff --git a/src/classes/repositories/class-tainacan-repository.php b/src/classes/repositories/class-tainacan-repository.php index fd1ba8a93..74dbeb70c 100644 --- a/src/classes/repositories/class-tainacan-repository.php +++ b/src/classes/repositories/class-tainacan-repository.php @@ -13,6 +13,29 @@ defined( 'ABSPATH' ) or die( 'No script kiddies please!' ); abstract class Repository { public $entities_type = '\Tainacan\Entities\Entity'; + /** + * If set to false, no logs will be generated upon insertion or update + * + * use enable_logs() and disable_logs() to set the values + * @var bool + */ + private $use_logs = true; + + /** + * Disable creation of logs while inerting and updating entities + */ + public function disable_logs() { + $this->use_logs = false; + } + + /** + * Enable creation of logs while inerting and updating entities + * if it was disabled + */ + public function enable_logs() { + $this->use_logs = true; + } + /** * Register hooks */ @@ -81,19 +104,22 @@ abstract class Repository { $old = ''; $diffs = []; - if ( $obj->get_id() ) { - - $old = $obj->get_repository()->fetch( $obj->get_id() ); - - if ( method_exists( $old, 'get_status' ) && $old->get_status() === 'auto-draft' ) { - $is_update = false; - } else { - $is_update = true; + + if ($this->use_logs) { + if ( $obj->get_id() ) { + + $old = $obj->get_repository()->fetch( $obj->get_id() ); + + if ( method_exists( $old, 'get_status' ) && $old->get_status() === 'auto-draft' ) { + $is_update = false; + } else { + $is_update = true; + } + + $diffs = $this->diff( $old, $obj ); } - - $diffs = $this->diff( $old, $obj ); } - + $map = $this->get_map(); // First iterate through the native post properties @@ -137,9 +163,10 @@ abstract class Repository { } // TODO: Logs for header image insert and update - do_action( 'tainacan-insert', $obj, $diffs, $is_update ); - do_action( 'tainacan-insert-' . $obj->get_post_type(), $obj ); - + if ($this->use_logs) { + do_action( 'tainacan-insert', $obj, $diffs, $is_update ); + do_action( 'tainacan-insert-' . $obj->get_post_type(), $obj ); + } // return a brand new object return new $this->entities_type( $obj->WP_Post ); } diff --git a/src/importer/class-tainacan-csv.php b/src/importer/class-tainacan-csv.php index bc1cde265..dc4b83027 100644 --- a/src/importer/class-tainacan-csv.php +++ b/src/importer/class-tainacan-csv.php @@ -15,7 +15,7 @@ class CSV extends Importer { 'encode' => 'utf8', 'enclosure' => '"' ]); - + } /** @@ -125,17 +125,9 @@ class CSV extends Importer { } /** - * insert processed item from source to Tainacan, adapted to insert their attachments and document - * - * @param array $processed_item Associative array with metadatum source's as index with - * its value or values - * @param integer $collection_index The index in the $this->collections array of the collection the item is beeing inserted into - * - * @return Tainacan\Entities\Item Item inserted + * @inheritdoc */ - public function insert( $processed_item, $collection_index ) { - $inserted_item = parent::insert( $processed_item, $collection_index ); - + public function after_inserted_item( $inserted_item, $collection_index ) { $column_document = $this->get_option('document_index'); $column_attachment = $this->get_option('attachment_index'); @@ -155,8 +147,6 @@ class CSV extends Importer { $this->handle_attachment( $values[$column_attachment], $inserted_item); } } - - return $inserted_item; } /** @@ -308,6 +298,44 @@ class CSV extends Importer { * method responsible to insert the item document */ private function handle_attachment( $column_value, $item_inserted){ + $TainacanMedia = \Tainacan\Media::get_instance(); + $attachments = explode( $this->get_option('multivalued_delimiter'), $column_value); + + if( $attachments ){ + foreach( $attachments as $attachment ){ + + if( strpos($column_value,'file:') !== 0 ){ + $this->add_log('Attachment must have "file:" previously the path or url '); + continue; + } + + + $correct_value = substr($column_value, 5); + + if( filter_var($correct_value, FILTER_VALIDATE_URL) ){ + $id = $TainacanMedia->insert_attachment_from_url($correct_value, $item_inserted->get_id()); + + if(!$id){ + $this->add_log('Error in Attachment file imported from URL ' . $correct_value); + return false; + } + + $this->add_log('Attachment file URL imported from ' . $correct_value); + + continue; + } + + $server_path_files = $this->get_option('server_path'); + $id = $TainacanMedia->insert_attachment_from_file($correct_value, $item_inserted->get_id()); + + if(!$id){ + $this->add_log('Error in Attachment file imported from server ' . $correct_value); + continue; + } + + $this->add_log('Attachment file in Server imported from ' . $correct_value); + } + } } } \ No newline at end of file diff --git a/src/importer/class-tainacan-importer.php b/src/importer/class-tainacan-importer.php index ac18f61d0..9756c9d0c 100644 --- a/src/importer/class-tainacan-importer.php +++ b/src/importer/class-tainacan-importer.php @@ -757,7 +757,7 @@ abstract class Importer { */ public function insert( $processed_item, $collection_index ) { - $collections = $this->get_collections(); + $collections = $this->get_collections(); $collection_definition = isset($collections[$collection_index]) ? $collections[$collection_index] : false; if ( !$collection_definition || !is_array($collection_definition) || !isset($collection_definition['id']) || !isset($collection_definition['mapping']) ) { $this->add_error_log('Collection misconfigured'); @@ -768,11 +768,14 @@ abstract class Importer { $Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance(); $Tainacan_Item_Metadata = \Tainacan\Repositories\Item_Metadata::get_instance(); - $Tainacan_Items = \Tainacan\Repositories\Items::get_instance(); + $Tainacan_Items = \Tainacan\Repositories\Items::get_instance(); + + $Tainacan_Items->disable_logs(); + $Tainacan_Metadata->disable_logs(); $item = new Entities\Item(); - $itemMetadataArray = []; - + $itemMetadataArray = []; + if( is_array( $processed_item ) ){ foreach ( $processed_item as $metadatum_source => $values ){ $tainacan_metadatum_id = array_search( $metadatum_source, $collection_definition['mapping'] ); @@ -788,23 +791,23 @@ abstract class Importer { } } - + if( !empty( $itemMetadataArray ) && $collection instanceof Entities\Collection ){ $item->set_collection( $collection ); if( $item->validate() ){ - $insertedItem = $Tainacan_Items->insert( $item ); + $insertedItem = $Tainacan_Items->insert( $item ); } else { $this->add_error_log( 'Error inserting item' ); $this->add_error_log( $item->get_errors() ); return false; } - + foreach ( $itemMetadataArray as $itemMetadata ) { $itemMetadata->set_item( $insertedItem ); // *I told you if( $itemMetadata->validate() ){ - $result = $Tainacan_Item_Metadata->insert( $itemMetadata ); + $result = $Tainacan_Item_Metadata->insert( $itemMetadata ); } else { $this->add_error_log('Error saving value for ' . $itemMetadata->get_metadatum()->get_name()); $this->add_error_log($itemMetadata->get_errors()); @@ -818,18 +821,20 @@ abstract class Importer { //} else { // $this->add_error_log( 'Item ' . $insertedItem->get_id() . ' has an error' ); //} - } - - $insertedItem->set_status('publish' ); - + } + + $insertedItem->set_status('publish' ); + if($insertedItem->validate()) { - $insertedItem = $Tainacan_Items->update( $insertedItem ); + $insertedItem = $Tainacan_Items->update( $insertedItem ); + + $this->after_inserted_item( $insertedItem, $collection_index ); } else { $this->add_error_log( 'Error publishing Item' ); $this->add_error_log( $insertedItem->get_errors() ); return false; - } - + } + return $insertedItem; } else { @@ -837,7 +842,15 @@ abstract class Importer { return false; } - } + } + + /** + * allow importers executes process after item is insertes + * @param array $insertedItem Associative array with inserted item + * @param integer $collection_index The index in the $this->collections array of the collection the item is beeing inserted into + * + */ + public function after_inserted_item($insertedItem, $collection_index){} /** * runs one iteration diff --git a/tests/test-importer.php b/tests/test-importer.php index 9be66b2de..498c9504a 100644 --- a/tests/test-importer.php +++ b/tests/test-importer.php @@ -396,7 +396,7 @@ class ImporterTests extends TAINACAN_UnitTestCase { '458', utf8_decode( 'Data 33||Rééço' ), 'file:https://d33wubrfki0l68.cloudfront.net/1dbc465f56f3a812f09666f522fa226efd947cfa/a4d9f/images/smashing-cat/newsletter-fish-cat.svg||file:https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/58f72418-b5ee-4765-8e80-e463623a921d/01-httparchive-opt-small.png', - 'file:https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&h=350'), + 'file:https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg'), array('Data 41', '459', 'Data 43||limbbo', 'file:photos/SamplePNGImage_100kbmb.png||file:audios/SampleAudio_0.4mb.mp3', 'url:http://www.pdf995.com/samples/pdf.pdf'), array('Data 51', '500', 'Data 53', 'file:http://techslides.com/demos/samples/sample.mp4', '') );