PHPackages                             naoned/oai-pmh-server-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. naoned/oai-pmh-server-bundle

ActiveBundle[API Development](/categories/api)

naoned/oai-pmh-server-bundle
============================

Bundle for Symfony2 that provides an Oai-Pmh server for your data

0.0.2(9y ago)72598[3 PRs](https://github.com/naoned/OaiPmhServerBundle/pulls)MITPHPPHP &gt;=5.4|~7.0

Since Jul 15Pushed 6y ago14 watchersCompare

[ Source](https://github.com/naoned/OaiPmhServerBundle)[ Packagist](https://packagist.org/packages/naoned/oai-pmh-server-bundle)[ RSS](/packages/naoned-oai-pmh-server-bundle/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (2)Dependencies (2)Versions (4)Used By (0)

OaiPmhServerBundle
==================

[](#oaipmhserverbundle)

About
-----

[](#about)

Provides an Oai-Pmh server to serve your data. This is an Oai-Pmh server only, you have to plug your own data provider.

Features
--------

[](#features)

- Compliant with official Oai-Pmh tech spec :
- Sucessfully pass  test
- Automated resumption in large list, with arrays or ArrayObject
- On the fly XML generation, if you provide Records in a real-time data-accesing ArrayObject
- Parametrable resumption items-per-page (default at 50)

Limitations
-----------

[](#limitations)

- Does not supports resumption (by token) on set lists
- More data formats (currently supports Dublin Core only)

Installation
------------

[](#installation)

Require the `naoned/OaiPmhServer` package in your composer.json and update your dependencies.

```
$ composer require naoned/OaiPmhServer:*

```

Add the NaonedOaiPmhServerBundle to your application's kernel:

```
    public function registerBundles()
    {
        $bundles = array(
            ...
            new Naoned\OaiPmhServer\NaonedOaiPmhServerBundle(),
            ...
        );
        ...
    }
```

Configuration
-------------

[](#configuration)

Add to your config.yml

```
naoned_oai_pmh_server:
    data_provider_service_name: naoned.oaipmh.data_provider
    count_per_load: 50
```

You can choose here nb of records and sets in list with resumption

Add to your routing.yml

```
naoned_oai_pmh_server:
    resource: "@NaonedOaiPmhServerBundle/Resources/config/routing.yml"
    prefix:   /oaipmh
```

You can choose here route to your Oai-Pmh server

Add to your services.yml In your own Bundle (that manage data), add a service to expose data

```
    naoned.oaipmh.data_provider:
        class: [YOUR_VENDOR]\[YOUR_BUNDLE]\[YOUR_PATH]\[YOUR_CLASS]
        calls:
            - [ setContainer, ["@service_container"] ]
```

Create Data provider
--------------------

[](#create-data-provider)

Fournishing data is up to you. That’s why you have to define a service. In order to do it, create on your side a class based on this example :

```
namespace [YOUR_VENDOR]\[YOUR_BUNDLE]\[YOUR_PATH];

use Naoned\OaiPmhServerBundle\DataProvider\DataProviderInterface;
use Symfony\Component\DependencyInjection\ContainerAware;

class [YOUR_CLASS] extends ContainerAware implements DataProviderInterface
{
    /**
     * @return string Repository name
     */
    public function getRepositoryName()
    {
        return 'My super Oai-Pmh Server';
    }

    /**
     * @return string Repository admin email
     */
    public function getAdminEmail()
    {
        return 'me@home.com';
    }

    /**
     * @return \DateTime|string     Repository earliest update change on data
     */
    public function getEarliestDatestamp()
    {
        return "2015-01-01";
    }

    /**
     * @param  string $identifier [description]
     * @return array
     */
    public function getRecord($identifier)
    {
        return array(
            'title'       => 'Dummy content',
            'description' => 'Some more dummy content',
            'sets'        => array('seta', 'setb'),
        );
    }

    /**
     * must return an array of arrays with keys «identifier» and «name»
     * @return array List of all sets, with identifier and name
     */
    public function getSets()
    {
        return array(
            array(
                'identifier' => 'seta',
                'name'       => 'THE set number A',
            ),
            array(
                'identifier' => 'setb',
                'name'       => 'THE set identified by B',
            )
        );
    }

    /**
     * Search for records
     * @param  String|null    $setTitle Title of wanted set
     * @param  \DateTime|null $from     Date of last change «from»
     * @param  \DataTime|null $until    Date of last change «until»
     * @return array|ArrayObject        List of items
     */
    public function getRecords($setTitle = null, \DateTime $from = null, \DataTime $until = null)
    {
        return array(
            array(
                'identifier'  => '1W1',
                'title'       => 'Dummy content 1',
                'description' => 'Some more dummy content',
                'last_change' => '2015-10-12',
                'sets'        => array('seta', 'setb'),
            ),
            array(
                'identifier'  => '1W2',
                'title'       => 'Dummy content 2',
                'description' => 'Some more dummy content',
                'last_change' => '2015-10-12',
                'sets'        => array('seta'),
            ),
            array(
                'identifier'  => '1W3',
                'title'       => 'Dummy content 3',
                'description' => 'Some more dummy content',
                'last_change' => '2015-10-12',
                'sets'        => array('seta'),
            ),
            array(
                'identifier'  => '1W4',
                'title'       => 'Dummy content 4',
                'description' => 'Some more dummy content',
                'last_change' => '2015-10-12',
                'sets'        => array('setc'),
            ),
            array(
                'identifier'  => '1W5',
                'title'       => 'Dummy content 5',
                'description' => 'Some more dummy content',
                'last_change' => '2015-10-12',
                'sets'        => array('setd'),
            ),
        );
    }

    /**
     * Tell me, this «record», in which «set» is it ?
     * @param  any   $record An item of elements furnished by getRecords method
     * @return array         List of sets, the record belong to
     */
    public function getSetsForRecord($record)
    {
        return $record['sets'];
    }

    /**
     * Transform the provided record in an array with Dublin Core, «dc_title»  style
     * @param  any   $record An item of elements furnished by getRecords method
     * @return array         Dublin core data
     */
    public static function dublinizeRecord($record)
    {
        return array(
            'dc_identifier'  => $record['identifier'],
            'dc_title'       => $record['title'],
            'dc_description' => $record['description'],
        );
    }

    /**
     * Check if sets are supported by data provider
     * @return boolean check
     */
    public function checkSupportSets()
    {
        return true;
    }

    /**
     * Get identifier of id
     * @param  any   $record An item of elements furnished by getRecords method
     * @return string        Record Id
     */
    public static function getRecordId($record)
    {
        return $record['identifier'];
    }

    /**
     * Get last change date
     * @param  any   $record An item of elements furnished by getRecords method
     * @return \DateTime|string     Record last change
     */
    public static function getRecordUpdated($record)
    {
        return $record['last_change'];
    }
}
```

If you use Symfony &gt;= 2.8, use ContainerAwareTrait instead of extending ContainerAware :

```
namespace [YOUR_VENDOR]\[YOUR_BUNDLE]\[YOUR_PATH];

use Naoned\OaiPmhServerBundle\DataProvider\DataProviderInterface
use Symfony\Component\DependencyInjection\ContainerAwareTrait;

class [YOUR_CLASS] implements DataProviderInterface
{
    use ContainerAwareTrait;

    ...
}
```

Of course, you have to implement data retreiveing here, based on anything : db (Sql), mappers (Doctrine, Pomm) or any other data storing (ElasticSearch …). That why I made this class container aware, but you can preferely set required services via setters.

In addition, lists (records ans sets) can be sent as ArrayObjects, in order to manage data calling in an other class that implements `\ArrayObject`.

###  Health Score

29

—

LowBetter than 59% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity20

Limited adoption so far

Community20

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 86.4% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~608 days

Total

2

Last Release

3353d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/3ed31f698a3aa64fdcca4cefb364eb9db73a5e8f27d35259561002671f2e2936?d=identicon)[sinaoned](/maintainers/sinaoned)

---

Top Contributors

[![vbeauvivre](https://avatars.githubusercontent.com/u/5468590?v=4)](https://github.com/vbeauvivre "vbeauvivre (51 commits)")[![sglorian](https://avatars.githubusercontent.com/u/6449127?v=4)](https://github.com/sglorian "sglorian (4 commits)")[![db4y](https://avatars.githubusercontent.com/u/5930927?v=4)](https://github.com/db4y "db4y (1 commits)")[![dragonito](https://avatars.githubusercontent.com/u/1980412?v=4)](https://github.com/dragonito "dragonito (1 commits)")[![mcharron](https://avatars.githubusercontent.com/u/6449337?v=4)](https://github.com/mcharron "mcharron (1 commits)")[![vcollignon](https://avatars.githubusercontent.com/u/4736786?v=4)](https://github.com/vcollignon "vcollignon (1 commits)")

---

Tags

OAI-PMHoaipmh

### Embed Badge

![Health badge](/badges/naoned-oai-pmh-server-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/naoned-oai-pmh-server-bundle/health.svg)](https://phpackages.com/packages/naoned-oai-pmh-server-bundle)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
