Jump to content

FieldtypeRepeater items accidentally removed from page. How to restore?


Cybermano
 Share

Recommended Posts

Hi everyone.
As per the title, this is the scenario:

I have a main page with a FieldtypeRepeater with 4/5 elements added, where each repeater are called in other pages (linked to the respective repeater by the id: so the pages are url based with their repeater items).

Accidentally, the repeater items were deleted from repeater field on the main page.

(I know what you're thinking... "Accidentally? How is that possible?" 🤣- But please, trust me 😨: I don't know how they are literally "disappeared" from the page...).

 

Actually only the main page has lost someting (a selection based on the deleted repeater ids), but not the other pages.

I suppose if I rebuild the deleted items in the main page from scratch, I will create a big mess in the other pages with the old repeaters and the newer ones.

And deleting all the other pages to rebuild them with the new repeaters is not an option.

 

I already checked in the admin tree and the repeaters are still in /admin/page/repeaters/for-field-XXX/for-page-XXXX/

Any ideas to "relink" those repeaters to the original main page (of course without losing original ids or recoding php templates and functions)?

Is there any "magic" API?

Many thanks in advance.🙏

Edited by Cybermano
Syntax corrections
Link to comment
Share on other sites

At the moment I have tried with:

if($user->isSuperuser()){
    $page->of(false);
    echo $vp = wire('pages')->get('/admin/repeaters/for-field-513/for-page-2905/'); // the admin path where the repeaters are saved
    foreach($vp->children() as $v){
		// Just for checking
        echo '<br/>';
        echo $v->id;

		// add repeaer to the repeater field in the page
        $page->vouchers->add($v);
    }
    $page->save();
    $page->of(true);
}

The echo return the correct ids, but the whole code won't save in page the repeaters...

Link to comment
Share on other sites

14 minutes ago, BitPoet said:

Just to understand right, the repeater field is no longer on the template of your main page, right? (If it isn't, don't add it yet!)

No, the repeater field is never gone away from the template.
Only the repeater items are disappeared...

P.S. Also tryed with this selector (ids are correct):

    $vv = wire('pages')->find('parent=2906, template=230, sort=sort, include=all');

but the foreach doesn't save the items in the field...

 

Link to comment
Share on other sites

11 minutes ago, BitPoet said:

Can you take a look into the database and do a "select * from field_vouchers where pages_id=2906"?

   $q = "SELECT * from field_vouchers where pages_id=2906";
    $statement = wire('database')->query($q);
    $results = $statement->fetchAll(PDO::FETCH_ASSOC);
   
    echo '<pre>';
        var_dump($results);
    echo '</pre>';
result:
array(0) {
}

Is it possible?

 

also this query has empty data:

    $field = $fields->get('vouchers');
    $table = $field->getTable();
    $q = "SELECT * from $table";
    $statement = wire('database')->query($q);
    $results = $statement->fetchAll(PDO::FETCH_ASSOC); 
    echo '<pre>';
        var_dump($results);
    echo '</pre>';

// Output
array(1) {
  [0]=>
  array(4) {
    ["pages_id"]=>
    string(4) "2905"
    ["data"]=>
    string(0) ""
    ["count"]=>
    string(1) "0"
    ["parent_id"]=>
    string(4) "2906"
  }
}
	

P.S. Many thanks for your interest.

Link to comment
Share on other sites

That's okay. I just wanted to be sure that it's actually empty and not filled with incorrect data. Since the pages still exists, this little snipped should do the trick:

if($user->isSuperuser()) {

	$repeaterParent = $pages->get('/admin/repeaters/for-field-513/for-page-2905/');

	$repeaterOwner = 2905;

	$sth = $database->prepare(
		'insert into field_voucher ' .
		'(pages_id, data, count, parent_id) ' .
		'values ' .
		'(:page, :repeaters, :count, :repparent)'
	);
	
	$params = [
		':page'			=>	$repeaterOwner,
		':repeaters'	=>	$repeaterParent->children()->implode(',', 'id'),
		':count'		=>	$repeaterParent->children()->count(),
		':repparent'	=>	$repeaterParent
	];

	$sth->execute($params);

	echo "<pre>Inserted repeater</pre>";
}

 

  • Like 2
