: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
use NF_Exports_Interfaces_SubmissionCollectionInterface as SubmissionCollectionInterface;
use NF_Exports_SingleSubmissionCPT as SingleSubmission;
* Provides and stores collection of submissions for a single form using CPT
final class NF_Exports_SubmissionCollectionCPT implements SubmissionCollectionInterface {
* Array of NF field objects for the form id
* Constructed once, on first request requiring fields; after that, use
* previously retrieved property that can be filtered or adjusted as
* needed, reducing DB calls
* Array of labels keyed on field key
* Option to use admin_label set on request
* Array of field types keyed on field key
protected $fieldTypes = [];
* Array of field Ids keyed on field key
protected $fieldIds = [];
* Indexed array collection of single submissions
* @var SingleSubmission[]
protected $submissionCollection = [];
* Indexed array of field types to be omitted in output
protected $hiddenFieldTypes = [];
* Starting date for filtering submissions
protected $startDate = null;
* Ending date for filtering submissions
protected $endDate = null;
* Boolean to filter submissions by `isUnread?`
protected $isUnread = null;
* Boolean to filter submissions by `previouslyExported?`
protected $previouslyExported = null;
* Maximum amount of submissions to return in a single request
protected $maxReturnCount = null;
* Total count of submissions
* Count of submissions that have been marked `Unread`
protected $isUnreadCount;
* Count of submissions that have been previously exported
protected $previouslyExportedCount;
* Construct submission collection with provided form Id
* @param string|int $form_id
public function __construct($form_id) {
$this->formId = $form_id;
public function getFormId() {
return intval($this->formId);
public function getFormTitle() {
$form = Ninja_Forms()->form($this->formId)->get();
return $form->get_setting('title');
* Set start and end dates to filter submissions
* @param int|null $startDate Starting date
* @param int|null $endDate Ending date
public function setDateParameters($startDate = null, $endDate = null) {
if (!is_null($startDate)) {
$this->startDate = $this->formatDate($startDate);
if (!is_null($endDate)) {
$this->endDate = $this->formatDate($endDate);
* Set parameter to filter submissions by `isUnread` = true or false
public function setIsUnreadParameter(bool $isUnread=null)/* :SubmissionCollectionInterface */ {
$this->isUnread = $isUnread;
* Set parameter to filter submissions by `previouslyExported` = true or false
* @param bool $previouslyExported
public function setPreviouslyExportedParameter(bool $previouslyExported=null)/* :SubmissionCollectionInterface */ {
$this->previouslyExported = $previouslyExported;
* Set max number of submissions to return in a request
* @param int $maxReturnCount
public function setMaxReturnCount($maxReturnCount=null)/* :SubmissionCollectionInterface */ {
$this->maxReturnCount = $maxReturnCount;
* Set all parameters using NF_Database_Models_SubmissionCollectionInterfaceParameters
* Using the object ensures all properties are set, with known defaults;
* this enables the requesting class to set only values that concerns it
* without needing to set any other value or default. The Submission
* Collection class knows that all values have valid paramters and can
* immediately run the filter.
* @param NF_Database_Models_SubmissionCollectionInterfaceParameters $params
* @return SubmissionCollectionInterface
public function filterByParameters(/* NF_Database_Models_SubmissionCollectionInterfaceParameters*/ $params)/* :SubmissionCollectionInterface */ {
/** @var NF_Database_Models_SubmissionCollectionInterfaceParameters $params */
$this->setDateParameters($params->getStartDate(),$params->getEndDate());
$this->setIsUnreadParameter($params->getIsUnread());
$this->setPreviouslyExportedParameter($params->getPreviouslyExported());
$this->setMaxReturnCount($params->getMaxReturnCount());
$this->setHiddenFieldTypes($params->getHiddenFieldTypes());
$this->filterSubmissions();
* Filter collection of submissions based on previously set parameters
public function filterSubmissions()/* :SubmissionCollectionInterface */ {
$defaultFilter = $this->constructDefaultFilter();
$filter = $this->addMetaFilters($defaultFilter);
// set max number values to return
if (!is_null($this->maxReturnCount)) {
$filter['posts_per_page'] = $this->maxReturnCount;
$dateQuery = $this->constructDateQuery();
if (!empty($dateQuery)) {
$filter['date_query'] = $dateQuery;
$subs = get_posts($filter);
$this->submissionCollection = [];
foreach ($subs as $sub) {
$this->submissionCollection[$sub->ID] = new SingleSubmission($sub->ID);
* Return count of submissions, exported, and unread
public function getCounts():array {
$defaultFilter = $this->constructDefaultFilter();
$subs = get_posts($defaultFilter);
foreach ($subs as $sub) {
$singleSubmission = new SingleSubmission($sub->ID);
$allSubmissions[] = $singleSubmission->getId();
if ($singleSubmission->wasExported()) {
$previouslyExported[] = $singleSubmission->getId();
if ($singleSubmission->isUnread()) {
$isUnread[] = $singleSubmission->getId();
'totalCount' => count($allSubmissions),
'previouslyExported' => count($previouslyExported),
'isUnread' => count($isUnread)
protected function addMetaFilters($filter)/* :array */ {
// add previously exported criterion to meta query
$previouslyExportedQuery = $this->constructPreviouslyExportedQuery();
if (!empty($previouslyExportedQuery)) {
$filter['meta_query'][] = $previouslyExportedQuery;
// add is unread criterion to meta query
$isUnreadQuery = $this->constructIsUnreadQuery();
if (!empty($isUnreadQuery)) {
$filter['meta_query'][] = $isUnreadQuery;
// add condition for multiple meta queries
if (1 < count($filter['meta_query'])) {
$filter['meta_query']['relation'] = 'AND';
* Construct/return default filter args array for WP's get_post
protected function constructDefaultFilter()/* :array */ {
'posts_per_page' => -1, // return all
* Construct meta query for isUnread; empty array if null param
protected function constructIsUnreadQuery() {
if (!is_null($this->isUnread)) {
$query['key'] = SingleSubmission::UNREAD_KEY;
$query['compare'] = 'LIKE';
$query['value'] = $this->isUnread;
* Construct meta query for previously exported; empty array if null parameter
* @param bool|null $previouslyExported
protected function constructPreviouslyExportedQuery() {
if (!is_null($this->previouslyExported)) {
$query['key'] = SingleSubmission::EXPORT_TIMESTAMP_KEY;
if ($this->previouslyExported) {
$query['compare'] = 'EXISTS';
$query['compare'] = 'NOT EXISTS';
* Construct meta query for start/end dates; empty array if null parameters
protected function constructDateQuery() {
if (!is_null($this->endDate)) {
$query['before'] = $this->endDate;
if (!is_null($this->startDate)) {
$query['after'] = $this->startDate;
* Return submission collection array
* @return \NF_Database_Models_SingleSubmissionInterface[]
public function getSubmissions()/*: SingleSubmission[]*/ {
if(empty($this->submissionCollection)){
$this->filterSubmissions();
return $this->submissionCollection;
* Return array of submission Ids in the collection
* Generated at time of request to ensure it is up to date after last
public function getSubmissionIds() {
if (!empty($this->submissionCollection)) {
foreach ($this->submissionCollection as $submission) {
$idArray[] = $submission->getId();
* Return array of field labels keyed on field key
* If hiddenFieldTypes array is set, labels filtered to hide those types
* @param bool|null $useAdminLabels
public function getLabels($useAdminLabels = null)/* : array */ {
// if not explicitly requesting admin labels and labels previously
// retrieved, use those, otherwise generate labels array
if (is_null($useAdminLabels) && !empty($this->labels)) {
foreach ($this->fields as $field) {
// omit hidden field types
if (!is_null($this->hiddenFieldTypes) &&
in_array($field->get_setting('type'), $this->hiddenFieldTypes)) {
if ($useAdminLabels && '' !== $field->get_setting('admin_label')) {
$labels[$field->get_setting('key')] = $field->get_setting('admin_label');
$labels[$field->get_setting('key')] = $field->get_setting('label');
* Return array of field types keyed on field key
public function getFieldTypes()/* : array */ {
if (empty($this->fieldTypes)) {
foreach ($this->fields as $field) {
$key = $field->get_setting('key');
$type = $field->get_setting('type');
$this->fieldTypes[$key] = $type;
return $this->fieldTypes;
* Return array of field Ids keyed on field keys
public function getFieldIds()/* :array */{
if (empty($this->fieldIds)) {
foreach ($this->fields as $field) {
$key = $field->get_setting('key');
$this->fieldIds[$key] = $id;