Unable to index docs using bufferedadd plugin in solarium - solr

I am using solarium to implement a solr search. I need to index my files into solr. I am using the following code to do so.
require('init.php');
use Solarium\Plugin\BufferedAdd\Event\Events;
use Solarium\Plugin\BufferedAdd\Event\PreFlush as PreFlushEvent;
use Solarium\Plugin\BufferedAdd\Event\PostCommit as PostCommitEvent;
/////////////////This function adds the knowledge maps to solr//////////////////////////////
$results_index = query(" select indexed_id from update_solr WHERE table_name='knowledgemaps'");
$results = query(" select m_id,k_id, m_title, m_des from knowledgemaps WHERE k_id>{$results_index[0]['indexed_id']}");
$client = new Solarium\Client($config);
$buffer = $client->getPlugin('bufferedadd');
$buffer->setBufferSize(10);
for($i=0;$i<count($results);$i++) {
// also register an event hook to display what is happening
$client->getEventDispatcher()->addListener(
Events::PRE_FLUSH,
function (PreFlushEvent $event) {
echo 'Flushing buffer (' . count($event->getBuffer()) . 'docs)<br/>';
}
);
// Create a document
$doc = array();
$doc["map_id"]=$results[$i]["m_id"];
$doc["user_id"]=$results[$i]["k_id"];
$doc["map_title"]=$results[$i]["m_title"];
if(isset($results[$i]["m_des"])&&is_null($results[$i]["m_des"])){
$doc["map_des"]=$results[$i]["m_des"];
}
$buffer->createDocument($doc);
}
$buffer->flush();
When I execute the code i do not get any errors. It give the number of flushes documents as correct. But no data is getting indexed in solr.
Is there some additional code required to index the information

You need probably still need to commit the changes, you can do this by replacing the last flush call with commit.

Related

CakePHP How to create pagination from API JSON data source

I have an API like example
I have used cakephp HTTP client to get data, below my attempted code
public index()
{
$http = new Client();
$response = $http->get('https://restcountries.eu/rest/v2/all');
// $json = $response->getJson(); //also tried usgin json
$countries = $this->paginate($response);
$this->set(compact('countries '));
}
I am trying to apply pagination with this country data then fetch it in view with pagination.
After tried above code , I have gotten below error
Argument 1 passed to Cake\Datasource\Paginator::extractData() must be an instance of Cake\Datasource\RepositoryInterface, instance of Cake\Http\Client\Response given, called in \myapp\vendor\cakephp\cakephp\src\Datasource\Paginator.php on line 176
How can I get my desire result ?
You have probably need to implement a class who extend RepositoryInterface.
class JsonSource implements Cake\Datasource\RepositoryInterface
{ ... }
public index() {
$http = new Client();
$response = $http->get('https://restcountries.eu/rest/v2/all');
$src = new JsonSource();
$src->fromResponse($response);
$countries = $this->paginate($src);
$this->set(compact('countries ')); }
Is a bit tedious, because you need to define Json like a datasource.
The default pagination only supports querying tables (repositories), or operating on pre-built query instances.
To extend on #Zeppi's answer. You basically have three somewhat straightforward options here:
Create custom query/repository implementations as hinted by #Zeppi.
This can indeed be quite a lot of work though, so you might want to look into alternatively implementing it with the help of plugins, for example muffin/webservice, which does most of the hard work of implementing the required interfaces.
Or create a custom paginator that actually accepts and works on array data.
Or use what is widely know as a "datatable", that is a JavaScript based table in the frontend that paginates the data, for example jQuery DataTables.

CakePHP 3: get a list of all table objects