Link to comment
Share on other sites

5 minutes ago, BitPoet said:

That's okay. I just wanted to be sure that it's actually empty and not filled with incorrect data. Since the pages still exists, this little snipped should do the trick:

if($user->isSuperuser()) {

	$repeaterParent = $pages->get('/admin/repeaters/for-field-513/for-page-2905/');

	$repeaterOwner = 2905;

	$sth = $database->prepare(
		'insert into field_voucher ' .
		'(pages_id, data, count, parent_id) ' .
		'values ' .
		'(:page, :repeaters, :count, :repparent)'
	);
	
	$params = [
		':page'			=>	$repeaterOwner,
		':repeaters'	=>	$repeaterParent->children()->implode(',', 'id'),
		':count'		=>	$repeaterParent->children()->count(),
		':repparent'	=>	$repeaterParent
	];

	$sth->execute($params);

	echo "<pre>Inserted repeater</pre>";
}

 

Ok thanks, something it's moving... but:

Yikes… Error: Exception: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2905' for key 'field_vouchers.PRIMARY' (in wire/core/WireDatabasePDOStatement.php line 168)

I've only changed field_voucher in field_vouchers (plural is the correct name)
 

Link to comment
Share on other sites

Oh, sorry. I've gotten turned around a bit here without noticing it. I must have looked too long at this line when I assembled the sql query:

    $vv = wire('pages')->find('parent=2906, template=230, sort=sort, include=all');

