From 626b354e23cbb70c4e41ffa19035c02497e4c0a0 Mon Sep 17 00:00:00 2001 From: Iain Saxon Date: Thu, 9 Jul 2015 17:24:14 +1000 Subject: [PATCH 1/3] Created new `create:channel_entry` command --- src/Command/CreateChannelEntryCommand.php | 337 ++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 src/Command/CreateChannelEntryCommand.php diff --git a/src/Command/CreateChannelEntryCommand.php b/src/Command/CreateChannelEntryCommand.php new file mode 100644 index 0000000..97a91c9 --- /dev/null +++ b/src/Command/CreateChannelEntryCommand.php @@ -0,0 +1,337 @@ +load->helper('security'); + + // load a super admin into the session + $query = ee()->db->where('members.group_id', 1) + ->join('member_groups', 'member_groups.group_id = members.group_id') + ->limit(1) + ->get('members'); + + // superadmin + ee()->session->userdata = $query->row_array(); + ee()->session->userdata['group_id'] = '1'; + ee()->session->userdata['assigned_template_groups'] = array(); + + $query->free_result(); + + // check first to avoid debug messages + if (false === isset(ee()->api)) { + ee()->load->library(array('api', 'stats')); + ee()->api->instantiate('channel_fields'); + ee()->api->instantiate('channel_entries'); + } + + $titleParam = $this->argument('title'); + $channelParam = $this->argument('channel'); + $urlTitleParam = $this->option('url_title'); + $authorParam = $this->option('author'); + $statusParam = $this->option('status'); + + // get the channel + $channel = $this->getChannel($channelParam); + $channelId = $channel['channel_id']; + + // was an author specified? + if ($authorParam) { + $author = $this->getAuthor($authorParam); + $authorId = $author['member_id']; + } else { + // user the super admin as the default author + $authorId = ee()->session->userdata('member_id'); + } + + $categories = array(); + $categoriesParam = $this->option('categories'); + + // were categories specified? + if (count($categoriesParam) > 0) { + $categories = $this->getCategories($categoriesParam); + } + + // set a default date + $nowDate = ee()->localize->format_date('%Y%m%d%H%i%s', ee()->localize->now); + + // build up an array the article data using the field names for convenience + $metaData = array( + 'title' => $titleParam, + 'url_title' => $urlTitleParam, + 'status' => $statusParam, + 'entry_date' => strtotime($nowDate), + 'edit_date' => $nowDate, + 'expiration_date' => null, + 'author_id' => (int) $authorId, + 'category' => (array) $categories, + 'channel_id' => $channelId, + ); + + $entryData = array(); + $entryFinalData = $metaData; + + // get the field mapping + $fieldMapping = $this->getFields(); + $fieldMappingKeys = array_keys($fieldMapping); + + // loop over the mapped data and create a new array using the field_id_# as the array key ready for API saving + foreach ($entryData as $entryDataKey => $entryDataVal) { + if (true === in_array($entryDataKey, $fieldMappingKeys)) { + $entryFinalData['field_id_' . $fieldMapping[$entryDataKey]] = $entryDataVal; + } else { + $entryFinalData[$entryDataKey] = $entryDataVal; + } + } + + // prep the channel fields API for saving + ee()->api_channel_fields->setup_entry_settings($channelId, $entryFinalData); + + // save the entry using the API + if (false === ee()->api_channel_entries->save_entry($entryFinalData, $channelId)) { + + throw new \RuntimeException('Could not create the new entry: ' . "\n\n" . implode("\n", ee()->api_channel_fields->errors)); + } + + $this->getApplication()->checkForErrors(true); + + $this->info(sprintf('Channel Entry "%s" created in "%s" channel.', $titleParam, $channel['channel_name'])); + } + + public function getLongDescription() + { + return 'Create a channel entry. Pass in an entry title wrapped in quotes and optionally pass in a url title using underscores only. If you exclude the url title, one will be auto-generated from your entry title.'; + } + + public function getExamples() + { + return array( + /* + 'Create a channel with the short name test_channel' => 'test_channel', + 'Create a channel with the title Test Channel' => 'test_channel "Test Channel"', + 'Create a channel with field group 5' => '--field_group=5 test_channel', + 'Create a channel with field group "Blog"' => '--field_group="Blog" test_channel', + 'Create a channel with status group "Statuses"' => '--status_group="Statuses" test_channel', + 'Create a channel with category group 5 and 6' => '--cat_group=5 --cat_group=6 test_channel', + 'Create a channel with category group "Apparel" and "Accessories"' => '--cat_group="Apparel" --cat_group="Accessories" test_channel', + 'Create a channel with new field group with same title as channel' => '--new_field_group test_channel', + */ + ); + } + + public function getOptionExamples() + { + return array( + /* + 'field_group' => '1', + 'status_group' => '1', + 'cat_group' => '1', + 'channel_url' => '/blog', + 'channel_description' => 'Your description here.', + 'default_entry_title' => 'Default Title', + 'url_title_prefix' => 'blog_', + 'deft_category' => '1', + */ + ); + } + + + /** + * Find the matching categories using the parameters + * + * @param array $categoriesParam + * + * @return array + */ + protected function getCategories($categoriesParam) + { + $categories = array(); + + // get the author if using the parameter + $query = ee()->db->select('cat_id, cat_url_title') + ->where_in('cat_id', $categoriesParam) + ->or_where_in('cat_url_title', $categoriesParam) + ->get('categories'); + + // no member found? quit now + if (0 === $query->num_rows()) { + throw new \RuntimeException(sprintf('Could not find categories for url titles or IDs "%s"', implode(', ', $categoriesParam))); + + return false; + } + + // add the valid categories to the collection + foreach ($query->result_array() as $categoryRow) { + $categories[] = $categoryRow['cat_id']; + } + + return $categories; + } + + /** + * Find the matching member using the parameters + * + * @param array $authorParam + * + * @return array + */ + protected function getAuthor($authorParam) + { + $author = array(); + + // get the author if using the parameter + $query = ee()->db->select('member_id, username') + ->where('member_id', intval($authorParam)) + ->or_where('username', $authorParam) + ->limit(1) + ->get('members'); + + // no member found? abort + if (0 === $query->num_rows()) { + throw new \RuntimeException(sprintf('Could not find member for username or ID "%s"', $authorParam)); + } + + $author = $query->row_array(); + + $query->free_result(); + + return $author; + } + + /** + * Find the matching channel using the parameters + * + * @param int|string $channelParam + * + * @return array + */ + protected function getChannel($channelParam) + { + $channel = array(); + + // get the channel + $query = ee()->db->select('channel_id, channel_name') + ->where('channel_id', intval($channelParam)) + ->or_where('channel_name', $channelParam) + ->limit(1) + ->get('channels'); + + // no channel found? quit now + if (0 === $query->num_rows()) { + throw new \RuntimeException(sprintf('Could not find channel for short name or ID "%s"', $channelParam)); + } + + $channel = $query->row_array(); + + $query->free_result(); + + return $channel; + } + + /** + * Get all fields from the database for now as key-value pairs + * + * @return array + */ + protected function getFields() + { + $fields = array(); + + // get the field names and ids + $query = ee()->db->select('field_id, field_name') + ->get('channel_fields'); + + $fields = array(); + foreach ($query->result_array() as $fieldRow) { + $fields[$fieldRow['field_id']] = $fieldRow['field_name']; + } + + $query->free_result(); + + return $fields; + } + +} + From 4f7ee402800673a3cf8fa8cb2f9f195483e3f980 Mon Sep 17 00:00:00 2001 From: Iain Saxon Date: Fri, 10 Jul 2015 17:33:19 +1000 Subject: [PATCH 2/3] Added basic functionality to include channel data when creating entries. --- src/Command/CreateChannelEntryCommand.php | 66 ++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/Command/CreateChannelEntryCommand.php b/src/Command/CreateChannelEntryCommand.php index 97a91c9..4a10866 100644 --- a/src/Command/CreateChannelEntryCommand.php +++ b/src/Command/CreateChannelEntryCommand.php @@ -72,6 +72,20 @@ protected function getOptions() InputOption::VALUE_REQUIRED, 'What is the author (member ID or username) for this channel?', ), + array( + 'stdin', // name + null, // shortcut + InputOption::VALUE_NONE, // mode + 'Use stdin as data contents.', // description + null, // default value + ), + array( + 'datatype', // name + null, // shortcut + InputOption::VALUE_REQUIRED, // mode + 'Declare the data type for the stdin content (json, serialize)', // description + 'json', // default value + ), ); } @@ -112,6 +126,7 @@ protected function fire() $urlTitleParam = $this->option('url_title'); $authorParam = $this->option('author'); $statusParam = $this->option('status'); + $stdInDataType = $this->option('datatype'); // get the channel $channel = $this->getChannel($channelParam); @@ -153,6 +168,11 @@ protected function fire() $entryData = array(); $entryFinalData = $metaData; + // are we accepting a data string to use for the entry? + if ($this->option('stdin')) { + $entryData = $this->processStdInData($stdInDataType); + } + // get the field mapping $fieldMapping = $this->getFields(); $fieldMappingKeys = array_keys($fieldMapping); @@ -217,6 +237,50 @@ public function getOptionExamples() ); } + /** + * Find the data coming from the stdin, transform it and return an array + * + * @param string $dataType + * + * @return array + */ + protected function processStdInData($dataType) + { + $entryData = array(); + + $handle = fopen('php://stdin', 'r'); + $inputData = ''; + while (($buffer = fgets($handle, 4096)) !== false) { + $inputData .= $buffer; + } + + switch ($dataType) { + case 'json': + $entryData = json_decode($inputData, true); + $jsonError = json_last_error(); + + // abort if the JSON is invalid + if (JSON_ERROR_NONE !== $jsonError) { + throw new \RuntimeException(sprintf('Invalid JSON received (code: %s)', $jsonError)); + } + + break; + case 'serialize': + $entryData = unserialize($inputData); + + // abort if the data is false as this is what `serialize` will return if there's a problem + if (false === $entryData) { + throw new \RuntimeException('Invalid serialized data received'); + } + + break; + default: + throw new \RuntimeException(sprintf('Invalid datatype "%s" option specified', $dataType)); + break; + } + + return $entryData; + } /** * Find the matching categories using the parameters @@ -325,7 +389,7 @@ protected function getFields() $fields = array(); foreach ($query->result_array() as $fieldRow) { - $fields[$fieldRow['field_id']] = $fieldRow['field_name']; + $fields[$fieldRow['field_name']] = $fieldRow['field_id']; } $query->free_result(); From 0144e9cedca00446ef2981a9130dc07a891145bb Mon Sep 17 00:00:00 2001 From: Iain Saxon Date: Fri, 10 Jul 2015 17:46:45 +1000 Subject: [PATCH 3/3] Expanded on the command examples --- src/Command/CreateChannelEntryCommand.php | 32 +++++++++-------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/Command/CreateChannelEntryCommand.php b/src/Command/CreateChannelEntryCommand.php index 4a10866..2a3081a 100644 --- a/src/Command/CreateChannelEntryCommand.php +++ b/src/Command/CreateChannelEntryCommand.php @@ -208,32 +208,24 @@ public function getLongDescription() public function getExamples() { return array( - /* - 'Create a channel with the short name test_channel' => 'test_channel', - 'Create a channel with the title Test Channel' => 'test_channel "Test Channel"', - 'Create a channel with field group 5' => '--field_group=5 test_channel', - 'Create a channel with field group "Blog"' => '--field_group="Blog" test_channel', - 'Create a channel with status group "Statuses"' => '--status_group="Statuses" test_channel', - 'Create a channel with category group 5 and 6' => '--cat_group=5 --cat_group=6 test_channel', - 'Create a channel with category group "Apparel" and "Accessories"' => '--cat_group="Apparel" --cat_group="Accessories" test_channel', - 'Create a channel with new field group with same title as channel' => '--new_field_group test_channel', - */ + 'Create an entry in channel "test_channel" with title "Test Entry"' => '"Test Entry" test_channel', + 'Create an entry in channel "test_channel" with title "Test Entry" and url_title "test-entry-2015"' => '"Test Entry" test_channel --url_title="test-entry-2015"', + 'Create an entry in channel "test_channel" with title "Test Entry" by an author member ID' => '"Test Entry" test_channel --author="1"', + 'Create an entry in channel "test_channel" with title "Test Entry" with "closed" status' => '"Test Entry" test_channel --status="closed"', + 'Create an entry in channel "test_channel" with title "Test Entry" with multiple categories' => '"Test Entry" test_channel --categories="trending" --categories="hip"', + 'Create an entry in channel "test_channel" with title "Test Entry" with entry data piped to the command as JSON' => '"Test Entry" test_channel --stdin --datatype=json', + 'Create an entry in channel "test_channel" with title "Test Entry" with entry data piped to the command as a serialized PHP object' => '"Test Entry" test_channel --stdin --datatype=serialize', ); } public function getOptionExamples() { return array( - /* - 'field_group' => '1', - 'status_group' => '1', - 'cat_group' => '1', - 'channel_url' => '/blog', - 'channel_description' => 'Your description here.', - 'default_entry_title' => 'Default Title', - 'url_title_prefix' => 'blog_', - 'deft_category' => '1', - */ + 'url_title' => 'my-test-entry-2015', + 'status' => 'draft', + 'categories' => 'trending', + 'author' => 'johndoe', + 'datatype' => 'json', ); }