I'm looking for a way to get a list of all available table objects. These are all the classes that are (by default) located under App/Modal/Table and that are handled by TableRegistry. How to get a list of all those objects?
I know it's possible to fetch all tables of the db:
$tables = ConnectionManager::get('default')->schemaCollection()->listTables();
And then using TableRegistry::get() to get the table object.
But this is not possible for my solution, because there are two cases where this does not work:
custom table names that are different to the table object name
plugin table objects
Any ideas?
Edit: Why? I need all table objects that use a behavior X. In my case a custom SearchableBehavior, which updates a searchindex table on each afterSave event for the saved entity. To update the searchindex for all entities of all tables, I need to know which tables are using the SearchableBehavior and call their update method manually.
$tables = glob(APP."Model".DS."Table".DS."*Table.php");
$tablesNames = [];
foreach ($tables as $name){
$item = explode('Table.php', basename($name));
$tablesNames[] = $item[0];
}
pr(tablesNames);
Write an event listener that listens on Model.initialize and then do a check on the subject, which is the table object if the table has your behavior. Then do something with that list.
If this doesn't work for you - you give zero background info - iterate over the apps Model/Table folder and plugin folder and the vendor folders and search for Model folders and check for *Table.php files. Then try to instantiate the table objects based on the path / namespace and filename and check the models. But this is not very fast, you should cache the resulting list.
I recently had a similar use case, where I needed to access all Table Objects, to initialize the data in the database once, in a console command.
I did it by first building an array of all the paths where the Table Object Classes could reside, then iterating over all files and using the ones ending in "Table.php". Note that this approach might need to be modified slightly depending on your use case.
<?php
use Cake\Core\Plugin;
use Cake\ORM\TableRegistry;
use Cake\Filesystem\Folder;
// Building an array of all possible paths. Firstly the src directory:
$tableClassPaths = [
APP . 'Model' . DS . 'Table' . DS,
];
// Secondly, all loaded plugins:
foreach(Plugin::loaded() as $plugin) {
$dir = Plugin::classPath($plugin) . 'Model' . DS . 'Table' . DS;
if(is_dir($dir)) {
$tableClassPaths[$plugin] = $dir;
}
}
// Iterating over each file in each folder.
$tableObjects = [];
foreach($tableClassPaths as $plugin => $dir) {
foreach(new \FilesystemIterator($dir) as $file) {
// All Files ending in Table.php might be relevant
if($file instanceof \SplFileInfo && $file->isFile()
&& mb_substr($file->getFilename(), -9) === 'Table.php'
) {
$className = mb_substr($file->getFilename(), 0, -9);
if(is_string($plugin)) {
$className = $plugin . '.' . $className;
}
$tableObject = TableRegistry::getTableLocator()->get($className);
// Here you can use / filter the Tables, for example by checking for the presence of a behavior "Indexable":
if($tableObject->hasBehavior('Indexable')) {
$tableObjects[] = $tableObject;
}
}
}
}
?>
Keep in mind, that this is only really suitable for very narrow circumstances, since this completely sidesteps the regular MVC patterns of CakePHP.

Drupal 7 Unable to clear view cache in custom module

I have a view and it is responding fine for the filters I give. However when I run this multiple times in a for loop in my module, I get the same response for whichever filter I apply.
I searched the web and found code to turn off view caching. I have also disabled views data caching from structure->views->settings->advanced. But that is not working.
Below is the example code:
foreach ($term_ids as $term_id) {
$view2 = test_generate_view($view_name, $display_handler, $page, $count, $term_id);
echo "<pre>";
print_r($view2);
}
function test_generate_view($view_name, $display_handler, $page, $count, $term_id = null) {
$view = views_get_view($view_name, TRUE);
$view->set_display($display_handler);
if (!empty($term_id)) {
$term_item = $view->get_item($display_handler, 'filter', 'field_ref_issue_target_id');
$term_item['value']['value'] = $term_id;
$view->set_item($display_handler, 'filter', 'field_ref_issue_target_id', $term_item);
}
$view->init_pager();
$view->pager['items_per_page'] = $count;
$view->pager['use_pager'] = true;
$view->display_handler->options['use_pager'] = true;
$view->set_items_per_page($count);
$view->pager['current_page'] = $page;
$view->is_cacheable = FALSE;
$view->pre_execute();
$view->execute();
return $view;
}
If I don't run them in a loop and try separately for every term-id its working fine. But if I run them in a loop like above, the output is same for any term-id.
The code doesn't look so bad and because the filter changes, the caching should deliver a different result even if turned on. Because the code is working without the loop, maybe you should look into that. is $term_ids really an array of integer values or an array of term objects? If so, the function call would fall back to default which is null for term_ids and would not add a filter.
By the way: You should have a look at contextual filters which you can use really easily.