The sql query with "2906" I had you do was wrong then and should have been 'select * from field_vouchers where pages_id=2905'. Can you run that again? Since there's still data there, let's take a look at what that is before I jump to conclusions (supposedly empty, but who knows, since it shouldn't have gotten into this state at all).

  • Like 1
Link to comment
Share on other sites

5 minutes ago, BitPoet said:

Oh, sorry. I've gotten turned around a bit here without noticing it. I must have looked too long at this line when I assembled the sql query:

    $vv = wire('pages')->find('parent=2906, template=230, sort=sort, include=all');

The sql query with "2906" I had you do was wrong then and should have been 'select * from field_vouchers where pages_id=2905'. Can you run that again? Since there's still data there, let's take a look at what that is before I jump to conclusions (supposedly empty, but who knows, since it shouldn't have gotten into this state at all).

Thanks: the query with 2095 it's also empty, but the second query to force inoculating the repeaters, performs again the same exception:

 Ouch… Error: Exception: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2905' for key 'field_vouchers.PRIMARY' (in wire/core/WireDatabasePDOStatement.php line 168)

Link to comment
Share on other sites

7 minutes ago, Cybermano said:

Thanks: the query with 2095 it's also empty, but the second query to force inoculating the repeaters, performs again the same exception:

 Ouch… Error: Exception: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2905' for key 'field_vouchers.PRIMARY' (in wire/core/WireDatabasePDOStatement.php line 168)

Ok, maybe I didn't get it: I run the second query with $repeaterOwner = 2906;
Your "<pre>" line appears with non other errors, but no repeater items are in page 2905.

 

To be more clear:

Public page with repeater field = id 2905

Admin page (container of repeater) = id 2906

 

Thanks for your time, and sorry because I'm not so keen on db queries... 🙂

I beg your pardon, but I have to go out from office: I will follow from home.

 

Link to comment
Share on other sites

30 minutes ago, Cybermano said:

Ok, maybe I didn't get it: I run the second query with $repeaterOwner = 2906;
Your "<pre>" line appears with non other errors, but no repeater items are in page 2905.

 

To be more clear:

Public page with repeater field = id 2905

Admin page (container of repeater) = id 2906

$repeaterOwner should be the public page (i.e. 2905), so you now just created a superfluous entry in field_vouchers. You can delete that with 'delete from field_vouchers where pages_id=2906'. What stumps me is that a select on field_vouchers with pages_id 2905 returns an empty result, yet you still get the primary key error. Off the top of my head, I can only think of two scenarios where this could happen
(a) your table's index got corrupted somehow, or
(b) you're using InnoDB and there's an open transaction that should have inserted the row in question but hasn't sent a commit yet.

To be on the safe side, you should probably export your repeater items and for-page-2905 using PagesExportImport and store that. This lets you recreate your repeater pages with identical ids even if PW decides to throw them away at some point.

Afterwards, you can try running the SQL query 'check table field_vouchers' and see if the result shows any errors.

  • Like 2
Link to comment
Share on other sites

3 hours ago, BitPoet said:

$repeaterOwner should be the public page (i.e. 2905), so you now just created a superfluous entry in field_vouchers. You can delete that with 'delete from field_vouchers where pages_id=2906'. What stumps me is that a select on field_vouchers with pages_id 2905 returns an empty result, yet you still get the primary key error. Off the top of my head, I can only think of two scenarios where this could happen
(a) your table's index got corrupted somehow, or
(b) you're using InnoDB and there's an open transaction that should have inserted the row in question but hasn't sent a commit yet.

To be on the safe side, you should probably export your repeater items and for-page-2905 using PagesExportImport and store that. This lets you recreate your repeater pages with identical ids even if PW decides to throw them away at some point.

Afterwards, you can try running the SQL query 'check table field_vouchers' and see if the result shows any errors.

Thank for your patience, and sorry for my mistakes (I'm not skilled in dbs and I have the terror to destroy some/everything...).

As far I know, we are using MySQL and never had problems on our PW installations: I will check next days with coworkers of mine because I'm suerly closer to a code monkey than a webmaster.

I already tried the way to export and import again all the tree structure from the parent, but with no luck. Both from the same server and from a weekly backup one where the repeaters are intact. No repeater items are imported in the public page.

At this point I think the solution is to sync backwards the backup server to the developing one that we are using. But we will check tomorrow with clear minds.

In the meanwhile I'll try to check with your latest hints and I will let you know.

Thank you for your time: very very appreciated.
 

Link to comment
Share on other sites

6 minutes ago, Cybermano said:

Thank for your patience, and sorry for my mistakes (I'm not skilled in dbs and I have the terror to destroy some/everything...).

As far I know, we are using MySQL and newer had problems on our PW installations: I will check next days with coworkers of mine because I'm suerly closer to a code monkey than a webmaster.

I already tried the way to export and import again all the tree structure from the parent, but with non luck. Both from the same server and from a weekly backup one where the repeaters are intact. No repeater items are imported in the public page.

At this point I think the solution is to sync backwards the backup server to the developing one that we are using. But we will check tomorrow with clear minds.

In the meanwhile I'll try to check with your latest hints and I will let you know.

Thank you for your time: very very appreciated.
 

Check on table is ok:

  $q = "check table field_vouchers";
    $statement = wire('database')->query($q);
    $results = $statement->fetchAll(PDO::FETCH_ASSOC); 
    echo '<pre>';
        var_dump($results);
    echo '</pre>';

// dump result
array(1) {
  [0]=>
  array(4) {
    ["Table"]=>
    string(29) "vouchers_newmc.field_vouchers"
    ["Op"]=>
    string(5) "check"
    ["Msg_type"]=>
    string(6) "status"
    ["Msg_text"]=>
    string(2) "OK"
  }
}

 

Link to comment
Share on other sites

  • Cybermano changed the title to FieldtypeRepeater items accidentally removed from page. How to restore?

In the meantime, I have packed the backup site with its db, that looks correct.

Looking into page differences, I've found that if I add a new item in the repeater field on the main page, this item uses a new template for the repeater:

"repeater_vouchers1" instead of the original "repeater_vouchers". New template is created yesterday.

image.thumb.png.d0da53c6aac02a065d46b51ee718d8f7.png

Obviously the php code doesn't extract nothing, becuse all the selectors points to "template=repeater_vouchers, ... "

But if I delete this item from the main page, it is deleted also from the admin for-page-XXXX container.

This did not happen for the original articles... Very strange.

 

For completeness, these updates were made yesterday:

586315343_ModuleUpgrades.thumb.png.da5a1ce640fb7b9f280ee4379ef8d5ad.png
The only one I think might have affected is core 3.0.210 (updated to migrate to TinyMCE): current repeater field is a FieldTypeRepeater, not the Matrix bundeled with pro ones.

 

01/06 - 10:44
Just finished to apply the same upgrades, step by step with double check on backup version of the site and all is fine: no repeater problems...

 

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...