Trying to write a simple Joomla plugin

Please help, this is my first plugin I'm writing and I'm completely lost. I'm trying to write and update information in a table in a joomla database using my custom giveBadge() function. The functions receives two different variables, the first variable is the $userID and the second one is the digit 300 which I pass at the bottom of the class using giveBadge(300). At the same comparing the $userID in the Joomla database to ensure that the number 300 is given to the current user logged in the Joomla site.
Thanks in advance.
<?php
defined('JPATH_BASE') or die;
class plgUserBadge extends JPlugin
{
public function onUserLogin () {
$user =& JFactory::getUser();
$userID =& user->userID;
return $userID;
}
public function giveBadge ($userID, &$badgeID) {
// Get a db connection.
$db = JFactory::getDbo();
// Create a new query object.
$query = $db->getQuery(true);
// Fields to update.
$fields = array(
'profile_value=\'Updating custom message for user 1001.\'',
'ordering=2');
// Conditions for which records should be updated.
$conditions = array(
'user_id='.$userID,
'profile_key=\'custom.message\'');
$query->update($db->quoteName('#__user_badges'))->set($fields)->where($conditions);
$db->setQuery($query);
try {
$result = $db->query();
} catch (Exception $e) {
// Catch the error.
}es = array(1001, $db->quote('custom.message'), $db->quote('Inserting a record using insert()'), 1);
}
}
giveBadge(300); //attaches to $badgeID
?>
Here is not going well with your code:
You can drop the assign by reference in all your code (&) - you really don't need it, in 99% of the cases.
Use an IDE (for example Eclipse with PDT). At the top of your code you have & user->userID; Any IDE will spot your error and also other things in your code.
Study existing plugins to understand how they work. Here is also the documentation on plugins.
The method onUserLogin() will automatically be called by Joomla when the specific event is triggered (when your plugin is activated). Check with a die("My plugin was called") to see if your plugin is really called
inside onUserLogin() you do all your business logic. You are not supposed to return something, just return true. Right now your method does absolutely nothing. But you can call $this->giveBadge() to move the logic to another method.

Is it safe to do query with Model while in Behavior's BeforeSave callback?

I don't see this documented anywhere, so I ask you, my dear Cake-eaters.
Inside a CakePHP's Behavior::BeforeSave(&$Model) method, I read and write changes to $Model->data array. Before I am finished, I need to read some other records from the database. I am worried that, if I use $Model->find(), it will overwrite the current data within the model, which is about to be saved.
Viewing the source code, the Model::find() function clearly resets the Model::$id variable. This is the same variable I later use to check if a field is being updated.
Here's an example:
<?php
class UniqueBehavior extends ModelBehavior {
function beforeSave(&$Model){
$value = $Model->data[$Model->alias]['unique_field'];
$query = array('conditions' => array('unique_field' => $value));
if ($Model->find('first', $query){
// Does $Model::find() reset the internal $Model->data array?
$Model->data[$Model->alias]['unique_field'] = "..."
//... some other code here
}
//ALSO...
if ($Model->exists()) // Returns true if a record with the currently set ID exists.
$slug = $Model->field('slug');
// this should fetch the slug of the currently updated Model::id from the database
// if I do find()'s, can I trust that the record I'm getting is the right one?
}
}
?>
you can always store the current id in $tmp and assign this stored id back to the model after you are finished
$tmp = $Model->id;
// ...
$Model->id = $tmp;
This way you don't run into problems using the Model-id.
If it is save or not depends on how you work in your model.
I - for example - never rely on this id. I always assign the id to the model manually prior to any update or delete call etc. But this is not necessary, of course. You have to be more careful then, though.

Resources